Récupérer des données Exif depuis UIImage – UIImagePickerController

Comment pouvons-nous obtenir des informations Exif à partir de UIImage sélectionné à partir de UIImagePickerController?

J’avais fait beaucoup de R & D pour cela et j’ai eu beaucoup de réponses mais je n’ai toujours pas réussi à le mettre en œuvre.

J’avais parcouru ceci ceci et ce lien

S’il vous plaît, aidez-moi à résoudre ce problème.

Merci d’avance..

Question interessante! Je suis arrivé avec la solution suivante en travaillant pour les images sélectionnées dans votre photothèque (notez que mon code utilise ARC ):

Importer AssetsLibrary.framework et ImageIO.framework .

Ensuite, incluez les classes nécessaires dans votre fichier .h:

 #import  #import  #import  #import  

Et mettez ceci dans votre imagePickerController:didFinishPickingMediaWithInfo: méthode délégué:

 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 NSSsortingng *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; NSURL *fileURL = nil; CGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, imagePropertiesDictionary); if (![[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"] isEqualToSsortingng:@"public.tiff"]) { fileURL = [NSURL fileURLWithPath:[NSSsortingng ssortingngWithFormat:@"%@/%@.%@", documentsDirectory, @"myimage", [[[sourceOptionsDict objectForKey:@"kCGImageSourceTypeIdentifierHint"] componentsSeparatedBySsortingng:@"."] objectAtIndex:1] ]]; CGImageDestinationRef dr = CGImageDestinationCreateWithURL ((__bridge CFURLRef)fileURL, (__bridge CFSsortingngRef)[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); } ]; 

Une chose que j’ai remarquée, c’est qu’iOS demandera à l’utilisateur d’autoriser les services de localisation – s’il le nie, vous ne serez pas en mesure d’obtenir les données d’image…

MODIFIER

Ajout de code pour enregistrer l’image, y compris ses métadonnées. C’est une approche rapide, alors peut-être y a-t-il un meilleur moyen, mais ça marche!

Ces réponses semblent toutes extrêmement complexes. Si l’image a été enregistrée sur la pellicule et que vous disposez de ALAsset (à partir de UIImagePicker ou ALAssetLibrary), vous pouvez obtenir les métadonnées comme suit:

 asset.defaultRepresentation.metadata; 

Si vous souhaitez enregistrer cette image depuis un appareil photo vers un autre emplacement (par exemple, Sandbox / Documents), procédez comme suit:

 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); 

J’avais trouvé une solution et obtenu une réponse d’ ici

De là, nous pouvons également obtenir des informations GPS.

Incroyable et merci à tous pour m’aider à résoudre ce problème.

METTRE À JOUR

C’est une autre fonction que j’ai créée moi-même, qui renvoie aussi des données Exif ainsi que des données GPS. Dans cette fonction, nous n’avons besoin d’aucune bibliothèque tierce. Mais vous devez activer les services de localisation pour cela. et utiliser la latitude et la longitude actuelles pour cela. alors faut utiliser 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:(NSSsortingng *)kCGImagePropertyGPSDictionary]mutableCopy]autorelease]; if(!GPSDictionary) GPSDictionary = [NSMutableDictionary dictionary]; [GPSDictionary setValue:[NSNumber numberWithDouble:currentLatitude] forKey:(NSSsortingng*)kCGImagePropertyGPSLatitude]; [GPSDictionary setValue:[NSNumber numberWithDouble:currentLongitude] forKey:(NSSsortingng*)kCGImagePropertyGPSLongitude]; NSSsortingng* ref; if (currentLatitude <0.0) ref = @"S"; else ref =@"N"; [GPSDictionary setValue:ref forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; if (currentLongitude <0.0) ref = @"W"; else ref =@"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; } 

et nous allons récupérer ces données comme ça

 //FOR CAMERA IMAGE NSData *originalImgData = [self getImageWithMetaData:imgOriginal]; //FOR PHOTO LIBRARY IMAGE [self getImagedataPhotoLibrary:[[myasset defaultRepresentation] metadata] andImage:imgOriginal]; 

Pour tout cela, vous devez importer AssetsLibrary.framework et ImageIO.framework .

J’ai utilisé cette méthode pour obtenir le dictionnaire exifdata de l’image, j’espère que cela fonctionnera aussi pour vous

 -(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:(NSSsortingng *)kCGImagePropertyExifDictionary]; NSDictionary *tiffDic = [myMetadata objectForKey:(NSSsortingng *)kCGImagePropertyTIFFDictionary]; NSLog(@"exifDic properties: %@", myMetadata); //all data float rawShutterSpeed = [[exifDic objectForKey:(NSSsortingng *)kCGImagePropertyExifExposureTime] floatValue]; int decShutterSpeed = (1 / rawShutterSpeed); NSLog(@"Camera %@",[tiffDic objectForKey:(NSSsortingng *)kCGImagePropertyTIFFModel]); NSLog(@"Focal Length %@mm",[exifDic objectForKey:(NSSsortingng *)kCGImagePropertyExifFocalLength]); NSLog(@"Shutter Speed %@", [NSSsortingng ssortingngWithFormat:@"1/%d", decShutterSpeed]); NSLog(@"Aperture f/%@",[exifDic objectForKey:(NSSsortingng *)kCGImagePropertyExifFNumber]); NSNumber *ExifISOSpeed = [[exifDic objectForKey:(NSSsortingng*)kCGImagePropertyExifISOSpeedRatings] objectAtIndex:0]; NSLog(@"ISO %ld",[ExifISOSpeed integerValue]); NSLog(@"Taken %@",[exifDic objectForKey:(NSSsortingng*)kCGImagePropertyExifDateTimeDigitized]); } } 

Vous avez besoin d’ALAssetsLibrary pour récupérer les informations EXIF ​​d’une image. L’EXIF est ajouté à une image uniquement lorsqu’il est enregistré dans la photothèque. Même si vous utilisez ALAssetLibrary pour obtenir un élément d’image de la bibliothèque, il perdra toutes les informations EXIF ​​si vous le définissez sur UIImage.

J’ai essayé d’insérer des coordonnées GPS dans les métadonnées d’image sélectionnées par la caméra iPad, comme cela avait été suggéré par Mehul. Ça marche, merci pour votre post

PS Qui a l’intention d’utiliser ce code, il suffit de substituer les deux géolocalisations en haut de la fonction – (NSMutableData *) getImageWithMetaData: (UIImage *) pImage {

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

En supposant que vous avez déjà initialisé quelque part locationManager dans votre code, comme ceci:

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

et en important les en-têtes CoreLocation / CoreLocation.h et ImageIO / ImageIO.h avec les frameworks associés.