iphone - UIImagePickerController 并从现有照片中提取 EXIF 数据

标签 iphone cocoa-touch gps uiimagepickercontroller exif

众所周知,UIImagePickerController 在选择照片后不会返回照片的元数据。但是,应用程序商店中的几个应用程序(Mobile Fotos、PixelPipe)似乎能够读取原始文件以及存储在其中的 EXIF 数据,从而使应用程序能够从所选照片中提取地理数据。

他们似乎是通过从 /private/var/mobile/Media/DCIM/100APPLE/ 文件夹中读取原始文件并通过 EXIF 库运行它来实现此目的。

但是,我无法找到将从 UIImagePickerController 返回的照片与磁盘上的文件相匹配的方法。我已经研究过文件大小,但原始文件是 JPEG,而返回的图像是原始 UIImage,因此无法知道所选图像的文件大小。

我正在考虑制作一个哈希表并与每个图像的前 x 像素进行匹配。但这似乎有点过头了,而且可能相当慢。

有什么建议吗?

最佳答案

您看过这个 exif iPhone 库吗?

http://code.google.com/p/iphone-exif/

要在我这边尝试一下。我想从使用 UIImagePickerController 拍摄的图片中获取 GPS(地理标签)坐标:/

经过深入研究,这个库似乎将 NSData 信息作为输入,并且 UIImagePickerController 在拍摄快照后返回一个 UIImage。理论上,如果我们使用从UIkit类别中选择的UIImage

NSData * UIImageJPEGRepresentation (
   UIImage *image,
   CGFloat compressionQuality
);

然后我们可以将 UIImage 转换为 NSData 实例,然后将其与 iPhone exif 库一起使用。

更新:
我对上面提到的库进行了测试,它似乎有效。然而,由于我对 EXIF 格式的了解有限,并且库中缺乏高级 API,我无法获取 EXIF 标签的值。 这是我的代码,以防你们中的任何人可以进一步:


#import "EXFJpeg.h"

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
    NSLog(@"image picked %@ with info %@", image, editingInfo);
    NSData* jpegData = UIImageJPEGRepresentation (image,0.5);
    EXFJpeg* jpegScanner = [[EXFJpeg alloc] init];
    [jpegScanner scanImageData: jpegData];
    EXFMetaData* exifData = jpegScanner.exifMetaData;
    EXFJFIF* jfif = jpegScanner.jfif;
    EXFTag* tagDefinition = [exifData tagDefinition: [NSNumber numberWithInt:EXIF_DateTime]];
    //EXFTag* latitudeDef = [exifData tagDefinition: [NSNumber numberWithInt:EXIF_GPSLatitude]];
    //EXFTag* longitudeDef = [exifData tagDefinition: [NSNumber numberWithInt:EXIF_GPSLongitude]];
    id latitudeValue = [exifData tagValue:[NSNumber numberWithInt:EXIF_GPSLatitude]];
    id longitudeValue = [exifData tagValue:[NSNumber numberWithInt:EXIF_GPSLongitude]];
    id datetime = [exifData tagValue:[NSNumber numberWithInt:EXIF_DateTime]];
    id t = [exifData tagValue:[NSNumber numberWithInt:EXIF_Model]];
....
....

