From 09cc1fed429e6169337c10156c4197444253bccb Mon Sep 17 00:00:00 2001 From: Alexis Rougnant Date: Fri, 13 Dec 2024 15:03:19 +0100 Subject: [PATCH 1/2] fix: load base64 image on android --- .../imagemarker/MarkerImageLoader.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt b/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt index 6734aaf9..74554a39 100644 --- a/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt +++ b/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt @@ -6,6 +6,7 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Build import android.os.Build.VERSION.SDK_INT +import android.util.Base64 import android.util.Log import androidx.annotation.RequiresApi import androidx.core.graphics.drawable.toBitmap @@ -48,8 +49,10 @@ class MarkerImageLoader(private val context: ReactApplicationContext, private va val deferredList = images.map { img -> async { try { + val isCoilImg = isCoilImg(img.uri) Log.d(IMAGE_MARKER_TAG, "isCoilImg: $isCoilImg") + if (isCoilImg) { val future = CompletableFuture() var request = ImageRequest.Builder(context) @@ -80,6 +83,17 @@ class MarkerImageLoader(private val context: ReactApplicationContext, private va } ).build()) return@async future.get() + } else if (isBase64String(img.uri)) { + Log.d(IMAGE_MARKER_TAG, "Loading Base64 Image") + decodeBase64ToBitmap(img.uri)?.let { bitmap -> + val scaledBitmap = ImageProcess.scaleBitmap(bitmap, img.scale) + ?: throw MarkerError(ErrorCode.LOAD_IMAGE_FAILED, "Failed to scale Base64 image") + if (!bitmap.isRecycled && img.scale != 1f) { + bitmap.recycle() + System.gc() + } + return@async scaledBitmap + } ?: throw MarkerError(ErrorCode.GET_RESOURCE_FAILED, "Failed to decode Base64 image") } else { val resId = getDrawableResourceByName(img.uri) Log.d(IMAGE_MARKER_TAG, "resId: $resId") @@ -130,4 +144,20 @@ class MarkerImageLoader(private val context: ReactApplicationContext, private va ) } + + private fun isBase64String(s: String?): Boolean { + if (s == null) return false + return s.startsWith("data:image/") && s.contains(";base64,") + } + + private fun decodeBase64ToBitmap(base64Str: String?): Bitmap? { + if (base64Str == null) return null + return try { + val imageBytes = Base64.decode(base64Str.substring(base64Str.indexOf(",") + 1), Base64.DEFAULT) + BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size) + } catch (e: Exception) { + Log.e("ImageLoader", "Failed to decode Base64 image", e) + null + } + } } From 19837bf3e82cd575a897d5806b180975d0fa7ac0 Mon Sep 17 00:00:00 2001 From: Alexis Rougnant Date: Fri, 13 Dec 2024 15:39:01 +0100 Subject: [PATCH 2/2] fix: handle base64 string before coil img --- .../imagemarker/MarkerImageLoader.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt b/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt index 74554a39..b0bd5956 100644 --- a/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt +++ b/android/src/main/java/com/jimmydaddy/imagemarker/MarkerImageLoader.kt @@ -53,7 +53,18 @@ class MarkerImageLoader(private val context: ReactApplicationContext, private va val isCoilImg = isCoilImg(img.uri) Log.d(IMAGE_MARKER_TAG, "isCoilImg: $isCoilImg") - if (isCoilImg) { + if (isBase64String(img.uri)) { + Log.d(IMAGE_MARKER_TAG, "Loading Base64 Image") + decodeBase64ToBitmap(img.uri)?.let { bitmap -> + val scaledBitmap = ImageProcess.scaleBitmap(bitmap, img.scale) + ?: throw MarkerError(ErrorCode.LOAD_IMAGE_FAILED, "Failed to scale Base64 image") + if (!bitmap.isRecycled && img.scale != 1f) { + bitmap.recycle() + System.gc() + } + return@async scaledBitmap + } ?: throw MarkerError(ErrorCode.GET_RESOURCE_FAILED, "Failed to decode Base64 image") + } else if (isCoilImg) { val future = CompletableFuture() var request = ImageRequest.Builder(context) .data(img.uri) @@ -83,17 +94,6 @@ class MarkerImageLoader(private val context: ReactApplicationContext, private va } ).build()) return@async future.get() - } else if (isBase64String(img.uri)) { - Log.d(IMAGE_MARKER_TAG, "Loading Base64 Image") - decodeBase64ToBitmap(img.uri)?.let { bitmap -> - val scaledBitmap = ImageProcess.scaleBitmap(bitmap, img.scale) - ?: throw MarkerError(ErrorCode.LOAD_IMAGE_FAILED, "Failed to scale Base64 image") - if (!bitmap.isRecycled && img.scale != 1f) { - bitmap.recycle() - System.gc() - } - return@async scaledBitmap - } ?: throw MarkerError(ErrorCode.GET_RESOURCE_FAILED, "Failed to decode Base64 image") } else { val resId = getDrawableResourceByName(img.uri) Log.d(IMAGE_MARKER_TAG, "resId: $resId")