Thursday, June 19, 2008

Geo Tagging images using iphone-exif

The GeoTagging of photos can be really useful. Flickr and Picasa can both use Exif data embedded into an image to generate the Map locations displayed on the site. The only downside is that it is quite tricky to do this directly on the phone.

There are a number of solutions to do this on the PC or by uploading to the site and then tag each image or image folder with  a location, but it is another step when you really want to do it all at once.

I ended up creating a static C/Objective-C library that allows reading/editing and deleting standard Exif tags directly on images on your iPhone. 

This is a quick guide to getting it set up in your project. The Exif spec is a bit tedious and can be found at www.exif.org/Exif2-2.PDF.

Add Into Xcode
Download the library from code.google.com/p/iphone-exif  and unzip into a directory. The zip file contains a static library which you must add into the project as a dependency. then place the header files into your source directory and you are good to go. This is not a dynamic library as the application must ship with the code embedded, it will not be on the iPhone to link with like the framework files you use.

Getting Started
NOTE: The 0.8 version of the library expects a logging variable to be declared - just add it into the AppDelegate .m class like so:

BOOL gLogging = FALSE;


this controls whether internal log statements are echoed to standard out.


The initial task is to parse the Jpeg file data to extrac the Exif data.
This we achieve in the following lines
NSData* theImageData = UIImageRepresentation(anImage,1.0);
EXFJpeg* jpegScanner = [[EXFJpeg alloc] init];
[jpegScanner scanImageData: theImageData];

This will scan the image and extract any Exif data. 

The ExifJpeg class gives us an interface that provides access to the Exif data and the JFIF tags using the properties:

EXFMetaData* exifData = jpegScanner.exifMetaData;
EXFJFIF* jfif = jpegScanner.jfif;

The EXFMetaData class is where most of the work is done. It allows us to 
  • retrieve a tag definition
  • get a list of child tags
  • get a value for a tag
  • remove a tag value
  • add a remove a custom handler
  • get a list of all the tag values.

Retrieving a tag definition
The tag definition details the id, data type, short string name, parent tag, and the number of components (see the Exif Spec for details) it can occupy.

EXFTag* tagDefinition = [exifData tagDefinition: aTagId];

Getting a list of child tags for a parent
NSMutableArray* tagDefinitions = [exifData tagDefinitionsForParent:aTagId];
Getting a value for a tag
The value is an id as it could be a Numeric value, a String, a binary type, or a type provided by a custom tag handler.
id tagValue = [exifData tagValue: aTagId];
Add a tag value
[exifData addTagValue: aValue forKey: aTagId];

Remove a tag value
[exifData removeTagValue:aTagId];
There is obviously a requirement to know what the tagIds are, and these are available in the spec. The EXFConstants.h file also has a defined set of constants to make it easy to see what these are.

Part II
The second post will deal with adding custom handlers and a discussion of the data types, especially around the GPS tag set.








8 comments:

tim said...

Hi,
I was directed to this code from the following thread.

http://discussions.apple.com/thread.jspa?threadID=1603384&tstart=120

I'm having trouble getting the line

NSData *theImageData = UIImageRepresentation(anImage, 1.0)

to work. I don't think UIImageJPEGRepresentation is what I want, since this strips the EXIF data, but UIImageRepresentation doesn't work.

I'm trying to use this library but I need the NSData* object, and all I have to start with is a UIImage* object.

Can anyone help?

steve woodcock said...

Hi Tim,
Unfortunately, Apple's API strips out the EXIf, There is no way for you to access these tags for images from the photo library or saved folder.

The library will allow you to add your own EXIF tags to the Image, but again until Apple fix this (I suggest you raise a bug report) - you are pretty much stucj reading and writing images from your App's directory.



The NSData reference is that you really need to read the file in from your own directory as an NSData block and then construct an image from that

Larry A. said...

Hi Steve,

I like your iphone-exif library and would like to use it in my project. However, the GPL license is preventing me from using it. Would you consider releasing the code under a BSD style license?

Thanks,
Larry

tmarbois said...

do you know if the new 3GS adds any location aware data into/with the video? We want geotagged videos from the phone - emailed into my service:

http://www.blipback.com

Currently we can parse location from helio phones but in that one the location is smartly added into the email as xml... Is there a way to grab geocoded information from videos / photos that are emailed from the iPhone?

Antonio Virzì said...

Hi Steve,

I was wondering whether you could share some sample code to better understand the whole geo tagging process.

I am missing something right now and a proper example would be great.

Thanks,
Antonio

johnny said...

Hello Steve,

Can I use your code in my paid iPhone Camera apps (BlueCam and ZCam) if I credit you on iTunes?

I just added Flickr upload support to these Apps and am working on geotagging with EXIF data.

Thanks,
Johnny

Manuele said...

Hi Stevie,

How can I use iphone-exif for projects which are not GPL compliant?

Regards

Manu

Unknown said...

+1 on getting non-GPL secondary license (as mentioned on the page)

please email me back.