Skip to content

Commit

Permalink
Add QR code image bitmap generator
Browse files Browse the repository at this point in the history
  • Loading branch information
msasikanth committed Sep 21, 2023
1 parent 4751ab2 commit 27d3c77
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package org.hisp.dhis.mobile.ui.designsystem.component.internal.qr

import android.graphics.Bitmap
import android.graphics.Color
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.common.BitMatrix
import com.google.zxing.qrcode.QRCodeWriter

internal actual class QrCodeGenerator {

actual fun generate(data: String): ImageBitmap {
val writer = QRCodeWriter()
val bitMatrix = writer.encode(
data,
BarcodeFormat.QR_CODE,
QR_CODE_SIZE,
QR_CODE_SIZE,
mapOf(Pair(EncodeHintType.MARGIN, 1)),
)
val bitmap = createAndroidBitmap(bitMatrix)

return bitmap.asImageBitmap()
}

private fun createAndroidBitmap(bitMatrix: BitMatrix): Bitmap {
val width = bitMatrix.width
val height = bitMatrix.height
val pixels = IntArray(width * height)

for (y in 0 until height) {
for (x in 0 until width) {
pixels[y * width + x] = if (bitMatrix[x, y]) Color.BLACK else Color.WHITE
}
}

return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
setPixels(pixels, 0, width, 0, 0, width, height)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.hisp.dhis.mobile.ui.designsystem.component.internal.qr

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.ImageBitmap

@Composable
internal fun rememberQrCodeGenerator(value: String): State<ImageBitmap?> {
val qrCodeGenerator = LocalQrCodeGenerator.current
val result = remember(value) { mutableStateOf<ImageBitmap?>(null) }

LaunchedEffect(value) {
result.value = qrCodeGenerator.generate(value)
}

return result
}

internal expect class QrCodeGenerator() {
fun generate(data: String): ImageBitmap
}

internal const val QR_CODE_SIZE = 512 // px

internal val LocalQrCodeGenerator = staticCompositionLocalOf { QrCodeGenerator() }
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.hisp.dhis.mobile.ui.designsystem.component.internal.qr

import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.common.BitMatrix
import com.google.zxing.qrcode.QRCodeWriter
import java.awt.image.BufferedImage

internal actual class QrCodeGenerator {

private val colorBlack = 0xFF000000.toInt()
private val colorWhite = 0xFFFFFFFF.toInt()

actual fun generate(data: String): ImageBitmap {
val writer = QRCodeWriter()
val bitMatrix = writer.encode(
data,
BarcodeFormat.QR_CODE,
QR_CODE_SIZE,
QR_CODE_SIZE,
mapOf(Pair(EncodeHintType.MARGIN, 1)),
)
val image = createBufferedImage(bitMatrix)

return image.toComposeImageBitmap()
}

private fun createBufferedImage(bitMatrix: BitMatrix): BufferedImage {
val width = bitMatrix.width
val height = bitMatrix.height
val pixels = IntArray(width * height)

for (y in 0 until height) {
for (x in 0 until width) {
pixels[y * width + x] = if (bitMatrix[x, y]) colorBlack else colorWhite
}
}

return BufferedImage(width, height, BufferedImage.TYPE_INT_RGB).apply {
setRGB(0, 0, width, height, pixels, 0, width)
}
}
}

0 comments on commit 27d3c77

Please sign in to comment.