4

给定一个代表照片的 ALAsset,是否可以在不将图像加载到 UIImageView 并且也不使用 aspectRationThumnail 方法的情况下检索照片的大小(高度和宽度)?

4

5 回答 5

14

请注意:iOS 5.1 为 ALAssetRepresentation 实例引入了新的属性维度。这将返回具有原始图像尺寸的 CGSize 结构,并且可能是将来解决此问题的最佳解决方案。

干杯,

亨德里克

于 2012-04-10T10:39:03.067 回答
6
float width = asset.defaultRepresentation.dimensions.width;
float height = asset.defaultRepresentation.dimensions.height;

它快速,稳定,并给出了实际尺寸。我已经将它与 ALAsset 视频一起使用。

于 2014-06-16T13:18:11.943 回答
3

访问图像大小的更简单方法是通过[ALAssetRepresentation metadata]. 在我测试的图像上,它NSDictionary包含名为PixelWidthand的键PixelHeight,它们是NSNumber具有您期望值的对象。

但是,对于您将找到的确切键似乎没有特别的保证,因此请确保您的应用程序可以处理这些键不在元数据中的情况。另请参阅iOS ALAsset 图像元数据,了解有关速度和线程安全的一些注意事项。

比较

我在 iPad 的整个资产库上测试了这两种方法——在 CGImageSourceRef 中加载图像数据或读取元数据。两种方法都在 FLT_EPSILON 中返回相同的大小。除了需要双倍时间的 2 个异常值外,16 次重复的运行时间非常相似:

方法 | 平均时间 +/- 95% 置信度
来自 CGImageSourceRef 的大小 | 0.1787 +/- 0.0004
元数据的大小 | 0.1789 +/- 0.0015

因此,这两种方法都没有性能优势。元数据字典完全可以通过读取图像数据按需构建。

于 2012-04-09T23:36:18.587 回答
2

更新

正如评论中所指出的,这不像最初提供的那样工作。我已经修复了它,但它现在加载了 OP 试图避免的所有图像数据。它仍然避免了将数据解压缩为图像的额外且更糟糕的步骤。

  1. 获取defaultRepresentationALAsset 的。
  2. 获取 ALAssetRepresentation 的数据。
  3. 使用这个方便的 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]];
}
于 2012-04-09T02:30:32.707 回答
-1
float width = CGImageGetWidth(asset.defaultRepresentation.fullResolutionImage);
float height = CGImageGetHeight(asset.defaultRepresentation.fullResolutionImage);

或相同的asset.defaultRepresentation.fullScreenImage...

于 2012-04-10T20:28:46.243 回答