From the results of UIImagePickerControlleHow, how do I get JPEG with metadata included in it?

时光怂恿深爱的人放手 提交于 2019-12-02 21:23:04

Since I asked the question I have done some more experimentation and think I know the answer now. All results were gotten on iOS 4.2 which is all I care about...

First of all, we were using UIImageJPEGRepresentation ala:

NSData *imageData = UIImageJPEGRepresentation(self.selectedImage, 0.9);

which seems to not give you (much of) the metadata (EXIF, GPS, etc.) that is in the image. Fair enough and I think that's well-known.

My testing shows that the JPEG in the "default representation" for the image asset will contain all the metadata, including EXIF and GPS information (assuming it's there in the first place). You can get that image by going from the asset URL to the Asset to the asset's default representation (ALAssetRepresentation) and then using the getBytes method/message to retrieve the bytes for the JPEG image. That stream of bytes has the aforementioned metadata in it.

Here's some example code that I use for this. It takes an Asset URL, presumed to be for an image, and returns NSData with with the JPEG. Caveat emptor with respect to your use, error handling in the code, etc.

/*
 * 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];
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!