2010-10-07 12 views
12

Tengo grandes problemas al intentar guardar una foto en el rollo de la cámara con información de geoetiqueta en iOS4.1. Estoy utilizando la API siguiente ALAssetsLibrary:Guardar información de geoetiqueta con foto en iOS4.1

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

tengo las coordenadas GPS que desea guardar con la foto como una entrada. Lamentablemente, no hay documentación o código de muestra que describa cómo se forma el metadato NSDictionary que encapsula las coordenadas del GPS. ¿Alguien puede publicar un código de muestra que se sabe que funciona?

También he intentado usar la biblioteca Exif de iPhone para guardar información geográfica en imageData en lugar de usar metadatos, pero desafortunadamente la biblioteca de iPhone Exif se está cayendo. Cualquier ayuda es muy apreciada.

Respuesta

2

Después de mucho buscar encontré y adaptado este

Esto convierte los datos en una cclocation adecuada 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]; 

} 

Luego añadir a los metadatos existentes que se obtiene a través de la cámara (que no lo hace tienen por defecto los datos GPS)

puedo obtener los metadatos originales como esta

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ 
    [imageMetaData setDictionary:[[info objectForKey:UIImagePickerControllerMediaMetadata] copy]]; 
} 

luego agrego el diccionario gps que produce el método anterior.

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

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

Buena respuesta, 1, pero se está configurando ' kCGImagePropertyGPSTimeStamp' mal. El valor debe ser un NSString en lugar de un NSDate. – Anomie

+0

No es necesario 'copiar' el diccionario que es el objeto para' UIImagePickerControllerMediaMetadata'; diciéndole a un diccionario mutable que se ajuste a sí mismo para que coincida con otro diccionario modificará el diccionario de recepción, de modo que ese diccionario se convierta en la copia. La copia que hace con el mensaje 'copy' se desperdicia; peor, ya que no lo sueltas, lo filtras. Podrías resolverlo soltándolo o soltándolo, pero es mejor no hacer la copia innecesaria en primer lugar. –

23

Aquí es código para copiar toda la información disponible de un objeto CLLocation en el formato adecuado para un diccionario de metadatos 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; 
} 

asignar el diccionario devuelto por este método como el valor de la clave kCGImagePropertyGPSDictionary en el diccionario de metadatos, pasa al writeImageDataToSavedPhotosAlbum:metadata:completionBlock: o CGImageDestinationAddImage().

+1

Creo que debería usar Double en lugar de Float con latitud y longitud ... de lo contrario podría salir con unos pocos pies/metros. – Marius

+0

@Anomie, hablando de kCGImagePropertyGPSDateStamp y kCGImagePropertyGPSTimeStamp, ¿es posible agregar nuestra propia fecha/hora., En lugar de tomarlo de "location.timestamp".? –

+0

@ShishirShetty: puede falsificar cualquier dato de geolocalización, si eso es lo que quiere hacer. – Anomie

Cuestiones relacionadas