diff options
author | 2025-05-31 04:21:50 +0200 | |
---|---|---|
committer | 2025-05-31 04:22:06 +0200 | |
commit | cb216c6ec60efe84f7c4d3f256bae33603406aa5 (patch) | |
tree | f0f103c6a21e3688b772730dd04e8a2193156333 | |
parent | QrCodeFromFileScanner: catch OOM errors (diff) | |
download | wireguard-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.kt | 60 |
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) } - } /** |