Copy EXIF metadata on Android

Almost every application working with camera at some point will need to resize pictures. And a pity thing about resizing is that usually all EXIF metadata will be missing in resized picture. We should manually copy all the EXIF tags from source file to the resized one. Unfortunately, Android's ExifInterface is not capable of copying *all* the tags from source file. Depending on Android version it will have different set of supported tags.

Apache Commons Imaging (ex. Sanselan) is a Pure-Java library that reads and writes EXIF metadata. You will find various samples of usage showing how to read and write EXIF metadata using this library.

Let's see one of the examples available online: It shows how to copy EXIF metadata from one image to another using Sanselan library. All looks pretty simple. EXIF metadata is structured as a set containing directories and every directory contains tags. The code in example will iterate over all directories and copy every single tag from one picture to another. Seems to be fair, but it is not.

Let's take precise look at getSanselanOutputSet(File jpegImageFile) method.
On line #109 comment says that we should create empty set of EXIF metadata in case destination file doesn't have one. But as we already learned image doesn't have any EXIF metadata after it was resized. It means we will always create new set for the resized image. TiffOutputSet class has two constructors: one empty constructor and one which takes byteOrder as attribute. In example we can see empty constructor used on line #113. And this is wrong.

From my experience camera application on two different Android devices was setting different byte order in EXIF header of picture file. Nexus 4 used big-endian and some unknown Chinese device used little-endian byte order. Sanselan library uses little-endian by default. This leads to the following on Nexus: EXIF metadata is read from big-endian file and then directly saved to little-endian file without any modifications. Data doesn't get corrupted, but any application which will read EXIF metadata from this file will read it wrong.

To avoid this problem we should either use the same byte order for both files, or transform bytes for every field copied between files. In my experience I had problem with GPS coordinates being corrupted. In source file I had 49 deg 59' 45.3332", but after copying I had 49 deg 59' 13.1816".

Comments (1): leave a comment

  • Paul on December 20, 2014 at 11:02
    Vladimir, I had the same problem with GPS coordinates using Snaselan library in my app, but couldn't find out the reason. For some devices the GPS coordinates and some other EXIF-tags were corrupted after copying.
    As you pointed, I used the empty constructor new TiffOutputSet(). I changed it to TiffOutputSet(byteOrder) from source and it's working perfectly now!
    Thank you very much!!!

Leave a comment