从UIImage获取Exif数据 - UIImagePickerController

Meh*_*tri 53 iphone exif objective-c ipad

我们如何从UIImagePickerController中选择UIImage获取Exif信息?

我为此做了很多研发并获得了很多回复,但仍未能实现这一点.

我已经完成了这个这个链接

请帮我解决这个问题.

提前致谢..

dom*_*dom 34

有趣的问题!我想出了以下解决方案,用于从照片库中选取的图像(注意我的代码使用的是ARC):

导入AssetsLibrary.frameworkImageIO.framework.

然后在.h文件中包含所需的类:

#import <AssetsLibrary/ALAsset.h>
#import <AssetsLibrary/ALAssetRepresentation.h>
#import <ImageIO/CGImageSource.h>
#import <ImageIO/CGImageProperties.h>
Run Code Online (Sandbox Code Playgroud)

并将其放在您的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);
    }
];
Run Code Online (Sandbox Code Playgroud)

我注意到的一件事是,iOS将要求用户允许位置服务 - 如果他否认,你将无法获得图像数据......

编辑

添加了保存图像的代码,包括其元数据.这是一个快速的方法,所以也许有更好的方法,但它的工作原理!


And*_*eis 29

这些答案看起来都非常复杂.如果图像已保存到相机胶卷,并且您有ALAsset(来自UIImagePicker或ALAssetLibrary),您可以获得如下元数据:

asset.defaultRepresentation.metadata;
Run Code Online (Sandbox Code Playgroud)

如果要将图像从相机胶卷保存到另一个位置(例如在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);
Run Code Online (Sandbox Code Playgroud)


Meh*_*tri 23

我找到了解决方案并从这里得到了答案

从这里我们也可以获得GPS信息..

非常感谢并帮助我解决这个问题.

UPDATE

这是我自己创建的另一个功能,也返回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;
}
Run Code Online (Sandbox Code Playgroud)

我们会像这样检索那些数据

//FOR CAMERA IMAGE
NSData *originalImgData = [self getImageWithMetaData:imgOriginal];

//FOR PHOTO LIBRARY IMAGE
[self getImagedataPhotoLibrary:[[myasset defaultRepresentation] metadata] andImage:imgOriginal];
Run Code Online (Sandbox Code Playgroud)

对于所有这一切,你应该进口AssetsLibrary.frameworkImageIO.framework.

  • 您实际上并没有从图像中获取 EXIF 数据,而是在创建 EXIF 并将其添加到图像中。这实际上并没有回答这个问题。 (3认同)

Gou*_*xit 9

我已经使用这种方法从图像中获取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]);


    }

}
Run Code Online (Sandbox Code Playgroud)