2012-03-19 83 views
50

如何從UIImage中選擇從UIImagePickerController獲取Exif信息?從UIImage獲取Exif數據 - UIImagePickerController

我爲此做了很多R & D並得到了很多答覆,但仍未能實現這一點。

我已經通過這個thisthis鏈接

請幫我解決這個問題了。

在此先感謝..

+0

看到這個答案。 [解決方案** iOS 8 **](http://stackoverflow.com/a/33672661/1378447)​​ – 2015-11-12 13:42:15

回答

21

我已經找到了解決方案,並得到了答案從here

從這裏我們可以得到GPS信息以及..

驚人的,感謝所有幫助我解決這個問題。

UPDATE

這是我創造了自己的另一個功能,也返回的Exif數據以及GPS數據和這個功能,我們不需要任何第三方庫..但是你必須把爲此提供位置服務。並使用當前的經度和緯度。所以必須使用CoreLocation.framework

//FOR CAMERA IMAGE 

-(NSMutableData *)getImageWithMetaData:(UIImage *)pImage 
{ 
    NSData* pngData = UIImagePNGRepresentation(pImage); 

    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)pngData, NULL); 
    NSDictionary *metadata = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source, 0, NULL); 

    NSMutableDictionary *metadataAsMutable = [[metadata mutableCopy]autorelease]; 
    [metadata release]; 

    //For GPS Dictionary 
    NSMutableDictionary *GPSDictionary = [[[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyGPSDictionary]mutableCopy]autorelease]; 
    if(!GPSDictionary) 
     GPSDictionary = [NSMutableDictionary dictionary]; 

    [GPSDictionary setValue:[NSNumber numberWithDouble:currentLatitude] forKey:(NSString*)kCGImagePropertyGPSLatitude]; 
    [GPSDictionary setValue:[NSNumber numberWithDouble:currentLongitude] forKey:(NSString*)kCGImagePropertyGPSLongitude]; 

    NSString* ref; 
    if (currentLatitude <0.0) 
     ref = @"S"; 
    else 
     ref [email protected]"N"; 
    [GPSDictionary setValue:ref forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; 

    if (currentLongitude <0.0) 
     ref = @"W"; 
    else 
     ref [email protected]"E"; 
    [GPSDictionary setValue:ref forKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; 

    [GPSDictionary setValue:[NSNumber numberWithFloat:location.altitude] forKey:(NSString*)kCGImagePropertyGPSAltitude]; 

    //For EXIF Dictionary 
    NSMutableDictionary *EXIFDictionary = [[[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy]autorelease]; 
    if(!EXIFDictionary) 
     EXIFDictionary = [NSMutableDictionary dictionary]; 

    [EXIFDictionary setObject:[NSDate date] forKey:(NSString*)kCGImagePropertyExifDateTimeOriginal]; 
    [EXIFDictionary setObject:[NSDate date] forKey:(NSString*)kCGImagePropertyExifDateTimeDigitized]; 

    //add our modified EXIF data back into the image’s metadata 
    [metadataAsMutable setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary]; 
    [metadataAsMutable setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary]; 

    CFStringRef UTI = CGImageSourceGetType(source); 

    NSMutableData *dest_data = [NSMutableData data]; 
    CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)dest_data, UTI, 1, NULL); 

    if(!destination) 
     dest_data = [[pngData mutableCopy] autorelease]; 
    else 
    { 
     CGImageDestinationAddImageFromSource(destination, source, 0, (CFDictionaryRef) metadataAsMutable); 
     BOOL success = CGImageDestinationFinalize(destination); 
     if(!success) 
      dest_data = [[pngData mutableCopy] autorelease]; 
    } 

    if(destination) 
     CFRelease(destination); 

    CFRelease(source); 

    return dest_data; 
} 

//FOR PHOTO LIBRARY IMAGE 

-(NSMutableData *)getImagedataPhotoLibrary:(NSDictionary *)pImgDictionary andImage:(UIImage *)pImage 
{ 
    NSData* data = UIImagePNGRepresentation(pImage); 

    CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)data, NULL); 
    NSMutableDictionary *metadataAsMutable = [[pImgDictionary mutableCopy]autorelease]; 

    CFStringRef UTI = CGImageSourceGetType(source); 

    NSMutableData *dest_data = [NSMutableData data]; 

    //For Mutabledata 
    CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)dest_data, UTI, 1, NULL); 

    if(!destination) 
     dest_data = [[data mutableCopy] autorelease]; 
    else 
    { 
     CGImageDestinationAddImageFromSource(destination, source, 0, (CFDictionaryRef) metadataAsMutable); 
     BOOL success = CGImageDestinationFinalize(destination); 
     if(!success) 
      dest_data = [[data mutableCopy] autorelease]; 
    } 
    if(destination) 
     CFRelease(destination); 

    CFRelease(source); 

    return dest_data; 
} 

