From c0ae4666ab2c15af73169f27a23a16fa04a45834 Mon Sep 17 00:00:00 2001
From: Kamal Bramwell <kamal@elixxir.io>
Date: Thu, 15 Dec 2022 12:42:32 -0500
Subject: [PATCH] Added logic to read exif data to apply correct photo
 orientation

---
 .../messenger/media/MediaProviderActivity.kt  | 54 +++++++++++++++++--
 1 file changed, 50 insertions(+), 4 deletions(-)

diff --git a/app/src/main/java/io/xxlabs/messenger/media/MediaProviderActivity.kt b/app/src/main/java/io/xxlabs/messenger/media/MediaProviderActivity.kt
index 50f44858..ee6f5af5 100644
--- a/app/src/main/java/io/xxlabs/messenger/media/MediaProviderActivity.kt
+++ b/app/src/main/java/io/xxlabs/messenger/media/MediaProviderActivity.kt
@@ -4,15 +4,24 @@ import android.Manifest
 import android.content.Context
 import android.content.Intent
 import android.graphics.Bitmap
+import android.graphics.Matrix
+import android.media.ExifInterface
 import android.net.Uri
 import android.os.Environment
 import androidx.activity.result.ActivityResultCallback
 import androidx.activity.result.contract.ActivityResultContracts
+import androidx.core.content.ContentProviderCompat.requireContext
 import androidx.core.content.FileProvider
 import androidx.core.content.PermissionChecker
+import androidx.lifecycle.lifecycleScope
 import io.xxlabs.messenger.BuildConfig
+import io.xxlabs.messenger.support.view.BitmapResolver
 import io.xxlabs.messenger.ui.base.BaseKeystoreActivity
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 import java.io.File
+import java.security.AccessController.getContext
 
 /**
  * Superclass for Activities that perform actions that require sensitive permissions
@@ -97,11 +106,48 @@ abstract class MediaProviderActivity :
     }
 
     private val cameraResultCallback = ActivityResultCallback<Boolean> { isSuccess ->
-        if (isSuccess) {
-            callback?.onFilesSelected(listOf(latestMediaUri))
+        lifecycleScope.launch {
+            withContext(Dispatchers.IO) {
+                if (isSuccess) {
+                    BitmapResolver.getBitmap(latestMediaUri)?.let {
+                        correctPhotoOrientation(it, latestMediaUri)
+                    }
+                    callback?.onFilesSelected(listOf(latestMediaUri))
+                }
+                callback = null
+                shouldStopNetworkFollower = true
+            }
         }
-        callback = null
-        shouldStopNetworkFollower = true
+    }
+
+    private fun correctPhotoOrientation(image: Bitmap, uri: Uri) {
+        val ei = ExifInterface(uri.path!!)
+        val orientation = ei.getAttributeInt(
+            ExifInterface.TAG_ORIENTATION,
+            ExifInterface.ORIENTATION_UNDEFINED
+        )
+        when (orientation) {
+            ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage(image, 90F)
+            ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage(image, 180F)
+            ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage(image, 270F)
+        }
+
+        contentResolver.openOutputStream(uri).use {
+            image.compress(Bitmap.CompressFormat.PNG, 100, it)
+        }
+    }
+
+    private fun rotateImage(source: Bitmap, angle: Float): Bitmap {
+        val matrix = Matrix().apply { postRotate(angle) }
+        return Bitmap.createBitmap(
+            source,
+            0,
+            0,
+            source.width,
+            source.height,
+            matrix,
+            true
+        )
     }
 
     private val cameraLauncher = registerForActivityResult(
-- 
GitLab