检索标签定义正常,但所有标签值返回 nil :(

如果您想尝试该库,则需要定义一个全局变量以使其运行(如文档中所述,但嗯..:/)

BOOL gLogging = FALSE;

更新2
在这里回答:iPhone - access location information from a photo UIImage 不封装元信息,所以我们陷入困境:当然,不会通过此接口(interface)给出 EXIF 信息。

最终更新
好的,我设法让它工作,至少对选择器返回的图片进行正确的地理标记。
在触发 UIImagePickerController 之前,您需要使用 CLLocationManager 来检索当前的 CLocation
拥有它后,您可以使用此方法,该方法使用 exif-iPhone 库对 CLLocation 中的 UIImage 进行地理标记:


-(NSData*) geotagImage:(UIImage*)image withLocation:(CLLocation*)imageLocation {
    NSData* jpegData =  UIImageJPEGRepresentation(image, 0.8);
    EXFJpeg* jpegScanner = [[EXFJpeg alloc] init];
    [jpegScanner scanImageData: jpegData];
    EXFMetaData* exifMetaData = jpegScanner.exifMetaData;
    // end of helper methods 
    // adding GPS data to the Exif object 
    NSMutableArray* locArray = [self createLocArray:imageLocation.coordinate.latitude]; 
    EXFGPSLoc* gpsLoc = [[EXFGPSLoc alloc] init]; 
    [self populateGPS: gpsLoc :locArray]; 
    [exifMetaData addTagValue:gpsLoc forKey:[NSNumber numberWithInt:EXIF_GPSLatitude] ]; 
    [gpsLoc release]; 
    [locArray release]; 
    locArray = [self createLocArray:imageLocation.coordinate.longitude]; 
    gpsLoc = [[EXFGPSLoc alloc] init]; 
    [self populateGPS: gpsLoc :locArray]; 
    [exifMetaData addTagValue:gpsLoc forKey:[NSNumber numberWithInt:EXIF_GPSLongitude] ]; 
    [gpsLoc release]; 
    [locArray release];
    NSString* ref;
    if (imageLocation.coordinate.latitude <0.0)
        ref = @"S"; 
    else
        ref =@"N"; 
    [exifMetaData addTagValue: ref forKey:[NSNumber numberWithInt:EXIF_GPSLatitudeRef] ]; 
    if (imageLocation.coordinate.longitude <0.0)
        ref = @"W"; 
    else
        ref =@"E"; 
    [exifMetaData addTagValue: ref forKey:[NSNumber numberWithInt:EXIF_GPSLongitudeRef] ]; 
    NSMutableData* taggedJpegData = [[NSMutableData alloc] init];
    [jpegScanner populateImageData:taggedJpegData];
    [jpegScanner release];
    return [taggedJpegData autorelease];
}<p></p>

// Helper methods for location conversion -(NSMutableArray*) createLocArray:(double) val{ val = fabs(val); NSMutableArray* array = [[NSMutableArray alloc] init]; double deg = (int)val; [array addObject:[NSNumber numberWithDouble:deg]]; val = val - deg; val = val*60; double minutes = (int) val; [array addObject:[NSNumber numberWithDouble:minutes]]; val = val - minutes; val = val*60; double seconds = val; [array addObject:[NSNumber numberWithDouble:seconds]]; return array; } -(void) populateGPS:(EXFGPSLoc* ) gpsLoc :(NSArray*) locArray{ long numDenumArray[2]; long* arrPtr = numDenumArray; [EXFUtils convertRationalToFraction:&arrPtr :[locArray objectAtIndex:0]]; EXFraction* fract = [[EXFraction alloc] initWith:numDenumArray[0]:numDenumArray[1]]; gpsLoc.degrees = fract; [fract release]; [EXFUtils convertRationalToFraction:&arrPtr :[locArray objectAtIndex:1]]; fract = [[EXFraction alloc] initWith:numDenumArray[0] :numDenumArray[1]]; gpsLoc.minutes = fract; [fract release]; [EXFUtils convertRationalToFraction:&arrPtr :[locArray objectAtIndex:2]]; fract = [[EXFraction alloc] initWith:numDenumArray[0] :numDenumArray[1]]; gpsLoc.seconds = fract; [fract release]; }

关于iphone - UIImagePickerController 并从现有照片中提取 EXIF 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1238838/

相关文章:

iphone - 使用 CFDictionaryCreate 和特殊字符创建 CFDictionaryRef

iphone - UIScrollView - 为新的 contentSize 设置适当的 contentOffset 会产生不需要的空白空间

iphone - 是否 applicationDidFinishLaunching : get called when application is updated and launched first time?

python - 计算以 KM 表示的总距离(在 Python 中提供坐标列表)

android如何检查服务是否正在运行

java - Android 模拟 GPS 卫星(不仅仅是位置)

iphone - 是否可以将图像图标添加到特定 View 中的导航栏?

iphone - 调用 setEditing 时自定义 UITableViewCell 调整大小标签

iphone - 有很多 "initWith"参数通常是不好的做法吗?

iphone - 间歇性 extaudiofileread exc_bad_access