I am using AvFoundation to take still image and adding gps info to metadata and saving to a photo album using Asset library but gps info is not saving at all.
here
There are several answers above and elsewhere on SO that give most of what you want. Here is the working code I generated from all of these sources, and it seems to work just fine.
This is all done within the captureStillImageAsynchronouslyFromConnection block. My thanks to all the various contributors:
[stillCapture
captureStillImageAsynchronouslyFromConnection: stillConnection
completionHandler:
^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
if (error) {
NSLog(@"snap capture error %@", [error localizedDescription]);
return;
}
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate);
CFMutableDictionaryRef mutableAttachments = CFDictionaryCreateMutableCopy(NULL, 0, attachments);
// Create GPS Dictionary
NSMutableDictionary *gps = [NSMutableDictionary dictionary];
CLLocation *location = ;
// 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];
// Latitude
[gps setObject: (location.coordinate.latitude < 0) ? @"S" : @"N"
forKey:(NSString *)kCGImagePropertyGPSLatitudeRef];
[gps setObject:[NSNumber numberWithDouble:fabs(location.coordinate.latitude)]
forKey:(NSString *)kCGImagePropertyGPSLatitude];
// Longitude
[gps setObject: (location.coordinate.longitude < 0) ? @"W" : @"E"
forKey:(NSString *)kCGImagePropertyGPSLongitudeRef];
[gps setObject:[NSNumber numberWithDouble:fabs(location.coordinate.longitude)]
forKey:(NSString *)kCGImagePropertyGPSLongitude];
// Altitude
if (!isnan(location.altitude)){
// NB: many get this wrong, it is an int, not a string:
[gps setObject:[NSNumber numberWithInt: location.altitude >= 0 ? 0 : 1]
forKey:(NSString *)kCGImagePropertyGPSAltitudeRef];
[gps setObject:[NSNumber numberWithDouble:fabs(location.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 numberWithDouble:location.speed*3.6] forKey:(NSString *)kCGImagePropertyGPSSpeed];
}
// Heading
if (location.course >= 0){
[gps setObject:@"T" forKey:(NSString *)kCGImagePropertyGPSTrackRef];
[gps setObject:[NSNumber numberWithDouble:location.course] forKey:(NSString *)kCGImagePropertyGPSTrack];
}
CFDictionarySetValue(mutableAttachments, kCGImagePropertyGPSDictionary, CFBridgingRetain(gps));
// NSDictionary *ma = (__bridge NSDictionary *)(mutableAttachments);
// NSLog(@"photo attachments: %@", ma);
[ROOTVC.library
writeImageDataToSavedPhotosAlbum:jpegData
metadata:(__bridge id)mutableAttachments
completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"XXX save to assets failed: %@", [error localizedDescription]);
} else {
[self processAsset:assetURL inGroup:ROOTVC.venue forMessage:savingMessage];
}
}];
if (mutableAttachments)
CFRelease(mutableAttachments);
if (attachments)
CFRelease(attachments);
}];
As always, I worry if I am getting the releases right. Here's a jhead(1) of the result:
File name : 20131001_082119/photo.jpeg
File size : 82876 bytes
File date : 2013:10:01 08:21:19
Resolution : 480 x 360
Orientation : rotate 90
Flash used : No
Focal length : 4.1mm (35mm equivalent: 30mm)
Exposure time: 0.0083 s (1/120)
Aperture : f/2.2
ISO equiv. : 6400
Whitebalance : Auto
Metering Mode: pattern
Exposure : program (auto)
GPS Latitude : N 40d 43m 22.32s
GPS Longitude: W 74d 34m 39.15s
GPS Altitude : 117.92m