Saving Geotag info with photo on iOS4.1
Solution 1:
Here is code to copy all available information from a CLLocation object into the proper format for a GPS metadata dictionary:
- (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;
}
Assign the dictionary returned by this method as the value for the kCGImagePropertyGPSDictionary
key in the metadata dictionary you pass to writeImageDataToSavedPhotosAlbum:metadata:completionBlock:
or CGImageDestinationAddImage()
.
Solution 2:
I used this code and created a NSMutableDictionary to help save geotag and other metadata to an image. Check out my blog post here:
http://blog.codecropper.com/2011/05/adding-metadata-to-ios-images-the-easy-way/
Solution 3:
After much searching I found and adapted this
This turns cclocation data into a suitable 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];
}
Then I add it to the existing metadata that you get through the camera (which doesn't by default have the gps data)
I get the original metadata like this
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
[imageMetaData setDictionary:[[info objectForKey:UIImagePickerControllerMediaMetadata] copy]];
}
then I add the gps dictionary the previous method produces.
[imageMetaData setObject:currentLocation forKey:(NSString*)kCGImagePropertyGPSDictionary];
[library writeImageToSavedPhotosAlbum:[viewImage CGImage] metadata:imageMetaData completionBlock:photoCompblock];