Adding metadata to iOS images the easy way

Email This Post Email This Post

Does it have to be so hard?

Are you writing a camera app or image editing app for iOS but are clueless on how to add geolocation to your pictures? Baffled by the lack of information in the otherwise very thorough XCode documentation? I feel your pain my friend. Or actually, felt, cause I got your meds right here.

When developing Snap I wanted to add this feature so that it could actually replace the built-in camera app. And since the built-in camera app adds geolocation, along with a lot of other metadata to the images, Snap had to do this too.

I present to you my NSMutableDictionary category that will solve all your problems. Ok, maybe not all, but the ones related to image metadata on iOS anyway.

For those with no patience, here’s the GitHub repo: https://github.com/gpambrozio/GusUtils. The repo contains an XCode project that should compile a nice static library for you to use on your projects. I plan on add a lot of utility classes here, so you might just want to pick and choose whatever you need to use instead of using the whole library.

The category is easy enough to use if you check out the code, but I’ll explain a few things on how to use it for those that never had to deal with image metadata on iOS before.

Who is this metadata person anyway?

For those of you that have no idea what I’m talking about, image metadata is most commonly known as EXIF data, even though that’s slightly wrong because EXIF data is only one type of metadata that can be embedded in an image file. My category deals with EXIF metadata, as well as with TIFF and IPTC metadata, depending on what kind of information you want to add to the image.

For example, the Original Date of an image can be embedded inside an EXIF property or inside a TIFF property. My category knows this and if you want to embed this date it will set both properties for you.

You can see all this metadata using most image viewers. On OSX, if you press cmd-i on the Preview app you can see an image’s metadata.

How does it work on iOS?

iOS SDK 4.1 introduced some methods that allowed an app to write image metadata in an image. One example is ALAssetsLibrary’s:

- (void)writeImageToSavedPhotosAlbum: metadata: completionBlock: completionBlock

That takes a NSDictionary as the metadata source. What the documentation doesn’t explain (or at least I could not find) is how this dictionary should be. I googled a lot and found some examples online that I used as a starting point for the category (sorry, can’t remember most of them…).

Turns out that this dictionary consists of a lot of other NSDictionaries with key/values that are dependent on the type of metadata you’re adding. You can find all the dictionaries that go inside this dictionary (I know…. even I’m getting confused with so many dictionaries…) in the CGImageProperties Reference of the documentation.

I’ll try to explain with an example. Say you want to add a “Description” property in your image. This property sits inside the TIFF dictionary. So, in order to add this information to your metadata dictionary you can use this code:

NSMutableDictionary *tiffMetadata = [[NSMutableDictionary alloc] init];
[tiffMetadata setObject:@"This is my description" forKey:(NSString*)kCGImagePropertyTIFFImageDescription];
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setObject:tiffMetadata forKey:(NSString*)kCGImagePropertyTIFFDictionary];

Why am I using NSMutableDictionary? Well, in this example you really don’t have to, but say you want to add another TIFF property to your metadata, with NSMutableDictionary you can just add another key/value to the tiffMetadata dictionary. If you used NSDictionary you’d have to create a new NSDictionary with the old key/values plus the new key/value. Not cool….

Adding geolocation is even harder. Geolocation has it’s own dictionary with a lot of possible values that are NOT explained in the documentation. The best information I found about this was in this StackOverflow question that I used as the basis for my implementation.

Please, help, I don’t want to do this…

The NSMutableDDictionary+ImageMetadata category takes all this complexity away from your code. To add geolocation to your metadata dictionary, all you have to do is this:

NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
[metadata setLocation:location];

Where location is a CLLocation instance. That’s it. My category will create the appropriate dictionary and add it to your NSMutableDictionary with all the appropriate key/values. I’ve implemented some other interesting setters and there are some helper methods that make it very easy to add methods for other properties:

- (void)setLocation:(CLLocation *)currentLocation;
- (void)setUserComment:(NSString*)comment;
- (void)setDateOriginal:(NSDate *)date;
- (void)setDateDigitized:(NSDate *)date;
- (void)setMake:(NSString*)make model:(NSString*)model software:(NSString*)software;
- (void)setDescription:(NSString*)description;
- (void)setKeywords:(NSString*)keywords;
- (void)setImageOrientarion:(UIImageOrientation)orientation;

 

After setting all your properties, you can call ALAssetsLibrary’s – writeImageDataToSavedPhotosAlbum:metadata:completionBlock: or – writeImageToSavedPhotosAlbum:metadata:completionBlock:. using your very special NSMutableDictionary and you’re all set!

Getting metadata

There’s another hard to find issue with metadata and that’s getting it from an image you just took using UIImagePickerController or an AVCaptureStillImageOutput. I’ll deal with this problem in another post but rest assured that out friendly category will help you a lot too. (UPDATE: The reading part in on this blog post)

