0

I'm developing an Android app using Jetpack Compose. These days, I'm testing the app using some devices and found out some photos(not all) from the device gallery rotate on one device(901FJ by Fujitsu, Android version is 9). Some photos rotate 90 degrees and some are upside down. I've read some codes written in Java but I only understand Kotlin. I still don't know how to change the code. Could someone help me?
The code of SignupView

@OptIn(ExperimentalFoundationApi::class, ExperimentalComposeUiApi::class)
@Composable
fun Signup(navController: NavController, auth: FirebaseAuth, mainViewModel: MainViewModel) {
    val requester = remember { BringIntoViewRequester() }
    val scope = rememberCoroutineScope()
    val context = LocalContext.current
    val dataStore = StoreUserData(context)
    var imageBitmap by remember { mutableStateOf<Bitmap?>(null) }
    val galleryLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
            uri?.getBitmapOrNull(context.contentResolver)?.let { bitmap: Bitmap ->
                imageBitmap = Bitmap.createScaledBitmap(bitmap, 120, 120, true)
            }
        }
...    

        Column(
        modifier = Modifier
            .background(Beige)
            .fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
            Spacer(modifier = Modifier.height(20.dp))
        Row(
            modifier = Modifier
                .fillMaxWidth(),
            horizontalArrangement = Arrangement.Center
        ) {
            Text(text = "Signup", fontSize = 32.sp, color = Brown)
        }
        Column(
            modifier = Modifier
                .fillMaxWidth(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Row() {
                if (imageBitmap != null) {
                    Image(
                        painter = rememberImagePainter(imageBitmap),
                        contentScale = ContentScale.FillBounds,
                        contentDescription = null,
                        modifier = Modifier
                            .width(60.dp)
                            .height(60.dp)
                            .clip(CircleShape)
                    )
                } else {
                    Image(
                        painter = painterResource(id = R.drawable.coffee),
                        contentDescription = null,
                        contentScale = ContentScale.Fit,
                        modifier = Modifier
                            .size(60.dp)
                            .clip(CircleShape)
                    )
                }
            }
            Row() {
                Button(
                    onClick = { galleryLauncher.launch("image/*") },
                    modifier = Modifier
                        .wrapContentSize(),
                    colors = ButtonDefaults.textButtonColors(
                        backgroundColor = Pink,
                        contentColor = Brown,
                        disabledContentColor = Color.LightGray
                    )
                ) {
                    Text(text = "Select a photo")
                }
            }          
...
                                                
}


fun Uri.getBitmapOrNull(contentResolver: ContentResolver): Bitmap? {
    return kotlin.runCatching {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val source = ImageDecoder.createSource(contentResolver, this)
            ImageDecoder.decodeBitmap(source)
        } else {
            MediaStore.Images.Media.getBitmap(contentResolver, this)
        }
    }.getOrNull()
}
Yuki
  • 225
  • 2
  • 7
  • 1
    Refer to https://developer.android.com/reference/android/media/ExifInterface. then rotate your bitmap when you decode it – fshdn19 Apr 04 '23 at 07:35

1 Answers1

0

Thanks to the helpful comment, I was able to learn about "ExifInterface". These are the codes I added and this works fine.
build.gradle(:app)

implementation 'androidx.exifinterface:exifinterface:1.3.6'
val galleryLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
            uri?.getBitmapOrNull(context.contentResolver)?.let { bitmap: Bitmap ->
                val orientation = uri?.getOrientation(context.contentResolver)
                val rotatedBitmap = orientation?.let { rotateBitmap(bitmap, it) } ?: bitmap
                imageBitmap = Bitmap.createScaledBitmap(rotatedBitmap, 120, 120, true)
            }
        }

fun Uri.getOrientation(contentResolver: ContentResolver): Int {
    var orientation = ExifInterface.ORIENTATION_UNDEFINED
    try {
        contentResolver.openInputStream(this)?.use { inputStream ->
            val exifInterface = ExifInterface(inputStream)
            orientation = exifInterface.getAttributeInt(
                ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED
            )
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }
    return orientation
}


fun rotateBitmap(bitmap: Bitmap, orientation: Int): Bitmap {
    val matrix = Matrix()
    when (orientation) {
        ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> matrix.setScale(-1f, 1f)
        ExifInterface.ORIENTATION_ROTATE_90 -> matrix.setRotate(90f)
        ExifInterface.ORIENTATION_TRANSVERSE -> {
            matrix.setRotate(270f)
            matrix.postScale(-1f, 1f)
        }
        ExifInterface.ORIENTATION_ROTATE_180 -> matrix.setRotate(180f)
        ExifInterface.ORIENTATION_FLIP_VERTICAL -> matrix.setRotate(180f)
        ExifInterface.ORIENTATION_TRANSPOSE -> {
            matrix.setRotate(90f)
            matrix.postScale(-1f, 1f)
        }
        ExifInterface.ORIENTATION_ROTATE_270 -> matrix.setRotate(270f)
        else -> return bitmap
    }
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}
Yuki
  • 225
  • 2
  • 7