Last active
November 11, 2024 08:29
-
-
Save virtual-addy/8f936062291e3d328c7d10bb644273d0 to your computer and use it in GitHub Desktop.
A function to encode text as a QR code using BitmapPainter and zxing-core for use in jetpack compose with Image composable.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Composable | |
fun rememberQrBitmapPainter( | |
content: String, | |
size: Dp = 150.dp, | |
padding: Dp = 0.dp | |
): BitmapPainter { | |
val density = LocalDensity.current | |
val sizePx = with(density) { size.roundToPx() } | |
val paddingPx = with(density) { padding.roundToPx() } | |
var bitmap by remember(content) { | |
mutableStateOf<Bitmap?>(null) | |
} | |
LaunchedEffect(bitmap) { | |
if (bitmap != null) return@LaunchedEffect | |
launch(Dispatchers.IO) { | |
val qrCodeWriter = QRCodeWriter() | |
val encodeHints = mutableMapOf<EncodeHintType, Any?>() | |
.apply { | |
this[EncodeHintType.MARGIN] = paddingPx | |
} | |
val bitmapMatrix = try { | |
qrCodeWriter.encode( | |
content, BarcodeFormat.QR_CODE, | |
sizePx, sizePx, encodeHints | |
) | |
} catch (ex: WriterException) { | |
null | |
} | |
val matrixWidth = bitmapMatrix?.width ?: sizePx | |
val matrixHeight = bitmapMatrix?.height ?: sizePx | |
val newBitmap = Bitmap.createBitmap( | |
bitmapMatrix?.width ?: sizePx, | |
bitmapMatrix?.height ?: sizePx, | |
Bitmap.Config.ARGB_8888, | |
) | |
for (x in 0 until matrixWidth) { | |
for (y in 0 until matrixHeight) { | |
val shouldColorPixel = bitmapMatrix?.get(x, y) ?: false | |
val pixelColor = if (shouldColorPixel) Color.BLACK else Color.WHITE | |
newBitmap.setPixel(x, y, pixelColor) | |
} | |
} | |
bitmap = newBitmap | |
} | |
} | |
return remember(bitmap) { | |
val currentBitmap = bitmap ?: Bitmap.createBitmap( | |
sizePx, sizePx, | |
Bitmap.Config.ARGB_8888, | |
).apply { eraseColor(Color.TRANSPARENT) } | |
BitmapPainter(currentBitmap.asImageBitmap()) | |
} | |
} |
Thanks for this gist! I forked to provide an Image Composable with circular indicator while the QR code renders.
It also includes the import statements and the performance enhancement from @SherifMuSherif.
https://gist.github.com/ryanholden8/6e921a4dc2a40bd40b3b5a15aaff4705
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, I wanted to start by saying thank you for sharing this QR code generation code. It's clear that a lot of effort and expertise went into it, and it's been very helpful. I've been using it in a
LazyColumn
and noticed some performance issues. After some investigation, I found that the bitmap generation could be optimized. Instead of setting pixels on the bitmap one at a time usingsetPixel
, which can be quite slow, you could create an array of the pixel values and then usesetPixels
to set all the pixels at once. This change significantly improved the performance in my case. Here's the modified part of the code for your reference:I hope this suggestion might be useful to you or others who are using your code. Thanks again for your great work!