Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem setting exif data for an image

I'm using the new ImageIO framework in iOS 4.1. I successfully retrieve the exif metadata using the following:

CFDictionaryRef metadataDict = CMGetAttachment(sampleBuffer, kCGImagePropertyExifDictionary , NULL); 

Reading it out, it appears valid. Saving an image out works, but there is never any exif data in the image.

    CGImageDestinationRef myImageDest = CGImageDestinationCreateWithURL((CFURLRef) docurl, kUTTypeJPEG, 1, NULL);      // Add the image to the destination using previously saved options.      CGImageDestinationAddImage(myImageDest, iref, NULL);      //add back exif     NSDictionary *props = [NSDictionary dictionaryWithObjectsAndKeys:                             [NSNumber numberWithFloat:.1], kCGImageDestinationLossyCompressionQuality,                            metadataDict, kCGImagePropertyExifDictionary, //the exif metadata                                                         nil];                            //kCGImagePropertyExifAuxDictionary      CGImageDestinationSetProperties(myImageDest, (CFDictionaryRef) props);      // Finalize the image destination.      bool status = CGImageDestinationFinalize(myImageDest); 
like image 615
akaru Avatar asked Feb 26 '11 05:02

akaru


People also ask

How do I put EXIF on a photo?

You need first to copy the exif files located here google exif to your project, then use the following code : ExifInterface exif = new ExifInterface(); exif. readExif(exifVar. getAbsolutePath()); exif.

How do I change the EXIF date on a photo?

Use Shift date to shift the date, and Shift time to shift the time. The calendar on the left here shows the original Date Created information stored in pictures' EXIF data. In the second calendar, choose a new date for the pictures. Use Shift date at the top to change the picture-taken date.

Can you alter EXIF data?

Yes EXIF data can be altered. You can change the fields in post with certain programs. You can also fake the date simply by changing the date and time of the camera before taking the picture, there's nothing that says a camera has to have the exact date and time.


2 Answers

The following blog post is where I got my answer when I had issues with modifying and saving Exif data Caffeinated Cocoa. This works on iOS.

Here is my test code for writing Exif and GPS data. It pretty much a copy and paste of the code from the above blog. I am using this to write exif data to a captured image.

NSData *jpeg = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer] ;  CGImageSourceRef  source ;     source = CGImageSourceCreateWithData((CFDataRef)jpeg, NULL);      //get all the metadata in the image     NSDictionary *metadata = (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(source,0,NULL);      //make the metadata dictionary mutable so we can add properties to it     NSMutableDictionary *metadataAsMutable = [[metadata mutableCopy]autorelease];     [metadata release];      NSMutableDictionary *EXIFDictionary = [[[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyExifDictionary]mutableCopy]autorelease];     NSMutableDictionary *GPSDictionary = [[[metadataAsMutable objectForKey:(NSString *)kCGImagePropertyGPSDictionary]mutableCopy]autorelease];     if(!EXIFDictionary) {         //if the image does not have an EXIF dictionary (not all images do), then create one for us to use         EXIFDictionary = [NSMutableDictionary dictionary];     }     if(!GPSDictionary) {         GPSDictionary = [NSMutableDictionary dictionary];     }      //Setup GPS dict       [GPSDictionary setValue:[NSNumber numberWithFloat:_lat] forKey:(NSString*)kCGImagePropertyGPSLatitude];     [GPSDictionary setValue:[NSNumber numberWithFloat:_lon] forKey:(NSString*)kCGImagePropertyGPSLongitude];     [GPSDictionary setValue:lat_ref forKey:(NSString*)kCGImagePropertyGPSLatitudeRef];     [GPSDictionary setValue:lon_ref forKey:(NSString*)kCGImagePropertyGPSLongitudeRef];     [GPSDictionary setValue:[NSNumber numberWithFloat:_alt] forKey:(NSString*)kCGImagePropertyGPSAltitude];     [GPSDictionary setValue:[NSNumber numberWithShort:alt_ref] forKey:(NSString*)kCGImagePropertyGPSAltitudeRef];      [GPSDictionary setValue:[NSNumber numberWithFloat:_heading] forKey:(NSString*)kCGImagePropertyGPSImgDirection];     [GPSDictionary setValue:[NSString stringWithFormat:@"%c",_headingRef] forKey:(NSString*)kCGImagePropertyGPSImgDirectionRef];      [EXIFDictionary setValue:xml forKey:(NSString *)kCGImagePropertyExifUserComment];     //add our modified EXIF data back into the image’s metadata     [metadataAsMutable setObject:EXIFDictionary forKey:(NSString *)kCGImagePropertyExifDictionary];     [metadataAsMutable setObject:GPSDictionary forKey:(NSString *)kCGImagePropertyGPSDictionary];      CFStringRef UTI = CGImageSourceGetType(source); //this is the type of image (e.g., public.jpeg)      //this will be the data CGImageDestinationRef will write into     NSMutableData *dest_data = [NSMutableData data];      CGImageDestinationRef destination = CGImageDestinationCreateWithData((CFMutableDataRef)dest_data,UTI,1,NULL);      if(!destination) {         NSLog(@"***Could not create image destination ***");     }      //add the image contained in the image source to the destination, overidding the old metadata with our modified metadata     CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef) metadataAsMutable);      //tell the destination to write the image data and metadata into our data object.     //It will return false if something goes wrong     BOOL success = NO;     success = CGImageDestinationFinalize(destination);      if(!success) {         NSLog(@"***Could not create data from image destination ***");     }      //now we have the data ready to go, so do whatever you want with it     //here we just write it to disk at the same path we were passed     [dest_data writeToFile:file atomically:YES];      //cleanup      CFRelease(destination);     CFRelease(source); 
like image 108
Steve McFarlin Avatar answered Sep 18 '22 19:09

Steve McFarlin


I tried Steve's answer and it works, but I think it's slow for large images because it's duplicating the entire image.

You can set the properties directly on the CMSampleBuffer using CMSetAttachments. Just do this before calling jpegStillImageNSDataRepresentation

CFDictionaryRef metaDict = CMCopyDictionaryOfAttachments(NULL, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate); CFMutableDictionaryRef mutable = CFDictionaryCreateMutableCopy(NULL, 0, metaDict);  NSMutableDictionary * mutableGPS = [self getGPSDictionaryForLocation:self.myLocation]; CFDictionarySetValue(mutable, kCGImagePropertyGPSDictionary, mutableGPS);  // set the dictionary back to the buffer CMSetAttachments(imageSampleBuffer, mutable, kCMAttachmentMode_ShouldPropagate); 

And the method getGPSDictionaryForLocation: can be found here:

Saving Geotag info with photo on iOS4.1

like image 40
Morty Avatar answered Sep 17 '22 19:09

Morty