浏览代码

Merge remote-tracking branch 'origin/master'

master
B.E.N.S.O.N 3 周前
父节点
当前提交
4f66c4ede4
共有 1 个文件被更改,包括 79 次插入32 次删除
  1. +79
    -32
      src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt

+ 79
- 32
src/main/java/com/ffii/fpsms/modules/jobOrder/service/PlasticBagPrinterService.kt 查看文件

@@ -7,6 +7,8 @@ import org.springframework.stereotype.Service

import java.awt.Color
import java.awt.Font
import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.util.zip.ZipEntry
@@ -20,6 +22,9 @@ import java.io.PrintWriter
import java.io.DataOutputStream
import java.nio.charset.Charset

// 1. Data class to store both the raw bytes and the width for XML injection
data class BitmapResult(val bytes: ByteArray, val width: Int)

@Service
open class PlasticBagPrinterService(
val jobOrderRepository: JobOrderRepository,
@@ -28,65 +33,105 @@ open class PlasticBagPrinterService(
val baos = ByteArrayOutputStream()
ZipOutputStream(baos).use { zos ->
// Use unique names based on the Lot Number
// Generate Bitmaps and capture their widths
val productBmp = createMonochromeBitmap(productName, 704)
val codeBmp = createMonochromeBitmap(itemCode, 1173)
val expBmp = createMonochromeBitmap(expiryDate, 1173)
val qrBmp = createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 1000)

val nameFile = "${lotNo}_product.bmp"
val codeFile = "${lotNo}_code.bmp"
val expFile = "${lotNo}_expiry.bmp"
val qrFile = "${lotNo}_qr.bmp"

// 1. Generate Bitmaps
addToZip(zos, nameFile, createMonochromeBitmap(productName, 5365, 704))
addToZip(zos, expFile, createMonochromeBitmap(expiryDate, 4203, 1173))
addToZip(zos, qrFile, createQrCodeBitmap("$itemCode|$lotNo|$expiryDate", 1000))
// Now "bytes" property is resolved
addToZip(zos, nameFile, productBmp.bytes)
addToZip(zos, codeFile, codeBmp.bytes)
addToZip(zos, expFile, expBmp.bytes)
addToZip(zos, qrFile, qrBmp.bytes)

// 2. Generate the .image file with dynamic references
// 2. Generate the .image file with XML headers and mandatory X40 tags
val imageXml = """
<?xml version="1.0" encoding="utf-8"?>
<Legend type="Image.V1" PaperColor="White" BackgroundColor="DarkGray">
<DeviceInfo DeviceURI="NGEDriver[SDX40c.cadb94e3-677c-4bcb-9c80-88bf9526d6fe]/"><DeviceName /></DeviceInfo>
<Mirrored>false</Mirrored>
<Orientation>DEG_0</Orientation>
<Width>5300</Width><Height>7100</Height>
<FieldList>
<Logo>
<Name>PRODUCT_NAME</Name>
<Logo type="Logo.V1">
<Name>LOGO</Name>
<Geometry><X>0</X><Y>250</Y></Geometry>
<FieldColor>BLACK</FieldColor>
<FileName>$nameFile</FileName>
<Width>${productBmp.width}</Width>
<Height>704</Height>
</Logo>
<Logo>
<Name>EXPIRY_DATE</Name>
<Logo type="Logo.V1">
<Name>LOGO_2</Name>
<Geometry><X>1000</X><Y>1250</Y></Geometry>
<FieldColor>BLACK</FieldColor>
<FileName>$codeFile</FileName>
<Width>${codeBmp.width}</Width>
<Height>1173</Height>
</Logo>
<Logo type="Logo.V1">
<Name>LOGO_3</Name>
<Geometry><X>500</X><Y>2500</Y></Geometry>
<FieldColor>BLACK</FieldColor>
<FileName>$expFile</FileName>
<Width>${expBmp.width}</Width>
<Height>1173</Height>
</Logo>
<Logo>
<Name>QR_CODE</Name>
<Logo type="Logo.V1">
<Name>LOGO_4</Name>
<Geometry><X>750</X><Y>3750</Y></Geometry>
<FieldColor>BLACK</FieldColor>
<FileName>$qrFile</FileName>
<Width>${qrBmp.width}</Width>
<Height>1000</Height>
</Logo>
</FieldList>
</Legend>
""".trimIndent()
addToZip(zos, "$lotNo.image", imageXml.toByteArray())
addToZip(zos, "$lotNo.image", imageXml.toByteArray(Charsets.UTF_8))
// 3. Generate the .job file pointing to the new .image [cite: 2]
val jobXml = "<Job><ImageFileName>$lotNo.image</ImageFileName></Job>"
addToZip(zos, "$lotNo.job", jobXml.toByteArray())
val jobXml = """<?xml version="1.0" encoding="utf-8"?><Job><ImageFileName>$lotNo.image</ImageFileName></Job>"""
addToZip(zos, "$lotNo.job", jobXml.toByteArray(Charsets.UTF_8))
}
return baos.toByteArray()
}

private fun createMonochromeBitmap(text: String, width: Int, height: Int): ByteArray {
val image = BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY) // Essential for printers
val g = image.createGraphics()
g.color = Color.WHITE
g.fillRect(0, 0, width, height)
g.color = Color.BLACK
g.font = Font("Arial", Font.BOLD, 400)
g.drawString(text, 50, height - 200)
g.dispose()
private fun createMonochromeBitmap(text: String, maxHeight: Int): BitmapResult {
val tempImg = BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY)
val g2dTemp = tempImg.createGraphics()
val font = Font("SimSun", Font.BOLD, (maxHeight * 0.8).toInt())
g2dTemp.font = font
val metrics = g2dTemp.getFontMetrics(font)
val width = metrics.stringWidth(text).let { if (it < 1) 1 else it }
val height = maxHeight
g2dTemp.dispose()

val finalImg = BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY)
val g2d = finalImg.createGraphics()
g2d.color = Color.WHITE
g2d.fillRect(0, 0, width, height)
g2d.color = Color.BLACK
g2d.font = font
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
g2d.drawString(text, 0, metrics.ascent)
g2d.dispose()

val baos = ByteArrayOutputStream()
ImageIO.write(image, "bmp", baos)
return baos.toByteArray()
ImageIO.write(finalImg, "bmp", baos)
return BitmapResult(baos.toByteArray(), width)
}

private fun createQrCodeBitmap(content: String, size: Int): ByteArray {
val bitMatrix = QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, size, size)
private fun createQrCodeBitmap(content: String, size: Int): BitmapResult {
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) {
@@ -95,11 +140,13 @@ open class PlasticBagPrinterService(
}
val baos = ByteArrayOutputStream()
ImageIO.write(image, "bmp", baos)
return baos.toByteArray()
// For QR code, width and height are the same (size)
return BitmapResult(baos.toByteArray(), size)
}

private fun addToZip(zos: ZipOutputStream, fileName: String, content: ByteArray) {
zos.putNextEntry(ZipEntry(fileName))
private fun addToZip(zos: ZipOutputStream, entryName: String, content: ByteArray) {
val entry = ZipEntry(entryName)
zos.putNextEntry(entry)
zos.write(content)
zos.closeEntry()
}


正在加载...
取消
保存