18

In Android, when decoding a Bitmap from a photo on the phone, the EXIF data in the original gets lost. I am sending this Bitmap to my server via a socket and would like to re-attach the missing EXIF data to the data being sent.

I have some code that loads a Bitmap object from the MediaStore and compresses it to a byte array in preparation to send it over a socket:

Bitmap bitmap = ...
ByteArrayOutputStream stream = new ByteArrayOutputStream(bitmap);
bitmap.compress(CompressFormat.JPEG, 70, stream);
byte[] input = stream.toByteArray();

I want to use the ExifInterface to get at the EXIF metadata in the original jpeg on the SD card and somehow add that to the outgoing byte array in a way that I'd be able to extract a jpeg with all the correct EXIF on the server side (hopefully without doing this on the server). So far, I managed to use the ExifInterface to read all EXIF data:

String path = ... //bitmap file path
ExifInterface exif = new ExifInterface(path);
... = exif.getAttribute(...)

EDIT: Optimally, I'd like to find a solution that uses no libraries. If I could just get the indices of the byte array of the original jpeg that contain the EXIF and prepend/append these bytes to the byte array produced by bitmap.compress(...) that would be best.

Bugs Happen
  • 2,169
  • 4
  • 33
  • 59
Warlax
  • 2,459
  • 5
  • 30
  • 41

1 Answers1

7

Thanks to @Nick Campion and Sanselan.

Working code:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 100, bos); //Bitmap object is your image
byte[] data = bos.toByteArray();

TiffOutputSet outputSet = null;

IImageMetadata metadata = Sanselan.getMetadata(new File(filepath)); // filepath is the path to your image file stored in SD card (which contains exif info)
JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
if (null != jpegMetadata)
{
    TiffImageMetadata exif = jpegMetadata.getExif();
    if (null != exif)
    {
        outputSet = exif.getOutputSet();
    }
}
if (null != outputSet)
{
    bos.flush();
    bos.close();
    bos = new ByteArrayOutputStream();
    ExifRewriter ER = new ExifRewriter();
    ER.updateExifMetadataLossless(data, bos, outputSet);
    data = bos.toByteArray(); //Update you Byte array, Now it contains exif information!
}
Community
  • 1
  • 1
Vikas
  • 24,082
  • 37
  • 117
  • 159
  • The code above often does not work as expected with Sanselan Android. In particular, if you resize the image, the code above will not just copy the EXIF metadata but will also overwrite your image data, undoing the resizing. Seems to be a Sanselan issue others have come across: http://mail-archives.apache.org/mod_mbox/commons-user/201103.mbox/%3C1299887792.2107.26.camel@jonah-desktop%3E . I wrote about a workaround for this problem here: http://bricolsoftconsulting.com/2012/12/08/copying-exif-metadata-using-sanselan/ – Theo Dec 09 '12 at 02:39
  • It works fine with me. but `Sanselan` should point to https://commons.apache.org/proper/commons-imaging/ and `Sanselan.getMetadata` becomes `Imaging.getMetadata` – Leon Oct 18 '17 at 16:12
  • By the code I see the format saved is jpeg. Or do you mean even BMP supports exif ? Or even any other format than PNG and JPEG? – kAmol Nov 27 '20 at 15:00