Obtener datos Exif de UIImage – UIImagePickerController

¿Cómo podemos obtener información Exif de UIImage seleccionada de UIImagePickerController?

Hice mucho I + D por esto y obtuve muchas respuestas, pero aún así no pude implementar esto.

Había pasado por esto esto y este enlace

Por favor ayúdame a resolver este problema.

Gracias por adelantado..

¡Interesante pregunta! Se me ocurrió la siguiente solución que funciona para las imágenes recogidas de su biblioteca de fotos (tenga en cuenta que mi código está usando ARC ):

Importar AssetsLibrary.framework y ImageIO.framework .

Luego incluya las clases necesarias dentro de su archivo .h:

 #import  #import  #import  #import  

Y ponga esto dentro de su imagePickerController:didFinishPickingMediaWithInfo: delegue el método:

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

Una cosa que noté es que iOS le pedirá al usuario que permita servicios de localización; si lo niega, no podrá obtener los datos de la imagen …

EDITAR

Se agregó un código para guardar la imagen, incluidos sus metadatos. Es un enfoque rápido, así que tal vez hay una mejor manera, ¡pero funciona!

Todas estas respuestas parecen extremadamente complejas. Si la imagen se ha guardado en el Carrete de la cámara, y usted tiene el ALAsset (ya sea de UIImagePicker o ALAssetLibrary), puede obtener los metadatos así:

 asset.defaultRepresentation.metadata; 

Si desea guardar esa imagen desde el rollo de la cámara a otra ubicación (por ejemplo, en Sandbox / Documents) simplemente haga lo siguiente:

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

Encontré solución y obtuve respuesta de aquí

Desde aquí también podemos obtener información de GPS …

Increíble y gracias a todos por ayudarme a resolver este problema.

ACTUALIZAR

Esta es otra función que yo mismo he creado, también devuelvo datos de Exif y datos de GPS y en esta función no necesitamos ninguna biblioteca de terceros, pero debes activar los servicios de ubicación para esto. y usa la latitud y la longitud actuales para eso. entonces tengo que usar 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 =@"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; } 

y recuperaremos esa información como esta

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

Para todo esto, debería tener que Importar AssetsLibrary.framework e ImageIO.framework .

He usado este método para obtener el diccionario exifdata de la imagen, espero que esto también funcione para usted

 -(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]); } } 

Necesita ALAssetsLibrary para recuperar realmente la información EXIF ​​de una imagen. El EXIF ​​se agrega a una imagen solo cuando se guarda en la Biblioteca de fotos. Incluso si usa ALAssetLibrary para obtener un elemento de imagen de la biblioteca, perderá toda la información EXIF ​​si lo configura en un UIImage.

Intenté insertar coordenadas de GPS en los metadatos de imagen seleccionados por la cámara del iPad, tal como sugirió Mehul. Funciona, gracias por tu publicación.

PD: ¿Quién tiene la intención de usar ese código? Simplemente sustituya las dos geolocalizaciones en la parte superior de la función: (NSMutableData *) getImageWithMetaData: (UIImage *) pImage {

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

Al suponer que ya has inicializado en algún lugar el LocationManager en tu código, así:

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

e importando CoreLocation / CoreLocation.h y ImageIO / Image.h encabezados con marcos asociados.