Iphone 从UIImage-UIImagePickerController获取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

如何从UIImagePickerController中选择的UIImage获取Exif信息

我为此做了很多研发工作,得到了很多回复,但仍然没有实现

我已经通过了这个链接

请帮我解决这个问题


提前感谢..

有趣的问题!我为从您的照片库中拾取的图像提出了以下解决方案(请注意,我的代码使用的是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]);


    }

}