diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt index 2235a82cbc..1e635aba66 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/Util.kt @@ -27,12 +27,10 @@ import chat.simplex.app.BuildConfig import chat.simplex.app.SimplexApp import chat.simplex.app.model.CIFile import kotlinx.coroutines.* -import java.io.File -import java.io.FileOutputStream +import java.io.* import java.text.SimpleDateFormat import java.util.* -import kotlin.math.log2 -import kotlin.math.pow +import kotlin.math.* fun withApi(action: suspend CoroutineScope.() -> Unit): Job = withScope(GlobalScope, action) @@ -245,7 +243,7 @@ fun getLoadedImage(context: Context, file: CIFile?): Bitmap? { val uri = FileProvider.getUriForFile(context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath)) val parcelFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r") val fileDescriptor = parcelFileDescriptor?.fileDescriptor - val image = BitmapFactory.decodeFileDescriptor(fileDescriptor) + val image = decodeSampledBitmapFromFileDescriptor(fileDescriptor, 1000, 1000) parcelFileDescriptor?.close() image } catch (e: Exception) { @@ -256,6 +254,39 @@ fun getLoadedImage(context: Context, file: CIFile?): Bitmap? { } } +// https://developer.android.com/topic/performance/graphics/load-bitmap#load-bitmap +private fun decodeSampledBitmapFromFileDescriptor(fileDescriptor: FileDescriptor?, reqWidth: Int, reqHeight: Int): Bitmap { + // First decode with inJustDecodeBounds=true to check dimensions + return BitmapFactory.Options().run { + inJustDecodeBounds = true + BitmapFactory.decodeFileDescriptor(fileDescriptor, null, this) + // Calculate inSampleSize + inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) + // Decode bitmap with inSampleSize set + inJustDecodeBounds = false + + BitmapFactory.decodeFileDescriptor(fileDescriptor, null, this) + } +} + +private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { + // Raw height and width of image + val (height: Int, width: Int) = options.run { outHeight to outWidth } + var inSampleSize = 1 + + if (height > reqHeight || width > reqWidth) { + val halfHeight: Int = height / 2 + val halfWidth: Int = width / 2 + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) { + inSampleSize *= 2 + } + } + + return inSampleSize +} + fun getFileName(context: Context, uri: Uri): String? { return context.contentResolver.query(uri, null, null, null, null)?.use { cursor -> val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)