2010-10-07 12 views
12

Mam poważne problemy z zapisaniem zdjęcia do rolki aparatu z informacjami o geotagu na iOS4.1. Używam następujący ALAssetsLibrary API:Zapisywanie informacji geotagów ze zdjęciem na iOS4.1

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

mam współrzędne GPS, który chciałbym, aby zapisać się na zdjęciu jako wejścia. Niestety, nie ma dokumentacji ani przykładowego kodu opisującego sposób tworzenia metadanych NSDictionary, który zawiera współrzędne GPS. Czy ktoś może opublikować przykładowy kod, o którym wiadomo, że działa?

Próbowałem również użyć biblioteki iPhone Exif, aby zapisać dane geograficzne w imageData, zamiast używać metadanych, ale niestety biblioteka iPhone Exif ulega awarii. Każda pomoc jest bardzo doceniana.

Odpowiedz

2

Po długich poszukiwaniach znalazłem i dostosować tę

ta zamienia dane cclocation do odpowiedniego 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]; 

} 

Potem dodać go do istniejącej metadanych, które można uzyskać za pomocą aparatu (co nie domyślnie mają dane gPS)

dostaję oryginalną metadane jak ten

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

, a następnie dodaję słownik gps, który produkuje poprzednia metoda.

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

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

Dobra odpowiedź, +1, ale jesteś ustawienie ' kCGImagePropertyGPSTimeStamp' wrong. Wartość musi być NSString zamiast NSDate. – Anomie

+0

Nie ma potrzeby "kopiowania" słownika, który jest obiektem dla 'UIImagePickerControllerMediaMetadata'; poinformowanie zmiennego słownika, aby ustawił się w celu dopasowania do innego słownika, zmodyfikuje słownik przyjmujący, tak aby słownik stał się kopią. Kopia wykonana z komunikatem 'copy' jest zmarnowana; gorzej, skoro go nie wypuszczasz, to wyciekasz. Możesz rozwiązać ten problem, zwalniając go lub automatycznie, ale lepiej nie robić niepotrzebnej kopii. –

23

Oto kod skopiować wszystkie dostępne informacje z obiektu CLLocation do odpowiedniego formatu dla słownika metadanych 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; 
} 

przypisać słownika zwrócony tą metodą jako wartość klucza kCGImagePropertyGPSDictionary w słowie metadanych przechodzisz na writeImageDataToSavedPhotosAlbum:metadata:completionBlock: lub CGImageDestinationAddImage().

+1

Myślę, że powinieneś użyć Double zamiast Float z szerokością i długością geograficzną ... w przeciwnym razie możesz wyjść z kilku stóp/metrów. – Marius

+0

@Anomie, mówiąc o kCGImagePropertyGPSDateStamp i kCGImagePropertyGPSTimeStamp, czy możliwe jest dodanie naszej własnej daty/czasu, zamiast pobrania jej z "location.timestamp".? –

+0

@ShishirShetty: Możesz sfałszować dowolne dane geolokalizacji, jeśli chcesz to zrobić. – Anomie

Powiązane problemy