在iOS 4.2上,当我使用UIImagePickerController让用户从照片库中选择一个图像时,这些是返回给我的字典键:
2011-03-02 13:15:59.518 xxx[15098:307] didFinishPickingMediaWithInfo:
info dictionary: {
UIImagePickerControllerMediaType = "public.image";
UIImagePickerControllerOriginalImage = "<UIImage: 0x3405d0>";
UIImagePickerControllerReferenceURL =
"assets-library://asset/asset.JPG?id=1000000050&ext=JPG";
}
使用这些键中的一个或多个,如何获得包含图像元数据(例如曝光信息和GPS位置数据)的JPEG表示,以便我可以在某处上传并包含元数据(不会被剥离) )?
我从Warren Burton在Display image from URL retrieved from ALAsset in iPhone?中非常好的回答中看到如何使用UIImagePickerControllerReferenceURL和ALAssetsLibrary assetForURL方法来获取ALAsset和ALAssetRepresentation。但是,我该怎样做才能获得包含所有元数据的JPEG?
或是否有通过UIImage的机制?
这里的底线是我想要获得包含在其中的元数据的JPEG ...
答案 0 :(得分:7)
因为我问了这个问题,我已经做了一些实验,并认为我现在知道了答案。所有结果都是在iOS 4.2上得到的,这就是我所关心的......
首先,我们使用UIImageJPEGRepresentation
ala:
NSData *imageData = UIImageJPEGRepresentation(self.selectedImage, 0.9);
似乎没有给你(大部分)图像中的元数据(EXIF,GPS等)。很公平,我认为这是众所周知的。
我的测试表明,图像资源的“默认表示”中的JPEG将包含所有元数据,包括EXIF和GPS信息(假设它首先出现在那里)。您可以通过从资产URL到资产到资产的默认表示(ALAssetRepresentation)然后使用getBytes方法/消息来检索JPEG图像的字节来获取该图像。该字节流中包含上述元数据。
这是我用于此的一些示例代码。它需要一个资产URL,假设是一个图像,并返回带有JPEG的NSData。注意你的使用,代码中的错误处理等等。
/*
* Example invocation assuming that info is the dictionary returned by
* didFinishPickingMediaWithInfo (see original SO question where
* UIImagePickerControllerReferenceURL = "assets-library://asset/asset.JPG?id=1000000050&ext=JPG").
*/
[self getJPEGFromAssetForURL:[info objectForKey:UIImagePickerControllerReferenceURL]];
// ...
/*
* Take Asset URL and set imageJPEG property to NSData containing the
* associated JPEG, including the metadata we're after.
*/
-(void)getJPEGFromAssetForURL:(NSURL *)url {
ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
[assetslibrary assetForURL:url
resultBlock: ^(ALAsset *myasset) {
ALAssetRepresentation *rep = [myasset defaultRepresentation];
#if DEBUG
NSLog(@"getJPEGFromAssetForURL: default asset representation for %@: uti: %@ size: %lld url: %@ orientation: %d scale: %f metadata: %@",
url, [rep UTI], [rep size], [rep url], [rep orientation],
[rep scale], [rep metadata]);
#endif
Byte *buf = malloc([rep size]); // will be freed automatically when associated NSData is deallocated
NSError *err = nil;
NSUInteger bytes = [rep getBytes:buf fromOffset:0LL
length:[rep size] error:&err];
if (err || bytes == 0) {
// Are err and bytes == 0 redundant? Doc says 0 return means
// error occurred which presumably means NSError is returned.
NSLog(@"error from getBytes: %@", err);
self.imageJPEG = nil;
return;
}
self.imageJPEG = [NSData dataWithBytesNoCopy:buf length:[rep size]
freeWhenDone:YES]; // YES means free malloc'ed buf that backs this when deallocated
}
failureBlock: ^(NSError *err) {
NSLog(@"can't get asset %@: %@", url, err);
}];
[assetslibrary release];
}