ImageIO を使って ALAsset の画像のサイズを高速に取得する

iOS 5.1 から、ALAssetRepresentation に dimension プロパティが追加されて、画像のサイズを取得できるようになりました。5.1以前の場合は、自分で画像を取得してサイズを取得する必要がありますが、ImageIOを使うと、画像をすべて読み込まずに取得できる方法があったので紹介します。

参考サイト
iphone – ALAsset Image Size – Stack Overflow
iOS: How to retrieve image dimensions without loading CGImage into memory — Gist

// 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;
{
// iOS5.1以降では、dimensionsプロパティがあるのでそちらを使用する。
if ([assetRepresentation respondsToSelector:@selector(dimensions)]) {
return assetRepresentation.dimensions;
}

// 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]];
}

iOS5.1以降では、dimensionsを直接返すようにしています。また、回転を考慮しないといけないかも知れないのですが、私のケースではサイズを知りたいだけだったので、そこまで考慮していません。また、
[[[assetRepresentation] metadata] objectForKey:@”PixelWidth”] integerValue]を使うことによってサイズを取得できることもありますが、metadataにPixelWidthが入っていないこともあるようで、ImageIOを使う方法にしました。ImageIO フレームワークのImportおよびプロジェクトへの読み込みが必要です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください