diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt index 334fc94..f1e34f5 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt @@ -42,31 +42,102 @@ open class PlasticBagPrinterService( ): ByteArray { val baos = ByteArrayOutputStream() ZipOutputStream(baos).use { zos -> - // Reduced heights by ~80% to hit the 12KB-17KB file size target // These heights (100-180) will produce much smaller BMP files - val productBmp = createMonochromeBitmap(productName, 100) - val codeBmp = createMonochromeBitmap(itemCode, 180) - val expBmp = createMonochromeBitmap(expiryDate, 180) - val qrBmp = createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 250) - - val nameFile = "${lotNo}_product.bmp" - val codeFile = "${lotNo}_code.bmp" - val expFile = "${lotNo}_expiry.bmp" - val qrFile = "${lotNo}_qr.bmp" + val productBmp = createMonochromeBitmap(productName, 300) + val codeBmp = createMonochromeBitmap(itemCode, 200) + val expBmp = createMonochromeBitmap(expiryDate, 180) + val qrBmp = createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 600) + val lotBmp = createMonochromeBitmap(lotNo, 180) + + // All file names now prefixed with "TT_$itemCode" + val prefix = "TT_$itemCode" + val nameFile = "${prefix}_product.bmp" + val codeFile = "${prefix}_code.bmp" + val expFile = "${prefix}_expiry.bmp" + val qrFile = "${prefix}_qr.bmp" + val lotFile = "${prefix}_lot.bmp" addToZip(zos, nameFile, productBmp.bytes) addToZip(zos, codeFile, codeBmp.bytes) - addToZip(zos, expFile, expBmp.bytes) - addToZip(zos, qrFile, qrBmp.bytes) - - // The XML Width/Height must match the ACTUAL generated bitmap dimensions - val imageXml = """falseDEG_053007100LOGO42505000BLACK$nameFile${productBmp.width}100LOGO_25100012500BLACK$codeFile${codeBmp.width}180LOGO_3650025000BLACK$expFile${expBmp.width}180LOGO_4750037500BLACK$qrFile${qrBmp.width}250""".trimIndent() - - addToZip(zos, "$lotNo.image", imageXml.toByteArray(Charsets.UTF_8)) - - val jobXml = """$lotNo.image""" - addToZip(zos, "$lotNo.job", jobXml.toByteArray(Charsets.UTF_8)) + addToZip(zos, lotFile, lotBmp.bytes) + addToZip(zos, qrFile, qrBmp.bytes) + + val imageXml = """ + + + + + + false + DEG_0 + 5300 + 7100 + + + LOGO + 4 + + 250 + 500 + 0 + + BLACK + $nameFile + 4914 + 845 + + + LOGO_2 + 5 + + 1000 + 1250 + 0 + + BLACK + $codeFile + 3205 + 1173 + + + LOGO_3 + 6 + + 500 + 2500 + 0 + + BLACK + $expFile + 4203 + 1173 + + + LOGO_4 + 7 + + 500 + 3750 + 0 + + BLACK + $qrFile + 4353 + 3000 + + + """.trimIndent() + + // Image and Job files now also use TT_$itemCode + addToZip(zos, "$prefix.image", imageXml.toByteArray(Charsets.UTF_8)) + + val jobXml = """ + + $prefix.image + """.trimIndent() + + addToZip(zos, "$prefix.job", jobXml.toByteArray(Charsets.UTF_8)) } return baos.toByteArray() } @@ -137,22 +208,31 @@ open class PlasticBagPrinterService( } } - private fun createQrCodeBitmap(content: String, size: Int): BitmapResult { + private fun createQrCodeBitmap(content: String, contentSize: Int, totalSize: Int = contentSize + 80): BitmapResult { + if (totalSize < contentSize) throw IllegalArgumentException("totalSize must be >= contentSize") + val writer = QRCodeWriter() - val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, size, size) - val image = BufferedImage(size, size, BufferedImage.TYPE_BYTE_BINARY) - for (x in 0 until size) { - for (y in 0 until size) { - image.setRGB(x, y, if (bitMatrix.get(x, y)) Color.BLACK.rgb else Color.WHITE.rgb) + val bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, contentSize, contentSize) + + val image = BufferedImage(totalSize, totalSize, BufferedImage.TYPE_BYTE_BINARY) + val g = image.createGraphics() + g.color = Color.WHITE + g.fillRect(0, 0, totalSize, totalSize) + + val offset = (totalSize - contentSize) / 2 + for (x in 0 until contentSize) { + for (y in 0 until contentSize) { + if (bitMatrix.get(x, y)) { + image.setRGB(x + offset, y + offset, Color.BLACK.rgb) + } } } - - // Crop QR code (removes quiet zone excess if any) - val cropped = cropToContent(image) + g.dispose() val baos = ByteArrayOutputStream() - ImageIO.write(cropped, "bmp", baos) - return BitmapResult(baos.toByteArray(), cropped.width) + ImageIO.write(image, "bmp", baos) + + return BitmapResult(baos.toByteArray(), image.width) } private fun cropToContent(img: BufferedImage): BufferedImage { diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/PlasticBagPrinterController.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/PlasticBagPrinterController.kt index 7b16662..2b20ab6 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/PlasticBagPrinterController.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/PlasticBagPrinterController.kt @@ -38,7 +38,7 @@ class PlasticBagPrinterController( // Set headers for file download response.contentType = "application/zip" - response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"Job_$lotNo.zip\"") + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"TT_${itemCode}_Job.zip\"") response.setContentLength(zipBytes.size) // Write to response stream