Получите данные Exif от UIImage – UIImagePickerController

Как мы можем получить информацию Exif из UIImage, выбранную из UIImagePickerController?

Я сделал много исследований и разработок для этого и получил много ответов, но до сих пор не смог реализовать это.

Я прошел через это и эту ссылку

Пожалуйста, помогите мне решить эту проблему.

Заранее спасибо..

Интересный вопрос! Я придумал следующее решение для изображений, выбранных из вашей фотобиблиотеки (обратите внимание, что мой код использует ARC ):

Импорт AssetsLibrary.framework и ImageIO.framework .

Затем включите необходимые classы внутри вашего .h-файла:

 #import  #import  #import  #import  

И помещаем это внутри вашего 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); } ]; - 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); } ]; - 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 попросит пользователя разрешить услуги определения местоположения – если он откажется, вы не сможете получить данные изображения …

РЕДАКТИРОВАТЬ

Добавлен код для сохранения изображения, включая его метаданные. Это быстрый подход, поэтому, возможно, есть лучший способ, но он работает!

Эти ответы кажутся чрезвычайно сложными. Если изображение было сохранено в Camera Roll, и у вас есть ALAsset (либо из UIImagePicker, либо ALAssetLibrary), вы можете получить метаданные следующим образом:

 asset.defaultRepresentation.metadata; 

Если вы хотите сохранить это изображение из ролика камеры в другое место (например, в Sandbox / Documents), просто выполните:

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

Я нашел решение и получил ответ отсюда

Отсюда мы также можем получить информацию GPS.

Удивительно и благодарю всех за то, что помог мне решить эту проблему.

ОБНОВИТЬ

Это еще одна функция, которую я создал сам, а также вернуть данные 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.framework и ImageIO.framework .

Я использовал этот метод для получения словаря 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]); } } 

Вам нужна ALAssetsLibrary для фактического извлечения информации EXIF ​​из изображения. EXIF добавляется к изображению только тогда, когда он сохраняется в Фотобиблиотеке. Даже если вы используете ALAssetLibrary для получения ресурса изображения из библиотеки, он потеряет всю информацию EXIF, если вы установите его в UIImage.

Я попытался вставить GPS-координаты в метаданные изображений, выбранные iPad-камерой, как это было предложено Мехулом. Это работает, спасибо за сообщение.

PS Кто намеревается использовать этот код, просто подстройте две геолокации в верхней части функции – (NSMutableData *) getImageWithMetaData: (UIImage *) pImage {

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

Предположим, что вы уже инициализировали где-то locationManager в своем коде, например:

  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 с соответствующими фреймворками.

  • Преимущества, проблемы, примеры добавления другого UIWindow в приложение iOS?
  • Как resize UIModalPresentationFormSheet?
  • Формат NSDate, выводящий неверную дату
  • Есть ли способ удалить разделительную линию из UITableView?
  • Лучший подход для синтаксического анализа XML на iPhone
  • Могу ли я передать блок как @selector с Objective-C?
  • Как я могу получить объект NSDate на сегодня в полночь?
  • создать подclass uibutton
  • Метод доступа после завершения анимации UIImageView
  • Как использовать CaptiveNetwork для получения текущего имени точки доступа Wi-Fi
  • Декларация о свойствах и автоматическое резервирование хранилища
  • Давайте будем гением компьютера.