2010-11-12 127 views
18

正如你所知,iPhone的指导方针不鼓励加载超过1024x1024的uiimages。访问UIImage属性而不在内存中加载图像

我将不得不加载的图像的大小各不相同,我想检查我即将加载的图像的大小;然而使用uiimage的.size属性需要图像被覆盖......这正是我想要避免的。

我的推理有什么问题吗?或者有解决方案吗?

谢谢大家

+1

这是一个很好的问题。 Android提供了一种手段来做到这一点,但我不知道iOS的解决方案。编辑:这已被问过。 http://stackoverflow.com/questions/1551300/get-size-of-image-without-loading-in-to-memory – Justin 2010-11-12 22:37:09

+0

我之前搜索过,但我找不到它!非常感谢! – koda 2010-11-13 02:05:16

回答

32

由于iOS的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 2012-02-13 04:28:04

+3

因为变量'width'和'height'被声明为'CGFloat',所以在调用CFNumberGetValue()时通过'kCFNumberCGFloatType'而不是'kCFNumberFloatType'是非常重要的。上面的代码可以在32位系统上运行,但是这些值在64位系统上会包含垃圾。 – fjoachim 2013-12-05 08:30:55

+0

@fjoachim:谢谢,修正。 – 2013-12-05 11:42:40

3

斯威夫特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) 
}