samedi 12 janvier 2013

Geotagging JPEG with Core Foundation

I was searching a way to edit or add GPS metadata of JPEG files without using an external library inside a Mac Application. After looking on internet and reading the ImageIOKit documentation, I found an interesting post on the Apple Mailing List talking about this topic and an old bug related to it. It includes a code sample that is apparently working now (Mac Os X 10.8).  I just wanted to add some details about it :
  • The values corresponding to the kCGImagePropertyGPSLatitudeRef/kCGImagePropertyGPSLongitudedRef keys are expected to be of type NSString.
  • The values corresponding to the kCGImagePropertyGPSLatitude/kCGImagePropertyGPSLongitude keys are expected to be of type NSNumber.
  • CGImageSourceRef originalImageSource = CGImageSourceCreateWithURL((CFURLRef)imageURL, NULL);
    //get gps metadata
    NSDictionary *metadata = (NSDictionary *)CGImageSourceCopyPropertiesAtIndex(originalImageSource,0,NULL);
    //make the metadata dictionary mutable so we can add properties to it
    NSMutableDictionary *metadataAsMutable = [[metadata mutableCopy]autorelease];
    [metadata release];
    //get mutable gps data
    NSMutableDictionary *GPSDictionary = [[[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyGPSDictionary]mutableCopy]autorelease];
    if(!GPSDictionary)
    {
    GPSDictionary = [NSMutableDictionary dictionary];
    }
    //Upate latitude longitude
    // latRef and lonRef are NSString
    [GPSDictionary setObject:[NSNumber numberWithFloat:lat] forKey:(NSString*)kCGImagePropertyGPSLatitude];
    [GPSDictionary setObject:latRef forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];
    [GPSDictionary setObject:[NSNumber numberWithFloat:lon] forKey:(NSString*)kCGImagePropertyGPSLongitude];
    [GPSDictionary setObject:lonRef forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];
    //add our modified GPS data back into the image's metadata
    [metadataAsMutable setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];
    NSLog(@"Updated metadata: %@", metadataAsMutable);
    // Create a new image source that reads the TIFF data that we get from our NSImage.
    NSData *imageData = [newImage TIFFRepresentation];
    CGImageSourceRef finalImageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
    // Create an image destination. This will take the image data from our source, and write it along with the metadata we read above
    // into a file in the correct format.
    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL((CFURLRef)imageURL, imageType, 1, NULL);
    CGImageDestinationAddImageFromSource(imageDestination, finalImageSource, 0, (CFDictionaryRef)metadataAsMutable);
    if (!CGImageDestinationFinalize(imageDestination))
    {
    // The sample code doesn't do any specific error handling in this case. This would be an appropriate
    // place to notify the user, put up an alert, etc.
    }
    view raw gistfile1.m hosted with ❤ by GitHub

Aucun commentaire:

Enregistrer un commentaire