2010-10-07 55 views
12

我在尝试使用iOS4.1上的地理标签信息将照片保存到相机卷时出现重大问题。我正在使用以下ALAssetsLibrary API:在iOS4.1上保存带有照片的地理标签信息

- (void)writeImageDataToSavedPhotosAlbum:(NSData *)imageData 
           metadata:(NSDictionary *)metadata 
         completionBlock:(ALAssetsLibraryWriteImageCompletionBlock)completionBlock 

我有GPS坐标,我希望将照片保存为输入。不幸的是,没有文档或示例代码描述了如何形成封装GPS坐标的元数据NSDictionary。有人可以发布已知工作的示例代码吗?

我也尝试过使用iPhone Exif库来保存imageData中的地理信息,而不是使用元数据,但不幸的是iPhone Exif库崩溃了。任何帮助是极大的赞赏。

回答

2

经过一番搜索,我发现并适应这个

这原来cclocation数据到合适的NSDictionary

#import <ImageIO/ImageIO.h> 

+(NSMutableDictionary *)updateExif:(CLLocation *)currentLocation{ 


    NSMutableDictionary* locDict = [[NSMutableDictionary alloc] init]; 


    CLLocationDegrees exifLatitude = currentLocation.coordinate.latitude; 
    CLLocationDegrees exifLongitude = currentLocation.coordinate.longitude; 

    [locDict setObject:currentLocation.timestamp forKey:(NSString*)kCGImagePropertyGPSTimeStamp]; 

    if (exifLatitude <0.0){ 
     exifLatitude = exifLatitude*(-1); 
     [locDict setObject:@"S" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; 
    }else{ 
     [locDict setObject:@"N" forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; 
    } 
    [locDict setObject:[NSNumber numberWithFloat:exifLatitude] forKey:(NSString*)kCGImagePropertyGPSLatitude]; 

    if (exifLongitude <0.0){ 
     exifLongitude=exifLongitude*(-1); 
     [locDict setObject:@"W" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; 
    }else{ 
     [locDict setObject:@"E" forKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; 
    } 
    [locDict setObject:[NSNumber numberWithFloat:exifLongitude] forKey:(NSString*) kCGImagePropertyGPSLongitude]; 


    return [locDict autorelease]; 

} 

然后我把它添加到您通过相机获得现有的元数据(不默认情况下,具备GPS数据)

我得到这样

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ 
    [imageMetaData setDictionary:[[info objectForKey:UIImagePickerControllerMediaMetadata] copy]]; 
} 
原来的元数据

然后我添加上一个方法产生的gps字典。

[imageMetaData setObject:currentLocation forKey:(NSString*)kCGImagePropertyGPSDictionary];   

    [library writeImageToSavedPhotosAlbum:[viewImage CGImage] metadata:imageMetaData completionBlock:photoCompblock]; 
+0

很好的回答,+ 1,但你设置' kCGImagePropertyGPSTimeStamp'错误。该值必须是NSString而不是NSDate。 – Anomie 2011-03-15 16:17:22

+0

你不需要复制'UIImagePickerControllerMediaMetadata'对象的字典;告诉可变字典设置自己以匹配另一个字典将修改接收字典,以便字典变成副本。您使用'copy'消息制作的副本被浪费;更糟糕的是,既然你不释放它,你就会泄漏它。你可以通过释放或者自动释放来解决这个问题,但是最好不要把不必要的拷贝放在第一位。 – 2011-05-01 05:08:20

23

这里是代码从CLLocation对象复制所有可用的信息转换成适当的格式用于GPS元数据字典:

- (NSDictionary *)getGPSDictionaryForLocation:(CLLocation *)location { 
    NSMutableDictionary *gps = [NSMutableDictionary dictionary]; 

    // GPS tag version 
    [gps setObject:@"2.2.0.0" forKey:(NSString *)kCGImagePropertyGPSVersion]; 

    // Time and date must be provided as strings, not as an NSDate object 
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
    [formatter setDateFormat:@"HH:mm:ss.SSSSSS"]; 
    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; 
    [gps setObject:[formatter stringFromDate:location.timestamp] forKey:(NSString *)kCGImagePropertyGPSTimeStamp]; 
    [formatter setDateFormat:@"yyyy:MM:dd"]; 
    [gps setObject:[formatter stringFromDate:location.timestamp] forKey:(NSString *)kCGImagePropertyGPSDateStamp]; 
    [formatter release]; 

    // Latitude 
    CGFloat latitude = location.coordinate.latitude; 
    if (latitude < 0) { 
     latitude = -latitude; 
     [gps setObject:@"S" forKey:(NSString *)kCGImagePropertyGPSLatitudeRef]; 
    } else { 
     [gps setObject:@"N" forKey:(NSString *)kCGImagePropertyGPSLatitudeRef]; 
    } 
    [gps setObject:[NSNumber numberWithFloat:latitude] forKey:(NSString *)kCGImagePropertyGPSLatitude]; 

    // Longitude 
    CGFloat longitude = location.coordinate.longitude; 
    if (longitude < 0) { 
     longitude = -longitude; 
     [gps setObject:@"W" forKey:(NSString *)kCGImagePropertyGPSLongitudeRef]; 
    } else { 
     [gps setObject:@"E" forKey:(NSString *)kCGImagePropertyGPSLongitudeRef]; 
    } 
    [gps setObject:[NSNumber numberWithFloat:longitude] forKey:(NSString *)kCGImagePropertyGPSLongitude]; 

    // Altitude 
    CGFloat altitude = location.altitude; 
    if (!isnan(altitude)){ 
     if (altitude < 0) { 
      altitude = -altitude; 
      [gps setObject:@"1" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef]; 
     } else { 
      [gps setObject:@"0" forKey:(NSString *)kCGImagePropertyGPSAltitudeRef]; 
     } 
     [gps setObject:[NSNumber numberWithFloat:altitude] forKey:(NSString *)kCGImagePropertyGPSAltitude]; 
    } 

    // Speed, must be converted from m/s to km/h 
    if (location.speed >= 0){ 
     [gps setObject:@"K" forKey:(NSString *)kCGImagePropertyGPSSpeedRef]; 
     [gps setObject:[NSNumber numberWithFloat:location.speed*3.6] forKey:(NSString *)kCGImagePropertyGPSSpeed]; 
    } 

    // Heading 
    if (location.course >= 0){ 
     [gps setObject:@"T" forKey:(NSString *)kCGImagePropertyGPSTrackRef]; 
     [gps setObject:[NSNumber numberWithFloat:location.course] forKey:(NSString *)kCGImagePropertyGPSTrack]; 
    } 

    return gps; 
} 

指定由该方法作为返回值的字典为kCGImagePropertyGPSDictionary键在元数据字典中,您传递给writeImageDataToSavedPhotosAlbum:metadata:completionBlock:CGImageDestinationAddImage()

+1

我认为你应该使用双精度而不是经度和纬度的浮点数,否则你可能会出现几英尺/米。 – Marius 2011-06-09 03:32:12

+0

@Anomie,谈论kCGImagePropertyGPSDateStamp和kCGImagePropertyGPSTimeStamp,是否可以添加我们自己的日期/时间,而不是从“location.timestamp”中获取它。 – 2012-01-09 18:49:50

+0

@ShishirShetty:你可以伪造任何地理位置数据,如果这是你想要做的。 – Anomie 2012-01-10 11:30:33

相关问题