Android image resizing and preserving EXIF data (orientation, rotation, etc.)
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();
}
It's already 2019 and there is still no better answer than those proposed by @prom85, Mike Repass and Theo.
In 2016, Android team introduced ExifInterface Support Library what can be the best option if you want to have consisent behaviour between Android versions. I ended up creating a subset of tags ExifInterface#EXIF_TAGS
(source code) and I just iterate over this subset to extract metadata from input file and set it in an output. If you ever get a requirement to copy over all tags I recommend you to not do it! Value of some of the tags will need to be updated accordingly anyway (e.g. TAG_IMAGE_LENGTH
and TAG_IMAGE_WIDTH
). Personally, I kept asking questions why we need to keep all metedata data in the first place (it differs what you get between devices and camera you use anyway) and we realised that gps location and date/time data is as well need to keep.
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();
}
As others have indicated, you must copy the Exif data from the original image to the final resized image. The Sanselan Android library is typically best for this. Depending on Android OS version, the ExifInterface sometimes corrupts the Exifdata.
In addition, the ExifInterface also handles a limited number of Exif tags -- namely only the tags that it "knows" about. Sanselan on the other hand will keep all Exiftags and marker notes.
Here is a blog post that shows how to use Sanselan for copying image data:
Copying Exif metadata using Sanselan
BTW, on Android I also tend to rotate the images and remove the Orientation Exiftag. For example, on a Nexus S with Android 4.03, the camera was setting an orientation tag in the Exifmetadata, but the webview was ignoring that information and displaying the image incorrectly. Sadly, rotating the actual image data and removing the Exiforientation tag is the only way to get every program to display images correctly.