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.

15 Responses to Parsing Exif Data From Images on Mobile Devices

  1. Kevin Hoyt says:

    I love Exif!

    I’ve found that under certain circumstances (TBD), device gallery applications will display image with the correct orientation for which the picture was taken. When loaded into AIR however, these sometimes load with an opposite orientation (e.g. taken in portrait will load in landscape). It’s as if the gallery application is checking the Exif information for orientation. Using an Exif library such as this can help solve that problem in AIR too – read the orientation and adjust as need.

    Exif also usually (not always) contains an already scaled down version of the full image as a thumbnail. That can speed things up from trying to do it yourself in ActionScript.

    I actually started a port of the same library you used here to JavaScript using the W3C File APIs (http://www.kevinhoyt.com/exifjs). My port is incomplete, but functional. Also posted on GitHub for anybody looking to contribute (https://github.com/parkerkrhoyt/ExifJS). All things being equal though, Exif access, scaling, and other common image manipulations seem like an ANE (or PhoneGap extension) screaming to be made. Or perhaps a Creative Cloud API waiting to be used?

    Nice post,
    Kevin

  2. The really good question was being asked by a really good artist/developer: Erik Natzke! 😉

    Besides that, thnx for coming back so quickly on that question…! 😀

  3. Dan says:

    Hi Christian,

    This is helpful thanks, and is getting me close to camera on iOS being usable, but is there any info on best practice for taking and using photos?

    Android is easy out of the box, but iOS (or iPhone at least) does not seem to work well – the orientation of the photos are incorrect.

    Am I missing something – I cannot believe that something as simple as taking and displaying a photo would be so troublesome.

    Thanks

  4. Joe Ward says:

    Dan, The reason this happens is because of the way the iOS camera roll returns saved images. The returned image has the image data stored in a standard rotation and an orientation value is set in the EXIF data. You have to rotate the image using this orientation value to get it to display right-side-up. At the same time, the iOS camera roll strips out most other EXIF information.

  5. Pingback: Cool Stuff with the Flash Platform - 10/24/2011 | Remote Synthesis

  6. Aaron says:

    Is there a particularly good/accepted way to handle the BitmapData from images taken with the camera once you do have them rotated? I was unaware of the exif data likely containing a thumbnail, but in cases where that isn’t available, what’s the best way to process a new image and store a thumbnail?

    Currently I’m attempting this with a loader, grabbing its BitmapData, scaling it and cropping it in a single draw() call with a Matrix and a Rectangle and handing it off to a PNGEncoder. This process is UI blocking on mobile despite the loader being asynchronous on a Nexus S, which isn’t the fastest device but is by no means on the bottom of the barrel of device performance.

  7. Saar says:

    hey Christian, thanx a lot

    one question: since we are already opening the mediapromise for reading the exif bytes can we keep reading all the bytes to get the entire picture/bitmapdata instead of using the loader.loadeMediaPromise()?

    (and register for event.complete instead of progressevent)

  8. Pac says:

    Weird, I’m getting exifBytes.length=0 on onMediaPromiseProgress.
    I tested it on Ipad.

    any clue?

    • Pac says:

      So I was loading the image right after trying to get the Exif data, like this:

      var mediaDispatcher:IEventDispatcher = cameraRollPromise.open() as IEventDispatcher;
      mediaDispatcher.addEventListener(ProgressEvent.PROGRESS, onMediaPromiseGetExifProgress);

      imageLoader.unload();
      imageLoader = new Loader();
      imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMediaPromiseCompleted);
      imageLoader.loadFilePromise(cameraRollPromise);

  9. Andrea says:

    Hey Christian, thank you very much for this post, really useful!

  10. Pingback: Getting photo orientation from EXIF data on iOS (AIR) | <igghera>

  11. Pingback: iOS: Pfad /var/mobile/Media/DCIM existiert nicht - Flashforum

  12. Johan says:

    Hey chris, thanks a lot for this demo.
    What I was wondering is how to get the gps / geo data from the exif.
    The Android version got it but the iOS version doesn’t.

    Any idea’s on this?

    I’am really stuck on this…

    thanks!

  13. Astraport says:

    Not work for iPad3 :(((