Can I use this?

Yes, use it, fork it, spread the word. And if you make any improvements to your fork, or if you found a bug or a better way to do things, please send me a pull request so that I can incorporate your improvements into the main branch.

And if you really want t help me out and get a nice app at the same time, get Snap for your iPhone. Best 2 bucks you’ll spend today!

Porn amateur webcam porn amateur webcam. Home treatment for bv infection home treatment for bv infection. Webcam free chat sex webcam free chat sex. New otc diet pill 2013 new otc diet pill 2013. Home cure for bv home cure for bv. Free cam shemales free cam shemales. Vitamin b hgh vitamin b hgh. Copper for arthritis pain copper for arthritis pain. Shemale live webcam free shemale live webcam free. Recovery after ruptured ovarian cyst recovery after ruptured ovarian cyst. Tinnitus inhibitor price tinnitus inhibitor price. Acai plants for sale uk acai plants for sale uk. Pcos stop hair loss pcos stop hair loss. Free acai berry trials australia free acai berry trials australia. Treating bv naturally treating bv naturally. Zovirax cream coupons zovirax cream coupons. Increase egg quality pcos increase egg quality pcos. Hemorrhoids delivery baby hemorrhoids delivery baby. Vaginitis holistic vaginitis holistic. Phentermine 37.5 mg tablets 90 phentermine 37.5 mg tablets 90. Stereo hearts piano sheet easy stereo hearts piano sheet easy. Bv wine prices bv wine prices. Arthritis pain lotion arthritis pain lotion. Hgh supplements research hgh supplements research. Ovarian cysts holistic approach ovarian cysts holistic approach. Lose weight at home lose weight at home. Cure teeth clenching cure teeth clenching. Best hair loss treatment men best hair loss treatment men. After hemorrhoid surgery pain after hemorrhoid surgery pain. Psoriasis under tongue psoriasis under tongue. How to get rid of ringing in ear how to get rid of ringing in ear. Piano wire breaking strain piano wire breaking strain. 100 pound weight loss stories 100 pound weight loss stories. Treat heartburn fast treat heartburn fast. Acai berry xtra reviews acai berry xtra reviews. Videos web cam porno videos web cam porno


Keep tuned for more technical and non technical posts. You can subscribe by email, RSS or following me on twitter.


