Refactor QRCodeDecoder for readability and performance (#3782)

- Improved the `createQRCode` function by replacing manual loops with Kotlin idioms and using `runCatching` for safer error handling.
- Refactored `syncDecodeQRCode` to simplify control flow and avoid redundant null checks.
- Enhanced error handling and logging by using `runCatching` and more concise exception handling.
This commit is contained in:
Tamim Hossain
2024-10-25 17:19:22 +06:00
committed by GitHub
parent 82087e1187
commit b66a8ca44d

View File

@@ -23,36 +23,19 @@ object QRCodeDecoder {
* create qrcode using zxing
*/
fun createQRCode(text: String, size: Int = 800): Bitmap? {
try {
val hints = HashMap<EncodeHintType, String>()
hints[EncodeHintType.CHARACTER_SET] = "utf-8"
val bitMatrix = QRCodeWriter().encode(
text,
BarcodeFormat.QR_CODE, size, size, hints
)
val pixels = IntArray(size * size)
for (y in 0 until size) {
for (x in 0 until size) {
if (bitMatrix.get(x, y)) {
pixels[y * size + x] = 0xff000000.toInt()
} else {
pixels[y * size + x] = 0xffffffff.toInt()
}
}
return runCatching {
val hints = mapOf(EncodeHintType.CHARACTER_SET to Charsets.UTF_8)
val bitMatrix = QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, size, size, hints)
val pixels = IntArray(size * size) { i ->
if (bitMatrix.get(i % size, i / size)) 0xff000000.toInt() else 0xffffffff.toInt()
}
val bitmap = Bitmap.createBitmap(
size, size,
Bitmap.Config.ARGB_8888
)
bitmap.setPixels(pixels, 0, size, 0, 0, size, size)
return bitmap
} catch (e: Exception) {
e.printStackTrace()
return null
}
Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888).apply {
setPixels(pixels, 0, size, 0, 0, size, size)
}
}.getOrNull()
}
/**
* 同步解析本地图片二维码。该方法是耗时操作,请在子线程中调用。
*
@@ -70,40 +53,24 @@ object QRCodeDecoder {
* @return 返回二维码图片里的内容 或 null
*/
fun syncDecodeQRCode(bitmap: Bitmap?): String? {
if (bitmap == null) {
return null
}
var source: RGBLuminanceSource? = null
try {
val width = bitmap.width
val height = bitmap.height
val pixels = IntArray(width * height)
bitmap.getPixels(pixels, 0, width, 0, 0, width, height)
source = RGBLuminanceSource(width, height, pixels)
val qrReader = QRCodeReader()
try {
val result = try {
qrReader.decode(
BinaryBitmap(GlobalHistogramBinarizer(source)),
mapOf(DecodeHintType.TRY_HARDER to true)
)
} catch (e: NotFoundException) {
qrReader.decode(
BinaryBitmap(GlobalHistogramBinarizer(source.invert())),
mapOf(DecodeHintType.TRY_HARDER to true)
)
return bitmap?.let {
runCatching {
val pixels = IntArray(it.width * it.height).also { array ->
it.getPixels(array, 0, it.width, 0, 0, it.width, it.height)
}
return result.text
} catch (e: Exception) {
e.printStackTrace()
}
} catch (e: Exception) {
e.printStackTrace()
}
val source = RGBLuminanceSource(it.width, it.height, pixels)
val qrReader = QRCodeReader()
return null
try {
qrReader.decode(BinaryBitmap(GlobalHistogramBinarizer(source)), mapOf(DecodeHintType.TRY_HARDER to true)).text
} catch (e: NotFoundException) {
qrReader.decode(BinaryBitmap(GlobalHistogramBinarizer(source.invert())), mapOf(DecodeHintType.TRY_HARDER to true)).text
}
}.getOrNull()
}
}
/**
* 将本地图片文件转换成可解码二维码的 Bitmap。为了避免图片太大这里对图片进行了压缩。感谢 https://github.com/devilsen 提的 PR
*
@@ -149,6 +116,6 @@ object QRCodeDecoder {
)
HINTS[DecodeHintType.TRY_HARDER] = BarcodeFormat.QR_CODE
HINTS[DecodeHintType.POSSIBLE_FORMATS] = allFormats
HINTS[DecodeHintType.CHARACTER_SET] = "utf-8"
HINTS[DecodeHintType.CHARACTER_SET] = Charsets.UTF_8
}
}