0

I have an app with an Android client and an iOS client. They share a common server to where they both upload photos as base64 string. The problem occurs when an iOS user uploads a photo that they snapped with the camera from within the app. Those photos are then rotated 90 degrees on the Android client.

I've understood that there is something called "Exif" where one can locate metadata, such as rotation, but I guess that data is lost when the photo comes as a base64 string?

Could this by a reliable solution?

if (width > height){
    photoBitmap = rotate(photoBitmap,90f)
}

I also tried the suggestion found here: Reading EXIF data from byte array in android but that only gives me "Orientation not found" when I transform my bitmap as a byte array and use it as input to the method getOrientation(byte[] jpeg).

Any tips on how to solve this the correct way? Should the fix be in the Android client or the iOS client?

Bonifacio2
  • 3,405
  • 6
  • 34
  • 54
matphi
  • 173
  • 3
  • 8
  • The data shouldn't be lost when the data comes as a base64 string, as it's embedded in the JPEG data itself (I assuming you're dealing with JPEG.) You may need to trace through your process step-by-step to find out exactly where you're losing the information. (Bear in mind that this won't happen with every photo, as iOS photos taken in "natural sensor" orientation won't have the rotation set.) (I doubt you'll get EXIF data out of a bitmap byte array, though; it's already been converted from JPEG at that point.) – Matt Gibson Apr 14 '18 at 11:03
  • First thing I'd try is to look at one of the "problem" photo files from the server and see if it's got EXIF information. There are JPEG metadata viewer tools for most platforms where you can just drag the JPEG file to them and they'll show you the orientation data. Bear in mind that some actual image viewers/web browsers, etc. will respect the EXIF rotation and some won't, so you can't always tell by just viewing the image! – Matt Gibson Apr 14 '18 at 11:06

1 Answers1

0

As commented, the EXIF data was never lost. For me to get around this problem, I had to store the bitmap as file, and from the file I was able to fetch the EXIF data.

This code did the trick:

private fun handleRotation(photoBitmap: Bitmap): Bitmap {
    var photoBitmap1 = photoBitmap
    val filename = "tempPhotoFile"
    this.openFileOutput(filename, Context.MODE_PRIVATE).use {
        it.write(photo!!.data)
    }

    val ei = ExifInterface(getFilesDir().path + "/" + filename)
    val orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
            ExifInterface.ORIENTATION_NORMAL)

    when (orientation) {
        ExifInterface.ORIENTATION_ROTATE_90 -> photoBitmap1 = rotateImage(photoBitmap1, 90f)
        ExifInterface.ORIENTATION_ROTATE_180 -> photoBitmap1 = rotateImage(photoBitmap1, 180f)
    }

    return photoBitmap1
}

private fun rotateImage(bm: Bitmap, rotation: Float): Bitmap {
    if (rotation != 0f) {
        val matrix = Matrix()
        matrix.postRotate(rotation)
        return Bitmap.createBitmap(bm, 0, 0, bm.width, bm.height, matrix, true)
    }
    return bm
}
matphi
  • 173
  • 3
  • 8