Parsing Exif Data From Images on Mobile Devices

If you’re interested in parsing Exif data from images on devices using AIR, you’re in the right place. But first, a little background to put this example in context.

Someone asked me a really good question at MAX about getting metadata about images on mobile devices. I don’t recommend using the file property of MediaPromise to get a reference to images because it doesn’t work across platforms (it works fine on Android, but not on iOS — for more information, see How to Use CameraUI in a Cross-platform Way), so that means you don’t have access to certain properties on File like creationDate, size, etc. The best way to get information about images on mobile devices, therefore, is to parse out the image’s Exif data.

Exif stands for "Exchangeable image file format," and it provides a way for digital cameras and applications to encode information about images directly in the images themselves. In other words, Exif is to images what ID3 is to MP3 files. Since the data is image-specific, it is typically much richer than information associated with a file reference. Of course, it’s also a little bit harder to get to, so I figured I would write a sample application to demonstrate one way of doing it.

ExifExample (Github project, Flash Builder project) is a simple application which allows the user to either take a photo, or browse to a photo already on the device, and then uses the ExifInfo library to parse the Exif data out of the image. The code is pretty simple, but there a few things to pay special attention to:

  1. I don’t use the file property of MediaPromise to access the image. As I mentioned above, that would work on Android, but it doesn’t work on iOS, and it’s not guaranteed to work on other platforms in the future. Instead, I use a MediaPromise to either synchronously or asynchronously get at the bytes of the image.
  2. I only read the first 64K of the image before parsing out the Exif data. Exif data has to be within the first 64K of an image which makes dealing with very large files much easier. If you’re downloading them, it saves time and bandwidth, and in the context of a mobile application, it saves memory. Now that the resolution of cameras on mobile devices is getting so high, you might not want to read entire images into RAM. (When mobile applications run out of memory, they tend to be shut down with little or no warning, so keeping your memory footprint as low as possible is always a good idea.) This is especially important if you want to display the thumbnails of multiple photos in a grid or list.
  3. Although the application supports both taking a picture using CameraUI and selecting a picture using CameraRoll, all the code that deals with the MediaPromise (both synchronous and asynchronous) is shared. If you have an application that supports both paths, I would recommend using this type of architecture in order to simplify your codebase.
  4. Even though this application is designed to run on mobile devices, it also supports selecting an image from a hard drive using the File.browseForOpen() function. If there’s an opportunity to add desktop functionality into a mobile application, I will usually do it since the more I can use and debug the application on the desktop before running it on a mobile device, the faster and smoother the development process goes. In order to support selecting an image from the desktop, I only had to add an additional 20 lines of code, and it definitely saved me much more time in testing and debugging than it cost me.

I should point out that this sample is not intended to highlight any particular Exif parsing library. I used the ExifInfo library because of its favorable license (MIT), but there are other libraries out there, as well (none of which I tried, so I can’t vouch for them). I should also point out that I had to modify the library according to Joe Ward’s instructions here in order to get it to work properly on iOS.