Optimized decoding of bitmaps
This commit is contained in:
@ -3,7 +3,6 @@ package com.tutpro.baresip
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import android.provider.ContactsContract
|
||||
import androidx.core.net.toUri
|
||||
@ -302,7 +301,7 @@ sealed class Contact {
|
||||
val avatarFilePath = BaresipService.filesPath + "/$id.png"
|
||||
if (File(avatarFilePath).exists()) {
|
||||
try {
|
||||
contact.avatarImage = BitmapFactory.decodeFile(avatarFilePath)
|
||||
contact.avatarImage = Utils.decodeSampledBitmapFromFile(avatarFilePath, 192, 192)
|
||||
Log.d(TAG, "Set avatarImage")
|
||||
if (contact.avatarImage == null)
|
||||
Log.d(TAG, "Contact $id avatarImage is null")
|
||||
|
||||
@ -468,9 +468,7 @@ private fun AvatarSection(
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
|
||||
if (uri != null) {
|
||||
try {
|
||||
val inputStream = ctx.contentResolver.openInputStream(uri)
|
||||
val avatarBitmap = BitmapFactory.decodeStream(inputStream)
|
||||
inputStream?.close()
|
||||
val avatarBitmap = Utils.decodeSampledBitmapFromUri(ctx, uri, 192, 192)
|
||||
|
||||
if (avatarBitmap == null) {
|
||||
Log.e(TAG, "Failed to decode bitmap from URI: $uri")
|
||||
|
||||
@ -5,7 +5,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import androidx.core.graphics.scale
|
||||
import android.provider.ContactsContract
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
@ -243,11 +243,17 @@ private fun ContactsScreen(navController: NavController) {
|
||||
if (photoBase64.isNotEmpty())
|
||||
try {
|
||||
val decodedString = Base64.decode(photoBase64, Base64.DEFAULT)
|
||||
val decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.size)
|
||||
val decodedByte = Utils.decodeSampledBitmapFromByteArray(decodedString, 192, 192)
|
||||
if (decodedByte != null) {
|
||||
val scaledByte = decodedByte.scale(192, 192)
|
||||
val avatarFile = File(BaresipService.filesPath, "$contactId.png")
|
||||
FileOutputStream(avatarFile).use { out ->
|
||||
decodedByte.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
try {
|
||||
val out = FileOutputStream(avatarFile)
|
||||
scaledByte.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
out.flush()
|
||||
out.close()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to save photo for $name: ${e.message}")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
||||
@ -15,6 +15,7 @@ import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffXfermode
|
||||
@ -1390,6 +1391,57 @@ object Utils {
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
|
||||
val (height: Int, width: Int) = options.outHeight to options.outWidth
|
||||
var inSampleSize = 1
|
||||
if (height > reqHeight || width > reqWidth) {
|
||||
val halfHeight = height / 2
|
||||
val halfWidth = width / 2
|
||||
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth)
|
||||
inSampleSize *= 2
|
||||
}
|
||||
return inSampleSize
|
||||
}
|
||||
|
||||
fun decodeSampledBitmapFromUri(ctx: Context, uri: Uri, reqWidth: Int, reqHeight: Int): Bitmap? {
|
||||
return try {
|
||||
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||
ctx.contentResolver.openInputStream(uri).use { BitmapFactory.decodeStream(it, null, options) }
|
||||
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
|
||||
options.inJustDecodeBounds = false
|
||||
ctx.contentResolver.openInputStream(uri).use { BitmapFactory.decodeStream(it, null, options) }
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to decode sampled bitmap from URI: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun decodeSampledBitmapFromByteArray(data: ByteArray, reqWidth: Int, reqHeight: Int): Bitmap? {
|
||||
return try {
|
||||
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||
BitmapFactory.decodeByteArray(data, 0, data.size, options)
|
||||
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
|
||||
options.inJustDecodeBounds = false
|
||||
BitmapFactory.decodeByteArray(data, 0, data.size, options)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to decode sampled bitmap from ByteArray: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun decodeSampledBitmapFromFile(path: String, reqWidth: Int, reqHeight: Int): Bitmap? {
|
||||
return try {
|
||||
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||
BitmapFactory.decodeFile(path, options)
|
||||
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
|
||||
options.inJustDecodeBounds = false
|
||||
BitmapFactory.decodeFile(path, options)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to decode sampled bitmap from file: ${e.message}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(29)
|
||||
@SuppressLint("HardwareIds")
|
||||
fun getLine1Number(ctx: Context, subscriptionId: Int = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID): String? {
|
||||
|
||||
Reference in New Issue
Block a user