reading android jpeg EXIF metadata from picture callback reading android jpeg EXIF metadata from picture callback android android

reading android jpeg EXIF metadata from picture callback


To read metadata/EXIF from image byte[] (useful for Camera.takePicture()) using version 2.9.1 of the metadata extraction library in Java by Drew Noakes:

try{    // Extract metadata.    Metadata metadata = ImageMetadataReader.readMetadata(new BufferedInputStream(new ByteArrayInputStream(imageData)), imageData.length);    // Log each directory.    for(Directory directory : metadata.getDirectories())    {        Log.d("LOG", "Directory: " + directory.getName());        // Log all errors.        for(String error : directory.getErrors())        {            Log.d("LOG", "> error: " + error);        }        // Log all tags.        for(Tag tag : directory.getTags())        {            Log.d("LOG", "> tag: " + tag.getTagName() + " = " + tag.getDescription());        }    }}catch(Exception e){    // TODO: handle exception}

To read the EXIF orientation of the image (not the orientation of the thumbnail):

try{    // Get the EXIF orientation.    final ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);    if(exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION))    {        final int exifOrientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);        /* Work on exifOrientation */    }    else    {        /* Not found */    }}catch(Exception e){    // TODO: handle exception}

The orientation is from 1 to 8. See here, here, here or here.


To transform a bitmap based on its EXIF orientation:

try{    final Matrix bitmapMatrix = new Matrix();    switch(exifOrientation)    {        case 1:                                                                                     break;  // top left        case 2:                                                 bitmapMatrix.postScale(-1, 1);      break;  // top right        case 3:         bitmapMatrix.postRotate(180);                                               break;  // bottom right        case 4:         bitmapMatrix.postRotate(180);           bitmapMatrix.postScale(-1, 1);      break;  // bottom left        case 5:         bitmapMatrix.postRotate(90);            bitmapMatrix.postScale(-1, 1);      break;  // left top        case 6:         bitmapMatrix.postRotate(90);                                                break;  // right top        case 7:         bitmapMatrix.postRotate(270);           bitmapMatrix.postScale(-1, 1);      break;  // right bottom        case 8:         bitmapMatrix.postRotate(270);                                               break;  // left bottom        default:                                                                                    break;  // Unknown    }    // Create new bitmap.    final Bitmap transformedBitmap = Bitmap.createBitmap(imageBitmap, 0, 0, imageBitmap.getWidth(), imageBitmap.getHeight(), bitmapMatrix, false);}catch(Exception e){    // TODO: handle exception}


The bad news:

Android Api sadly won't allow you to read exif data from a Stream, only from a File.
ExifInterface don't have a constructor with an InputStream.So you must parse jpeg content by yourself.

The good news:

API exists in pure Java for this. You can use this one: https://drewnoakes.com/code/exif/
It's Open Source, published under Apache Licence 2 and available as a Maven package.

There is a constructor with an InputStream:public ExifReader(java.io.InputStream is)

You can build an InputStream backed by your byte[] using a ByteArrayInputStream like this:

InputStream is = new ByteArrayInputStream(decodedBytes);


AndroidX ExifInterface supports reading EXIF information from an inputstream:

implementation "androidx.exifinterface:exifinterface:1.1.0"

You can then just pass the inputstream into the constructor like that:

val exif = ExifInterface(inputStream)val orientation =        exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)