,我們會找回這樣

//FOR CAMERA IMAGE 
NSData *originalImgData = [self getImageWithMetaData:imgOriginal]; 

//FOR PHOTO LIBRARY IMAGE 
[self getImagedataPhotoLibrary:[[myasset defaultRepresentation] metadata] andImage:imgOriginal]; 

對於這一切,你應該有導入AssetsLibrary.frameworkImageIO.framework數據。

+0

哪裏是currentLatitude來自哪裏?您是在調用UIImagePicker之前從標準CoreLocation調用中設置它,還是直接從返回的圖像中讀取它? – 2012-04-24 14:55:14

+0

CoreLoation在調用UIImagePickerController – 2012-04-25 04:17:33

+0

之前調用ahhh,那麼它可能不準確。您可以調用CoreLocation,調用UIImagePicker,然後在拍攝圖像前將設備物理移動一段距離。您現在將有不準確的經度和緯度。 Drat ... – 2012-04-25 08:48:08

32

有趣的問題!我想出了以下解決方案的圖像時,從你的照片庫中挑選(注意我的代碼使用ARC):

導入AssetsLibrary.frameworkImageIO.framework

然後包括你的.h文件內所需的類:

#import <AssetsLibrary/ALAsset.h> 
#import <AssetsLibrary/ALAssetRepresentation.h> 
#import <ImageIO/CGImageSource.h> 
#import <ImageIO/CGImageProperties.h> 