Email This Post Email This Post
  • Pingback: Post about a nice color picker for iOS - iPhone Dev SDK Forum

  • Pingback: Nice article on writing metadata on images on iOS - iPhone Dev SDK Forum

  • Pingback: Adding Image Metadata at Under The Bridge

  • Pingback: Tutorial: Adding Metadata to iOS Images | iPhone, iOS 4, iPad SDK Development Tutorial and Programming Tips

  • Ksaran76

    nice article..but i have a question..i’m a newbie in iphone development..maybe the question i ask is stupid…

    how do we get the “currentLocation” object.  Your comment says its an CLLocation instance.  is it a blank instance? or do we need to get it from imagepicker or something?

    Thanks,
    S

    • Anonymous

      Check out CoreLocation to understand how to get it from the GPS. But you can also get it from existing images. I’ll address these issues on my next blog post this wednesday. Keep tuned!

      Em 24/05/2011, às 06:49 AM, “Disqus” escreveu:

      • http://ihatenostradamus.com KruptWorld

        when i compile “NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
        [metadata setLocation:location];” it says location not declared.. im such a noob, please help! lol

        • Flexmcpee

          Hey did you manage to save the gps location to the image in the end i like you have struggled with the saving/merging with the image?

      • http://www.ihatenostradamus.com KruptWorld

        ok. i fixed the location part. now im stuck at putting the nsmutabledictionary into the uiimage. basically what im trying to achieve is someone takes a picture, then the gps data is added into the uiimage (thats where your code comes in ;) thank you) then that image is uploaded to a server.

        where im stuck is i put the code “NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];

        [metadata setLocation:location];”

        into where im getting the location so it looks like this…

        - (void)locationUpdate:(CLLocation *)location {
        NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
        [metadata setLocation:location];}the person takes a picture like this…- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo {
        [picker.parentViewController dismissModalViewControllerAnimated:YES];
        imageView.image = image;
        }how to i merge the data to the image? i would like to upload this image to my server, which a php code handles it and extracts the gps data.thank you so much for your help, time, code!

        • http://twitter.com/codecrop CodeCrop Software

          This is tricky using only iOS API. I use it to write to the camera roll, so it’s easy using ALAssetsLibrary:

          - (void)writeImageToSavedPhotosAlbum:(CGImageRef)imageRef metadata:(NSDictionary *)metadata completionBlock:(ALAssetsLibraryWriteImageCompletionBlock)completionBlock.

          What you can do is upload the GPS data as a separate field while uploading the image and you won’t even have to extract the data then…

          • KruptWorld

            I was thinking about doing like that, but its a script for google kml, which gets created based on the images in the folder. Adding or deleting would be a little messy i think.

            I put in that code and i see the image is saved and the only thing i see different in the exif data is now the exif ver. Is there! Wahoo, thats a step for me lol. Im still confused on how to save the gps data into the image. Also is it possible i save the photo in the documents part of the app so i dont fill up the users camera roll?

            Thank you once again!

          • Ideaignitor

             Hi . .I just read the things … & even i am looking for what you have already done earlier. Also, can you please share the project on Github ,since I was not to get it. Otherwise pls mail me on : ideaignitor@gmail.com

          • http://ihatenostradamus.com KruptWorld

            to be clear, there is no “gps” group in the exif, like the pictures taken with the native camera app. do i need to put code to “show” that group? as in there is no spot that says latitude and would show me any value in it.

          • http://www.ihatenostradamus.com KruptWorld

            eureka! i got it!! thank you so much for taking the time to help me out and writing this library. there’s no way i could have done this without you! i think i’ll put up an example in github because man that was pretty tough for someone like me who is making an app for the first time lol.

      • Flexmcpee

        Hello I am trying to achieve the same result as kruptworld however i can’t seem to get it work my code is below.

        - (void)locationUpdate:(CLLocation *)location {
            
            
            NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
            [metadata setLocation:location];
            
            
           
            NSLog(@”Our metadata again %@”, metadata);
            
            
            
        }I can see the location data in the log however how do i write it to the below method as it does recognise location commented out below. Any help greatly appreciated I am sure its simple but I couldn’t figure it out. I can write the below tiff data as mentioned on your blog but not the location data?-(void) imagePickerController:(UIImagePickerController *) picker didFinishPickingMediaWithInfo:(NSDictionary *)info

        {
               
            
            
            NSMutableDictionary *tiffMetadata = [[NSMutableDictionary alloc] init];
            [tiffMetadata setObject:@"This is my description" forKey:(NSString*)kCGImagePropertyTIFFImageDescription];
            NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
            [metadata setObject:tiffMetadata forKey:(NSString*)kCGImagePropertyTIFFDictionary];
            //    [metadata setLocation:location];
                
            NSLog(@”Metadata %@”, metadata);
            
            
             
                       
            
            UIImage *image = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
            
        //    // Save image
        //    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
            
            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

            [library writeImageToSavedPhotosAlbum:[image CGImage] metadata:metadata completionBlock:nil];

            
            
            [self dismissModalViewControllerAnimated:YES];
            
            [self performSelector:@selector(emailImage:) withObject:image afterDelay:1.0];
            
            [picker release];
            [library release];
            

        • Anonymous

          First: There’s a setDescription method in the category, use that to set your description! The category has so much more than just location.
          Second: It should work. One thing another user brought to my attention. These do not work with PNG images, just JPG. So, if you’re picking a screenshot it’s a PNG and it won’t write any metadata

          • Flexmcpee

            Hi codecrop ok I will try to give that a try. Thanks for replying firstly! Yeah in my location log I can see lots of info for the GPS I just couldn’t work out how to add the data to the metadata In the pickerdidfinsihpickingmediawithinfo as it doesn’t recognise [metadata setlocation:location]; in the update location it does but as u know I want to write the data to the metadata. If I just wanted the long and lat would you have some sample code as I’ve struggled a good few days with this…as a thank you I’ll download Snap

          • Flexmcpee

            Ok another problem that is driving me nuts. When I add your .h and .m files for your category and try to compile i get the below when I change to armv6 i get the same. I am just dragging your files from your project into mine however your guide says compile and static library do I also need to do that?

            This process so far is really not easy so any help is appreciated!

             ”_CMCopyDictionaryOfAttachments”, referenced from:
                  -[NSMutableDictionary(ImageMetadataCategory) initWithImageSampleBuffer:] in NSMutableDictionary+ImageMetadata.o
            ld: symbol(s) not found for architecture armv7
            clang: error: linker command failed with exit code 1 (use -v to see invocation)

          • Flexmcpee

            If I comment out this it compiles however do I need this?
             - (id)initWithImageSampleBuffer:(CMSampleBufferRef) imageDataSampleBuffer {
                
                // Dictionary of metadata is here
                CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate);
                
                // Just init with it….
                self = [self initWithDictionary:(NSDictionary*)metadataDict];
                
                // Release it
                CFRelease(metadataDict);
                return self;
            }

          • Anonymous

            Linker problems are usually the result of a missing framework. In your case CoreMedia. Just add this framework to your project and it will solve the problem.

          • Flexmcpee

            Thankyou simple when u know how. I got every thing else working today so it’s all good. Thanks a lot for this great code!

  • Pingback: The CodeCropper » Getting metadata from images on iOS.

  • http://www.tracks.io Tom Corwine

    Thanks! This save me some headaches.

  • http://www.mspy.com/ Watslaw

    I definitely enjoyed reading it, you may be a great author.I will make sure to bookmark your blog and will often come back someday.

  • http://www.sufalamtech.com/iphone-application-development.php iPhone Developer UK

    What I would like to do is have the photo taken in DVC #1 be saved as image #1 and show up every time I open DVC #1 and then when I open DVC #1 and take a photo it is saved as image #2 and stays displayed in it and so forth and so on. First off is this possible? And admitting that I am rather new to coding and I think here way over my head could someone help me accomplish this. 

    • Gustavo

      I’m not sure I understood your use case but it seems like you want a camera that only changes the image once you takema picture. If that’s the case, yes, you can do this.

      As you’re new to programming I’d suggest you read a few tutorials on Ray Wenderlich’s site: http://www.raywenderlich.com/tutorials and then find a nice tutorial that shows you how to capture images from the camera.

      Best of luck to you

  • Mike A.

    Is there any way to save the image to the Documents folder, rather than using writeImageDataToSavedPhotosAlbum:metadata:completionBlock?  Thanks.

    • http://blog.codecropper.com/ Gustavo Ambrozio

      Using the iOS API it’s not possible, not with metadata. If you want to save without the metadata you can use 

      UIImageJPEGRepresentation or UIImagePNGRepresentation. These methods return an NSData object with the correct format. Alternatively you can try using this lib: http://code.google.com/p/iphone-exif/

  • Mark Chouinard

    Wow.  You’re a lifesaver.

    Thank you!

  • Andrew

    nice thing. What about if I want just add some metadata to the existing set?

    • http://blog.codecropper.com/ Gustavo Ambrozio

      There’s no way to edit the images in the camera roll if that’s what you’re asking. You’d have to read, modify and write a copy of it.

  • orthorim

    Hey – Much appreciate the library. I was comparing the metadata returned by the iOS assets library with the metadata generated by the category & noticed some differences.

    I just got the CLLocation from the asset (an image from the library taken with the stock iOS camera app).
    - Timestamp seems to be wrong – However, the GPS timestamp in iOS is weird and seems to make no sense, it’s just a UTC hour, without date. Still, should probably be the same when written with the library.- Altitude is missing in the category.I’ll fix these…    // iOS ALAssetLibrary metadata
            “{GPS}” =     { 
            Altitude = “314.5499″; 
            AltitudeRef = 0; 
            Latitude = “18.779″; 
            LatitudeRef = N; 
            Longitude = “99.00149999999999″; 
            LongitudeRef = E; 
            TimeStamp = “02:44:36.46″; 
        }; 

    // Category metadata using same CLLocation object
        “{GPS}” =     { 
            Altitude = 0; 
            AltitudeRef = 0; 
            DOP = 0; 
            Latitude = “18.779″; 
            LatitudeRef = N; 
            Longitude = “99.0015″; 
            LongitudeRef = E; 
            TimeStamp = “2012-07-12 07:47:15 +0000″; 
        }; 

  • http://www.arthisoft.com/ Arth I-Soft

    Wow!! it’s great to adding metadata to an iOS images which are use in iPhone, It’s looking great.

  • orthorim

    So this method is very problematic: initWithInfoFromImagePicker

    If this is loading from the assets library, then the call to set the meta data is asynchronous. That means in the code following the ‘initWithInfoFromImagePicker’, nothing has actually been initialized yet!

    I recommend you fix this. An init method in my opinion should return an initialized object. It should not return an object that gets initialized some time later in a background thread!

  • LayerLapse

    My developer says he is having a problem to save image to camera roll having a different timestamp than the current time of when it is added to camera roll. My app stores images and then adds them later to camera roll so you can then share with other app users but the other app users need the correct time for the app to work properly. Can you please tell me what to tell my dev so he will know what to do?

  • http://www.facebook.com/people/Sijun-Jia/604160155 Sijun Jia

    I’m catching video in my app. Do you have any suggestions on how to add meta data into the video?

  • Rob Wilco

    For those having linker troubles: Be sure to link your binary with CoreMedia and ImageIO frameworks!

  • Pingback: The CodeCropper » Adding metadata to iOS ...

  • Michal Glowacki

    Thank for this post? Is there a way to read all photos from photo library into a nativate application? can this be done using stuff like phonegap?

  • Pingback: Is it possible to retrive an existing iPhone image’s metadata (specifically geolocation data) using PhoneGap? | Yannone Answers