Android image resizing and preserving EXIF data (orientation, rotation, etc.)
If your Android app uses the device camera to take a picture and then resizes it (this is very, very common to reduce the size for upload), you might not realize that this resize operation strips the Exif metadata.
This can cause problems, especially if the device in question relies on the 'Orientation' tag to properly show the image upright.
Different Android devices handle camera/image rotation in different ways - my trusty old Nexus One seems to always rotate the image immediately post capture, so the file's native contents are always 'upright' when viewed.
However, other devices (especially Samsung phones in my testing), do not rotate the contents of the image file - rather, they set the Exif 'Orientation' tag. Whenever the image is displayed later, the relevant image code should detect the presence of the Orientation 'tag' and rotate the image appropriately. But if you have done any bitmap processing on the image and saved it to a new file, all of that Exif data is lost.
In addition to Orientation data, you might also lose other valuable metadata such as make/model, etc.
This confused me for a few weeks (image appears upright when displayed in phone gallery, but then arrives on my server with bad orientation and no apparent metadata). I'm adding this self-question here to help others. This blog post was very helpful:
Android re-size image without loosing EXIF information
Solution 1:
As far as I can tell, there is no mechanism to persist the metadata automatically or even snapshot whatever is there and transfer in bulk.
Rather, it seems you must explicitly check for specific properties and copy them yourself to the new image file using the ExifInterface.
http://developer.android.com/reference/android/media/ExifInterface.html
So something like:
ExifInterface oldExif = new ExifInterface(oldImagePath);
String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION);
if (exifOrientation != null) {
ExifInterface newExif = new ExifInterface(imagePath);
newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation);
newExif.saveAttributes();
}
Solution 2:
For the lazy ones, here's a reusable function:
public static void copyExif(String oldPath, String newPath) throws IOException
{
ExifInterface oldExif = new ExifInterface(oldPath);
String[] attributes = new String[]
{
ExifInterface.TAG_APERTURE,
ExifInterface.TAG_DATETIME,
ExifInterface.TAG_DATETIME_DIGITIZED,
ExifInterface.TAG_EXPOSURE_TIME,
ExifInterface.TAG_FLASH,
ExifInterface.TAG_FOCAL_LENGTH,
ExifInterface.TAG_GPS_ALTITUDE,
ExifInterface.TAG_GPS_ALTITUDE_REF,
ExifInterface.TAG_GPS_DATESTAMP,
ExifInterface.TAG_GPS_LATITUDE,
ExifInterface.TAG_GPS_LATITUDE_REF,
ExifInterface.TAG_GPS_LONGITUDE,
ExifInterface.TAG_GPS_LONGITUDE_REF,
ExifInterface.TAG_GPS_PROCESSING_METHOD,
ExifInterface.TAG_GPS_TIMESTAMP,
ExifInterface.TAG_IMAGE_LENGTH,
ExifInterface.TAG_IMAGE_WIDTH,
ExifInterface.TAG_ISO,
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
ExifInterface.TAG_ORIENTATION,
ExifInterface.TAG_SUBSEC_TIME,
ExifInterface.TAG_SUBSEC_TIME_DIG,
ExifInterface.TAG_SUBSEC_TIME_ORIG,
ExifInterface.TAG_WHITE_BALANCE
};
ExifInterface newExif = new ExifInterface(newPath);
for (int i = 0; i < attributes.length; i++)
{
String value = oldExif.getAttribute(attributes[i]);
if (value != null)
newExif.setAttribute(attributes[i], value);
}
newExif.saveAttributes();
}