,並把這個你imagePickerController:didFinishPickingMediaWithInfo:委託方法內:

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 
[library assetForURL:[info objectForKey:UIImagePickerControllerReferenceURL] 
    resultBlock:^(ALAsset *asset) { 

     ALAssetRepresentation *image_representation = [asset defaultRepresentation]; 

     // create a buffer to hold image data 
     uint8_t *buffer = (Byte*)malloc(image_representation.size); 
     NSUInteger length = [image_representation getBytes:buffer fromOffset: 0.0 length:image_representation.size error:nil]; 

     if (length != 0) { 

      // buffer -> NSData object; free buffer afterwards 
      NSData *adata = [[NSData alloc] initWithBytesNoCopy:buffer length:image_representation.size freeWhenDone:YES]; 

      // identify image type (jpeg, png, RAW file, ...) using UTI hint 
      NSDictionary* sourceOptionsDict = [NSDictionary dictionaryWithObjectsAndKeys:(id)[image_representation UTI] ,kCGImageSourceTypeIdentifierHint,nil]; 

      // create CGImageSource with NSData 
      CGImageSourceRef sourceRef = CGImageSourceCreateWithData((__bridge CFDataRef) adata, (__bridge CFDictionaryRef) sourceOptionsDict); 

      // get imagePropertiesDictionary 
      CFDictionaryRef imagePropertiesDictionary; 
      imagePropertiesDictionary = CGImageSourceCopyPropertiesAtIndex(sourceRef,0, NULL); 

      // get exif data 
      CFDictionaryRef exif = (CFDictionaryRef)CFDictionaryGetValue(imagePropertiesDictionary, kCGImagePropertyExifDictionary); 
      NSDictionary *exif_dict = (__bridge NSDictionary*)exif; 
      NSLog(@"exif_dict: %@",exif_dict); 

      // save image WITH meta data 
      NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
      NSURL *fileURL = nil; 
      CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, imagePropertiesDictionary); 

      if (![[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"] isEqualToString:@"public.tiff"]) 
        { 
         fileURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@.%@", 
                  documentsDirectory, 
                  @"myimage", 
                  [[[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"] componentsSeparatedByString:@"."] objectAtIndex:1] 
                  ]]; 

         CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((__bridge CFURLRef)fileURL, 
                        (__bridge CFStringRef)[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"], 
                        1, 
                        NULL 
                        ); 
       CGImageDestinationAddImage(dr, imageRef, imagePropertiesDictionary); 
       CGImageDestinationFinalize(dr); 
       CFRelease(dr); 
      } 
      else 
      { 
       NSLog(@"no valid kCGImageSourceTypeIdentifierHint found …"); 
      } 

      // clean up 
      CFRelease(imageRef); 
      CFRelease(imagePropertiesDictionary); 
      CFRelease(sourceRef); 
     } 
     else { 
      NSLog(@"image_representation buffer length == 0"); 
     } 
    } 
    failureBlock:^(NSError *error) { 
     NSLog(@"couldn't get asset: %@", error); 
    } 
]; 

有一件事我就是注意到了,那iOS會要求的用戶允許定位服務 - 如果他否認,您將無法獲取圖像數據...

編輯

添加代碼以保存圖像,包括其元數據。這是一個快速的方法,所以也許有更好的方法,但它的工作原理!

+0

你能告訴我如何保存圖像後獲得exif數據? – 2012-03-19 09:40:52

+0

+1很酷的答案.. – 2012-03-19 09:44:01

+0

@Marvin查看我的編輯:P – dom 2012-03-19 10:54:10

1

您需要ALAssetsLibrary才能從圖像中實際檢索EXIF信息。僅當EXIF保存到照片庫時纔會將EXIF添加到圖像中。即使您使用ALAssetLibrary從庫中獲取圖像資源,如果將其設置爲UIImage,它也會丟失所有EXIF信息。

0

我曾嘗試將GPS座標插入由iPad相機拍攝的圖像元數據中,正如Mehul所建議的那樣。它工作,感謝您的職位。

P.S. 誰打算使用該代碼,只需分別代替兩個geolocations在函數的頂部 - (NSMutableData *)getImageWithMetaData:(*的UIImage)pImage {

double currentLatitude = [locationManager location].coordinate.latitude; 
double currentLongitude = [locationManager location].coordinate.longitude; 

...

通過假設你已經在你的代碼的某個地方的LocationManager initializied,像這樣:

locationManager = [[CLLocationManager alloc] init]; 
    [locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; 
    [locationManager setDelegate:self]; // Not necessary in this case 
    [locationManager startUpdatingLocation]; // Not neccessary in this case 

,並通過導入CoreLocation/CoreLocation.h和ImageIO的/ ImageIO.h頭以及相關的框架。

28

這些答案似乎都非常複雜。如果圖像已保存到相機膠捲,和你有ALAsset(無論是從UIImagePicker或ALAssetLibrary)即可獲得元數據,像這樣:

asset.defaultRepresentation.metadata; 

如果您想保存從相機膠捲到另一圖像位置(在沙盒/文件說)只是做:

CGImageDestinationRef imageDestinationRef = CGImageDestinationCreateWithURL((__bridge CFURLRef)urlToSaveTo, kUTTypeJPEG, 1, NULL); 
CFDictionaryRef imagePropertiesRef   = (__bridge CFDictionaryRef)asset.defaultRepresentation.metadata; 

CGImageDestinationAddImage(imageDestinationRef, asset.defaultRepresentation.fullResolutionImage, imagePropertiesRef); 
if (!CGImageDestinationFinalize(imageDestinationRef)) NSLog(@"Failed to copy photo on save to %@", urlToSaveTo); 

CFRelease(imageDestinationRef); 
+1

這是一個比2012年答案要好得多的方法。 – broughten 2013-10-18 06:13:12

+1

它還會返回**更多**信息,而不是其他方式:它們不會返回信息存儲在{TIFF}中,如模型,製作,版權,藝術家等。這**應該被標記爲答案! – 2013-12-07 17:02:37

8

我已經使用這個方法從圖像獲取exifdata字典,我希望這也會爲你工作

-(void)getExifDataFromImage:(UIImage *)currentImage 
{ 

    NSData* pngData = UIImageJPEGRepresentation(currentImage, 1.0); 

    CGImageSourceRef mySourceRef = CGImageSourceCreateWithData((CFDataRef)pngData, NULL); 

    //CGImageSourceRef mySourceRef = CGImageSourceCreateWithURL((__bridge CFURLRef)myURL, NULL); 
    if (mySourceRef != NULL) 
    { 
     NSDictionary *myMetadata = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex(mySourceRef,0,NULL); 
     NSDictionary *exifDic = [myMetadata objectForKey:(NSString *)kCGImagePropertyExifDictionary]; 
     NSDictionary *tiffDic = [myMetadata objectForKey:(NSString *)kCGImagePropertyTIFFDictionary]; 
     NSLog(@"exifDic properties: %@", myMetadata); //all data 
     float rawShutterSpeed = [[exifDic objectForKey:(NSString *)kCGImagePropertyExifExposureTime] floatValue]; 
     int decShutterSpeed = (1/rawShutterSpeed); 
     NSLog(@"Camera %@",[tiffDic objectForKey:(NSString *)kCGImagePropertyTIFFModel]); 
     NSLog(@"Focal Length %@mm",[exifDic objectForKey:(NSString *)kCGImagePropertyExifFocalLength]); 
     NSLog(@"Shutter Speed %@", [NSString stringWithFormat:@"1/%d", decShutterSpeed]); 
     NSLog(@"Aperture f/%@",[exifDic objectForKey:(NSString *)kCGImagePropertyExifFNumber]); 


     NSNumber *ExifISOSpeed = [[exifDic objectForKey:(NSString*)kCGImagePropertyExifISOSpeedRatings] objectAtIndex:0]; 
     NSLog(@"ISO %ld",[ExifISOSpeed integerValue]); 
     NSLog(@"Taken %@",[exifDic objectForKey:(NSString*)kCGImagePropertyExifDateTimeDigitized]); 


    } 

}