diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d00607a..2eb6a001 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,11 +15,13 @@ and this application adheres to [Semantic Versioning](https://semver.org/spec/v2 - The About screen has been redesigned to align with the new design guidelines - `StyledBalance` text styles have been refactored from `Pair` into `BalanceTextStyle` - The Restore Success dialog has been reworked into a separate screen, allowing users to opt out of the Keep screen - on while restoring option + on while restoring option ## Fixed - Support Screen now shows the Send button above keyboard instead of overlaying it. This was achieved by setting `adjustResize` to `MainActivity` and adding `imePadding` to top level composable +- QR code scanning speed and reliability have been improved to address the latest reported scan issue. The obtained + image cropping and image reader hints have been changed as part of these improvements. ## [1.1.3 (682)] - 2024-07-03 diff --git a/docs/whatsNew/WHATS_NEW_EN.md b/docs/whatsNew/WHATS_NEW_EN.md index d45baa6d..69bda7ea 100644 --- a/docs/whatsNew/WHATS_NEW_EN.md +++ b/docs/whatsNew/WHATS_NEW_EN.md @@ -19,3 +19,4 @@ directly impact users rather than highlighting other key architectural updates.* ### Fixed - Support Screen now shows the Send button above keyboard instead of overlaying it +- QR code scanning speed and reliability have been improved to address the latest reported scan issue diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/ImageUriToQrCodeConverter.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/ImageUriToQrCodeConverter.kt index 52b6e6b0..f0518d38 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/ImageUriToQrCodeConverter.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/ImageUriToQrCodeConverter.kt @@ -48,7 +48,12 @@ class ImageUriToQrCodeConverter { private fun BinaryBitmap.toQRCode(): String = MultiFormatReader() .apply { - setHints(mapOf(DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE))) + setHints( + mapOf( + DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE), + DecodeHintType.ALSO_INVERTED to true + ) + ) } - .decode(this@toQRCode).text + .decodeWithState(this@toQRCode).text } diff --git a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/QrCodeAnalyzer.kt b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/QrCodeAnalyzer.kt index b036ac10..1535ea0b 100644 --- a/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/QrCodeAnalyzer.kt +++ b/ui-lib/src/main/java/co/electriccoin/zcash/ui/screen/scan/util/QrCodeAnalyzer.kt @@ -37,35 +37,55 @@ class QrCodeAnalyzer( "Image height: ${image.height}" } + // TODO [#1380]: Leverage FramePosition in QrCodeAnalyzer + // TODO [#1380]: https://github.com/Electric-Coin-Company/zashi-android/issues/1380 val source = - PlanarYUVLuminanceSource( - bytes, - image.width, - image.height, - 0, - 0, - image.width, - image.height, - false - ) + if (image.height > image.width) { + PlanarYUVLuminanceSource( + // yuvData = + bytes, + // dataWidth = + image.width, + // dataHeight = + image.height, + // left = + (image.width * LEFT_OFFSET).toInt(), + // top = + (image.height * TOP_OFFSET).toInt(), + // width = + (image.width * WIDTH_OFFSET).toInt(), + // height = + (image.height * HEIGHT_OFFSET).toInt(), + // reverseHorizontal = + false + ) + } else { + PlanarYUVLuminanceSource( + // yuvData = + bytes, + // dataWidth = + image.width, + // dataHeight = + image.height, + // left = + (image.width * TOP_OFFSET).toInt(), + // top = + (image.height * LEFT_OFFSET).toInt(), + // width = + (image.width * HEIGHT_OFFSET).toInt(), + // height = + (image.height * WIDTH_OFFSET).toInt(), + // reverseHorizontal = + false + ) + } val binaryBmp = BinaryBitmap(HybridBinarizer(source)) - // TODO [#1380]: Leverage FramePosition in QrCodeAnalyzer - // TODO [#1380]: https://github.com/Electric-Coin-Company/zashi-android/issues/1380 - @Suppress("MagicNumber") - val binaryBitmapCropped = - binaryBmp.crop( - (binaryBmp.width * 0.25).toInt(), - (binaryBmp.height * 0.30).toInt(), - (binaryBmp.width * 0.30).toInt(), - (binaryBmp.height * 0.4).toInt() - ) - Twig.verbose { "Scan result cropped: " + - "Image width: ${binaryBitmapCropped.width}, " + - "Image height: ${binaryBitmapCropped.height}" + "Image width: ${binaryBmp.width}, " + + "Image height: ${binaryBmp.height}" } runCatching { @@ -73,13 +93,11 @@ class QrCodeAnalyzer( MultiFormatReader().apply { setHints( mapOf( - DecodeHintType.POSSIBLE_FORMATS to - arrayListOf( - BarcodeFormat.QR_CODE - ) + DecodeHintType.POSSIBLE_FORMATS to arrayListOf(BarcodeFormat.QR_CODE), + DecodeHintType.ALSO_INVERTED to true ) ) - }.decode(binaryBitmapCropped) + }.decodeWithState(binaryBmp) onQrCodeScanned(result.text) }.onFailure { @@ -96,3 +114,8 @@ class QrCodeAnalyzer( } } } + +private const val LEFT_OFFSET = .15 +private const val TOP_OFFSET = .15 +private const val WIDTH_OFFSET = .7 +private const val HEIGHT_OFFSET = .45