众所周知,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/