QR scanner better cropping & support for inverted colors

* QR scanner fixes

* QR cropping

* Code cleanup

* Scanning frame offsets change

* Changelog update

---------

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
Milan 2024-07-19 14:28:59 +02:00 committed by GitHub
parent 741601b65f
commit a503091ab2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 62 additions and 31 deletions

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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