0

I try to add simple functionality with getting picture from gallery or from camera in my Android app. And all works fine, I successfully obtain uri of picture and after that want to show this picture to user. And this code works well:

private fun showImageToUser(uri: Uri) {
    val inputStream = contentResolver?.openInputStream(uri)
    val bytes = inputStream?.readBytes() ?: return
    val bitmapOriginal = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
    // show bitmap in ImageView...
}

Then, I want to rotate image if need (for example, after camera all images have 90-degrees rotation). For this I use ExifInterface (from androidx.exifinterface:exifinterface:1.3.1). But there is something strange. In this code:

private fun showImageToUser(uri: Uri) {
        val inputStream = contentResolver?.openInputStream(uri)

        val exifInterface = ExifInterface(inputStream ?: return)
        val rotation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)

        val bytes = inputStream.readBytes()

        val bitmapOriginal = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
        val bitmapRotated = bitmapOriginal.rotateImageIfRequired(rotation) // simple logic for rotating in rotateImageIfRequired method...
    }

the bitmapOriginal is always null. As you can see, I create exifInterface object before inputStream.readBytes(). If I swap them, and try to run the following code:

private fun showImageToUser(uri: Uri) {
    val inputStream = contentResolver?.openInputStream(uri)
    val bytes = inputStream?.readBytes() ?: return

    val exifInterface = ExifInterface(inputStream)
    val rotation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)

    val bitmapOriginal = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
    val bitmapRotated = bitmapOriginal.rotateImageIfRequired(rotation)
} 

then bitmapOriginal will not be null, but the rotation value will be always ORIENTATION_UNDEFINED.

So, what am I doing wrong? How to get correctly bytes and image orientation from uri and create after that bitmap with correct orientation?

Alex D.
  • 1,424
  • 15
  • 40
  • The InputStream is in an invalid state. Reopen the stream or try to reset. Depends on that is the source of the stream. You can also ready the stream as bytes and then you do NOT need to reread the stream. – Олег Казьмин Dec 04 '20 at 09:16
  • @ОлегКазьмин reset doesnt work. It throws exception "Caused by: java.io.IOException: mark/reset not supported". – Alex D. Dec 04 '20 at 09:53
  • I tried to open two streams and it works fine in this case. But, I think it is not a good practice to open two inputStreams - one for byreArray and one for exifInterface. Or not? – Alex D. Dec 04 '20 at 10:22
  • 1
    There is no alternative as exif interface consumed the first part of that inputstream and left it useless for bitmap factory. – blackapps Dec 04 '20 at 10:35
  • As a variant you can read the bitmap into the byte array. Also, scale down if needed. Then pass this byte array to ExifInterface. Reopening streams is also ok I think. ExifInterface does not read the whole image. It only searches for the needed headers. The choice is yours. – Олег Казьмин Dec 04 '20 at 13:43

0 Answers0