Iphone 从UIImage-UIImagePickerController获取Exif数据
如何从UIImagePickerController中选择的UIImage获取Exif信息 我为此做了很多研发工作,得到了很多回复,但仍然没有实现 我已经通过了这个链接 请帮我解决这个问题Iphone 从UIImage-UIImagePickerController获取Exif数据,iphone,objective-c,ipad,exif,Iphone,Objective C,Ipad,Exif,如何从UIImagePickerController中选择的UIImage获取Exif信息 我为此做了很多研发工作,得到了很多回复,但仍然没有实现 我已经通过了这个链接 请帮我解决这个问题 提前感谢..有趣的问题!我为从您的照片库中拾取的图像提出了以下解决方案(请注意,我的代码使用的是ARC): 导入AssetLibrary.framework和ImageIO.framework 然后在.h文件中包含所需的类: #import <AssetsLibrary/ALAsset.h> #i
提前感谢..有趣的问题!我为从您的照片库中拾取的图像提出了以下解决方案(请注意,我的代码使用的是ARC): 导入
AssetLibrary.framework
和ImageIO.framework
然后在.h文件中包含所需的类:
#import <AssetsLibrary/ALAsset.h>
#import <AssetsLibrary/ALAssetRepresentation.h>
#import <ImageIO/CGImageSource.h>
#import <ImageIO/CGImageProperties.h>
我注意到的一件事是,iOS会要求用户允许定位服务–如果他拒绝,你将无法获取图像数据
编辑
添加了用于保存图像(包括其元数据)的代码。这是一个快速的方法,所以也许有更好的方法,但它是有效的 我找到了解决办法,并从 从这里我们还可以获得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 =@"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;
}
对于所有这些,您必须导入
assetsbrary.framework
和ImageIO.framework
您需要从图像中实际检索EXIF信息。只有在将EXIF保存到照片库时,才会将其添加到图像中。即使您使用ALAssetLibrary从库中获取图像资源,如果您将其设置为UIImage,它也会丢失所有EXIF信息。我尝试将GPS坐标插入到iPad摄像头拾取的图像元数据中,正如Mehul建议的那样。
这很有效,谢谢你的帖子
附言。
谁打算使用该代码,只需将函数顶部的两个地理位置-(NSMutableData*)getImageWithMetaData:(UIImage*)pImage替换即可{
假设您已经在代码中初始化了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标题以及相关框架,这些答案似乎都非常复杂。如果图像已保存到相机卷,并且您拥有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);
我使用这种方法从图像中获取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]);
}
}
你能告诉我获取exif数据后如何保存图像吗?请告诉我什么是“桥”在您的代码中?:-)@Marvin我使用的是ARC。
\uuuu bridge
是一手关键字之一,它告诉ARC对象的所有权,以便它可以正确地清理它们。最简单的情况是\uuu bridge
强制转换,ARC不会为其做任何额外的工作(它假设您自己处理对象的内存)。缓冲区的内存是否释放过?怀疑没有…?注意:您还需要包括#导入currentLatitude从何而来?您是在调用UIImagePicker之前通过标准CoreLocation调用进行设置,还是直接从返回的映像读取?调用UIImage之前的CoreLocation调用PickerControllerahh,它可能不准确。您调用CoreLocation,调用UIImagePicker,然后在拍摄图像之前物理移动设备一段距离。您现在的纬度和经度不准确。Drat…但您也可以将距离过滤器设置为5米,因此如果使用moves,它将自动获取其当前位置。您实际上,您并没有从映像中获取EXIF数据,而是创建EXIF并将其添加到映像中。这实际上并没有回答问题。这是一种比2012年的答案更好的方法。它还返回比其他方法多得多的信息:它们不会返回存储在{TIFF}中的信息如型号、品牌、版权、艺术家等。这应该标记为答案!请参见此答案。这不是回答问题,这与主题无关。他没有问如何获取位置,而是需要将位置作为UIImage的元数据
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);
-(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]);
}
}