2010-11-12 1 views
18

Как вы знаете, принципы iphone препятствуют загрузке изображений, превышающих 1024x1024.доступ к свойствам UIImage без загрузки в память изображения

Размер изображений, которые мне нужно будет загружать, варьируется, и я хотел бы проверить размер изображения, которое я собираюсь загрузить; однако использование свойства .size для uiimage требует, чтобы изображение было laoded ..., что именно то, чего я пытаюсь избежать.

Есть ли что-то не так в моих рассуждениях или есть решение?

спасибо всем

+1

Это хороший вопрос. Android предоставляет средства для этого, но я не знаю решения iOS. EDIT: Это было задано раньше. http://stackoverflow.com/questions/1551300/get-size-of-image-without-loading-in-to-memory – Justin

+0

Я искал раньше, но я не мог найти его! большое спасибо! – koda

ответ

32

С прошивкой 4.0 IOS SDK включает CGImageSource... functions (в рамках ImageIO). Это очень гибкий API для запроса метаданных без загрузки изображения в память. Получение размеров пикселов изображения должны работать, как это (не забудьте включить ImageIO.framework в вашей цели):

#import <ImageIO/ImageIO.h> 

NSURL *imageFileURL = [NSURL fileURLWithPath:...]; 
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageFileURL, NULL); 
if (imageSource == NULL) { 
    // Error loading image 
    ... 
    return; 
} 

CGFloat width = 0.0f, height = 0.0f; 
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); 

CFRelease(imageSource); 

if (imageProperties != NULL) { 

    CFNumberRef widthNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth); 
    if (widthNum != NULL) { 
     CFNumberGetValue(widthNum, kCFNumberCGFloatType, &width); 
    } 

    CFNumberRef heightNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight); 
    if (heightNum != NULL) { 
     CFNumberGetValue(heightNum, kCFNumberCGFloatType, &height); 
    } 

    // Check orientation and flip size if required 
    CFNumberRef orientationNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); 
    if (orientationNum != NULL) { 
     int orientation; 
     CFNumberGetValue(orientationNum, kCFNumberIntType, &orientation); 
     if (orientation > 4) { 
      CGFloat temp = width; 
      width = height; 
      height = temp; 
     } 
    } 

    CFRelease(imageProperties); 
} 

NSLog(@"Image dimensions: %.0f x %.0f px", width, height); 

(адаптировано из «Программирование с кварцем» по Gelphman и Ладеном, листинг 9.5, страница 228)

+2

Зачем использовать 'CGImageSourceCopyPropertiesAtIndex' вместо' CGImageSourceCopyProperties'? – jcm

+3

Очень важно передать 'kCFNumberCGFloatType' вместо' kCFNumberFloatType' при вызове CFNumberGetValue(), поскольку переменные 'width' и' height' объявлены как 'CGFloat'. Приведенный выше код будет работать на 32-битных системах, но значения будут содержать мусор в 64-битных системах. – fjoachim

+0

@fjoachim: Спасибо, исправлено. –

3

Swift 3 вариант ответа:

import Foundation 
import ImageIO 

func sizeForImage(at url: URL) -> CGSize? { 

    guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil) 
     , let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [AnyHashable: Any] 
     , let pixelWidth = imageProperties[kCGImagePropertyPixelWidth as String] 
     , let pixelHeight = imageProperties[kCGImagePropertyPixelHeight as String] 
     , let orientationNumber = imageProperties[kCGImagePropertyOrientation as String] 
     else { 
      return nil 
    } 

    var width: CGFloat = 0, height: CGFloat = 0, orientation: Int = 0 

    CFNumberGetValue(pixelWidth as! CFNumber, .cgFloatType, &width) 
    CFNumberGetValue(pixelHeight as! CFNumber, .cgFloatType, &height) 
    CFNumberGetValue(orientationNumber as! CFNumber, .intType, &orientation) 

    // Check orientation and flip size if required 
    if orientation > 4 { let temp = width; width = height; height = temp } 

    return CGSize(width: width, height: height) 
}