给定一个代表照片的 ALAsset,是否可以在不将图像加载到 UIImageView 并且也不使用 aspectRationThumnail 方法的情况下检索照片的大小(高度和宽度)?
5 回答
请注意:iOS 5.1 为 ALAssetRepresentation 实例引入了新的属性维度。这将返回具有原始图像尺寸的 CGSize 结构,并且可能是将来解决此问题的最佳解决方案。
干杯,
亨德里克
float width = asset.defaultRepresentation.dimensions.width;
float height = asset.defaultRepresentation.dimensions.height;
它快速,稳定,并给出了实际尺寸。我已经将它与 ALAsset 视频一起使用。
访问图像大小的更简单方法是通过[ALAssetRepresentation metadata]
. 在我测试的图像上,它NSDictionary
包含名为PixelWidth
and的键PixelHeight
,它们是NSNumber
具有您期望值的对象。
但是,对于您将找到的确切键似乎没有特别的保证,因此请确保您的应用程序可以处理这些键不在元数据中的情况。另请参阅iOS ALAsset 图像元数据,了解有关速度和线程安全的一些注意事项。
比较
我在 iPad 的整个资产库上测试了这两种方法——在 CGImageSourceRef 中加载图像数据或读取元数据。两种方法都在 FLT_EPSILON 中返回相同的大小。除了需要双倍时间的 2 个异常值外,16 次重复的运行时间非常相似:
方法 | 平均时间 +/- 95% 置信度 来自 CGImageSourceRef 的大小 | 0.1787 +/- 0.0004 元数据的大小 | 0.1789 +/- 0.0015
因此,这两种方法都没有性能优势。元数据字典完全可以通过读取图像数据按需构建。
更新
正如评论中所指出的,这不像最初提供的那样工作。我已经修复了它,但它现在加载了 OP 试图避免的所有图像数据。它仍然避免了将数据解压缩为图像的额外且更糟糕的步骤。
- 获取
defaultRepresentation
ALAsset 的。 - 获取 ALAssetRepresentation 的数据。
- 使用这个方便的 sizeOfImageAtURL函数的改编版。谢谢你,什帕科夫斯基。
下面的代码代表上面的步骤。
// This method requires the ImageIO.framework
// This requires memory for the size of the image in bytes, but does not decompress it.
- (CGSize)sizeOfImageWithData:(NSData*) data;
{
CGSize imageSize = CGSizeZero;
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) data, NULL);
if (source)
{
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:(NSString *)kCGImageSourceShouldCache];
NSDictionary *properties = (__bridge_transfer NSDictionary*) CGImageSourceCopyPropertiesAtIndex(source, 0, (__bridge CFDictionaryRef) options);
if (properties)
{
NSNumber *width = [properties objectForKey:(NSString *)kCGImagePropertyPixelWidth];
NSNumber *height = [properties objectForKey:(NSString *)kCGImagePropertyPixelHeight];
if ((width != nil) && (height != nil))
imageSize = CGSizeMake(width.floatValue, height.floatValue);
}
CFRelease(source);
}
return imageSize;
}
- (CGSize)sizeOfAssetRepresentation:(ALAssetRepresentation*) assetRepresentation;
{
// It may be more efficient to read the [[[assetRepresentation] metadata] objectForKey:@"PixelWidth"] integerValue] and corresponding height instead.
// Read all the bytes for the image into NSData.
long long imageDataSize = [assetRepresentation size];
uint8_t* imageDataBytes = malloc(imageDataSize);
[assetRepresentation getBytes:imageDataBytes fromOffset:0 length:imageDataSize error:nil];
NSData *data = [NSData dataWithBytesNoCopy:imageDataBytes length:imageDataSize freeWhenDone:YES];
return [self sizeOfImageWithData:data];
}
- (CGSize)sizeOfAsset:(ALAsset*) asset;
{
return [self sizeOfAssetRepresentation:[asset defaultRepresentation]];
}
float width = CGImageGetWidth(asset.defaultRepresentation.fullResolutionImage);
float height = CGImageGetHeight(asset.defaultRepresentation.fullResolutionImage);
或相同的asset.defaultRepresentation.fullScreenImage
...