aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2025-05-31 04:21:50 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2025-05-31 04:22:06 +0200
commitcb216c6ec60efe84f7c4d3f256bae33603406aa5 (patch)
treef0f103c6a21e3688b772730dd04e8a2193156333
parentQrCodeFromFileScanner: catch OOM errors (diff)
downloadwireguard-android-cb216c6ec60efe84f7c4d3f256bae33603406aa5.tar.xz
wireguard-android-cb216c6ec60efe84f7c4d3f256bae33603406aa5.zip
QrCodeFromFileScanner: more efficiently downscale images and release memory
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--ui/src/main/java/com/wireguard/android/util/QrCodeFromFileScanner.kt60
1 files changed, 16 insertions, 44 deletions
diff --git a/ui/src/main/java/com/wireguard/android/util/QrCodeFromFileScanner.kt b/ui/src/main/java/com/wireguard/android/util/QrCodeFromFileScanner.kt
index 8ffd6bb4..4ea2dc7a 100644
--- a/ui/src/main/java/com/wireguard/android/util/QrCodeFromFileScanner.kt
+++ b/ui/src/main/java/com/wireguard/android/util/QrCodeFromFileScanner.kt
@@ -29,7 +29,6 @@ class QrCodeFromFileScanner(
private val contentResolver: ContentResolver,
private val reader: Reader,
) {
-
private fun scanBitmapForResult(source: Bitmap): Result {
val width = source.width
val height = source.height
@@ -40,55 +39,28 @@ class QrCodeFromFileScanner(
return reader.decode(bBitmap, mapOf(DecodeHintType.TRY_HARDER to true))
}
- private fun downscaleBitmap(source: Bitmap, scaledSize: Int): Bitmap {
-
- val originalWidth = source.width
- val originalHeight = source.height
-
- var newWidth = -1
- var newHeight = -1
- val multFactor: Float
-
- when {
- originalHeight > originalWidth -> {
- newHeight = scaledSize
- multFactor = originalWidth.toFloat() / originalHeight.toFloat()
- newWidth = (newHeight * multFactor).toInt()
- }
-
- originalWidth > originalHeight -> {
- newWidth = scaledSize
- multFactor = originalHeight.toFloat() / originalWidth.toFloat()
- newHeight = (newWidth * multFactor).toInt()
- }
-
- originalHeight == originalWidth -> {
- newHeight = scaledSize
- newWidth = scaledSize
- }
- }
- return Bitmap.createScaledBitmap(source, newWidth, newHeight, false)
- }
-
private fun doScan(data: Uri): Result {
Log.d(TAG, "Starting to scan an image: $data")
contentResolver.openInputStream(data).use { inputStream ->
- val originalBitmap = BitmapFactory.decodeStream(inputStream)
- ?: throw IllegalArgumentException("Can't decode stream to Bitmap")
-
- return try {
- scanBitmapForResult(originalBitmap).also {
- Log.d(TAG, "Found result in original image")
+ var bitmap: Bitmap? = null
+ var firstException: Throwable? = null
+ for (i in arrayOf(1, 2, 4, 8, 16, 32, 64, 128)) {
+ try {
+ val options = BitmapFactory.Options()
+ options.inSampleSize = i
+ bitmap = BitmapFactory.decodeStream(inputStream, null, options)
+ ?: throw IllegalArgumentException("Can't decode stream for bitmap")
+ return scanBitmapForResult(bitmap)
+ } catch (e: Throwable) {
+ bitmap?.recycle()
+ System.gc()
+ Log.e(TAG, "Original image scan at scale factor $i finished with error: $e")
+ if (firstException == null)
+ firstException = e
}
- } catch (e: Throwable) {
- Log.e(TAG, "Original image scan finished with error: $e, will try downscaled image")
- val scaleBitmap = downscaleBitmap(originalBitmap, 500)
- scanBitmapForResult(originalBitmap).also { scaleBitmap.recycle() }
- } finally {
- originalBitmap.recycle()
}
+ throw Exception(firstException)
}
-
}
/**