Open LossyDragon opened 1 year ago
Heya! Thanks for bringing up this issue! I'll give it a try later today and I'll get back to you 😄
Might be something due to the optimization implemented.
Also, I'm working on implementing examples with all platforms of the library, but I'll definitely add a Jetpack Compose one! Thanks for suggesting it ^^
I think this is also related to our issue. We had:
Image(
modifier = Modifier.padding(8.dp),
bitmap = (QRCode(barcode).render().nativeImage() as Bitmap).asImageBitmap(),
alpha = if (expired) 0.38f else 1.0f,
contentDescription = stringResource(R.string.alt_qr_code)
)
And this worked fine in v3.x.x but with v4.0.2 and the QRCodeProcessor
instead of QRCode
we now just get a black square with no white at all.
I see! That really seems like it is related, I'll try this out right now
Heya, I pinpointed the issue. I'm not 100% sure of what caused it, but it is because the Int
s of the colors are kind of being compiled wrong on Android. Color.WHITE
for example goes from 0xFFFFFFFF
to -1
which makes it black... and basically the same for all other colors 🤔
Still figuring out how to fix it x_x
Might not be that, btw... Anyway, I'm still trying to figure out what is going on O_o
🤦♂️ found the issue, preparing the next version with the fix
In short, either I'm dumb or Android API is. Thing is, rectangles are described via:
(x1, y1)
of the top-left corner and (x2, y2)
of the bottom right corner. I assumed, as all other platforms works like this, that they were x, y, width, height
...
This is what causes this weird "everything is black" state.
Edit: Now that the library draws all squares directly into the Canvas, this was what caused the issue: any black rectangles would become something like "draw from 1000,1000 to -20,-20"
Also, I'll make a few adjustments to the compatibility API for the use-case @barry-irvine shared :)
Right now, since the innerSpace
is being defaulted to 1
, the QRCodes might end up looking like this:
This should fix both reported issues. I'll keep this issue open since I didn't implement Jetpack Compose examples yet 😅
@g0dkar I can confirm that the QR code now looks good in Compose (for my scenario at least)
I am not sure if this is a related issue (or even a feature!) either way there is no timing pattern on the generated QR codes- is this a feature of a bug?! Trying to optimise readability on larger & animated codes. Thank you. Great library.
Heya! I was having little time to work on the lib lately, but I'm coming back to it this month :)
I'll check the timing pattern and some other reported bugs today and the following days.
And animated QRCodes sound like an awesome idea hahaha, I'll look into it 😬
Thank you very much! It turns out the reason for the poor reading rate was the size of the QR code- when I limited the number of alphanumeric characters to about 55 the smaller QR code resulted in a better overall outcome. The larger ones overwhelmed the ability to hold & process multiple images so kept dropping them, requiring the loop of QR codes to cycle round again until the missed QRs were read.
So the timing pattern did not seem to have any impact on the readability of the QR code.
Code to display 'animated' QR code below:
@Composable
fun QRCodeSlideshow(
modifier: Modifier = Modifier,
qrContents: String,
) {
var currentBitmap by remember { mutableStateOf<Bitmap?>(null) }
var currentIndex by remember { mutableStateOf(0) }
val qrParts = divideStringIntoEqualParts(qrContents, 50)
// Divide the string into parts: 50 empirically optimal with a 100ms display duration
LaunchedEffect(key1 = "QRSlideshow") {
if (qrParts.isNotEmpty()) { // Only proceed if qrParts is not empty
while (true) {
val content = qrParts[currentIndex]
// Generate the QR code bitmap.
currentBitmap = QRCodeGenerator.generateQRCodeBitmap("ur:bytes/${currentIndex+1}-5/$content")
// Show the QR code for at least 100ms
delay(100)
// Move to the next QR code content
currentIndex = (currentIndex + 1) % qrParts.size
}
}
}
Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
if (qrParts.isEmpty()) {
Text(
text = "No data to transfer",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
} else {
currentBitmap?.let {
Image(bitmap = it.asImageBitmap(), contentDescription = "QR Code")
}
Text(
text = "${currentIndex + 1} / ${qrParts.size}",
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center
)
}
}
}
fun divideStringIntoEqualParts(inputString: String, maxLength: Int): List<String> {
// Check if the maxLength is less than or equal to zero to avoid division by zero or infinite loops
if (maxLength <= 0) throw IllegalArgumentException("Maximum length must be greater than zero")
val result = mutableListOf<String>()
// Iterate over the string, taking substrings of length `maxLength` at a time
var start = 0
while (start < inputString.length) {
// Calculate end index. Ensure it does not exceed the string's length
val end = minOf(start + maxLength, inputString.length)
// Add the substring to the result list
result.add(inputString.substring(start, end))
// Move the start index forward
start += maxLength
}
return result
}
object QRCodeGenerator {
fun generateQRCodeBitmap(content: String): Bitmap {
val QRtoReturn = QRCode.ofSquares()
.withColor(Colors.BLACK)
.withSize(25).build(content).render()
return QRtoReturn.nativeImage() as Bitmap
}
}
Describe the bug 4.0.2-3
I'm updating a hobby project from v3.3.0 to 4.0.+ and it seems I am unable to render a QR code through Jetpack compose.
I am using landscapist as my image loading library and QR codes were working fine throughout v3, but now they are just blank solid colored squares moving to v4
I have tried using
render()
,render("bmp")
, andrenderToGraphics().nativeImage()
to no avail. nativeImage() was my working way last major version.render() seems to actually produce an inner square
but, and rounded only shows rounded corners along the right side.Correction: Top left corner is square while the other corners show a rounded corner
To Reproduce Steps to reproduce the behavior. For example:
Expected behavior Rendered QR codes using Jetpack compose. Maybe a quick sample showing it off would help newcomers too!
Screenshots or other QRCodes rendered with other tools
Additional context
Quick sample code