Сохранение информации Geotag с фотографией на iOS4.1 - PullRequest
12 голосов
/ 07 октября 2010

У меня возникают серьезные проблемы при попытке сохранить фотографию в фотопленку с информацией о геотегах на iOS4.1. Я использую следующий API ALAssetsLibrary:

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

У меня есть GPS-координаты, которые я хочу сохранить с фотографией в качестве входа. К сожалению, нет документации или примера кода, который описывает, как формировать метаданные NSDictionary, которые инкапсулируют координаты GPS. Может кто-нибудь опубликовать пример кода, который, как известно, работает?

Я также пытался использовать библиотеку iPhone Exif для сохранения географической информации в imageData вместо использования метаданных, но, к сожалению, библиотека iPhone Exif дает сбой. Любая помощь с благодарностью.

Ответы [ 5 ]

24 голосов
/ 15 марта 2011

Вот код для копирования всей доступной информации из объекта 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().

11 голосов
/ 15 мая 2011

Я использовал этот код и создал NSMutableDictionary, чтобы помочь сохранить геотег и другие метаданные в изображение. Проверьте мой блог здесь:

http://blog.codecropper.com/2011/05/adding-metadata-to-ios-images-the-easy-way/

2 голосов
/ 20 июля 2013

Вот удобная категория CLLocation для gist, чтобы сделать все это для вас:

https://gist.github.com/phildow/6043486

2 голосов
/ 17 ноября 2010

После долгих поисков я нашел и адаптировал

Это превращает данные размещения в подходящий 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 голосов
/ 09 октября 2018

Ответ Аноми в Swift 4.0:

func getGPSDictionaryForLocation(location:CLLocation) -> [String:AnyObject] {

    var gps = [String:AnyObject]()

    var latitude = location.coordinate.latitude

    if(latitude < 0){
        latitude = -latitude
        gps[kCGImagePropertyGPSLatitudeRef as String] = "S" as AnyObject

    }else{
        gps[kCGImagePropertyGPSLatitudeRef as String] = "N" as AnyObject
    }

    gps[kCGImagePropertyGPSLatitude as String] = latitude as AnyObject


    var longitude = location.coordinate.longitude

    if(longitude < 0){
        longitude = -longitude
        gps[kCGImagePropertyGPSLongitudeRef as String] = "W" as AnyObject
    }else{
        gps[kCGImagePropertyGPSLongitudeRef as String] = "E" as AnyObject
    }

    gps[kCGImagePropertyGPSLongitude as String] = longitude as AnyObject

    gps[kCGImagePropertyGPSAltitude as String] = location.altitude as AnyObject

    return gps
}
...