65.9K
CodeProject 正在变化。 阅读更多。
Home

在 ESC/POS 热敏打印机上打印带有文本换行和对齐的图像

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2019年11月14日

CPOL

1分钟阅读

viewsIcon

14042

一种在 ESC/POS 热敏打印机上打印位图图像,并实现文本换行和对齐的算法。

引言

首先,我已经将收据打印机连接到 Android 设备。由于它已经连接到串口,我不需要考虑连接问题。我只需要将字节数组发送到打印机即可。但是,此打印机无法打印韩文字体,因为它不包含韩文字体。此外,我没有时间,所以我需要一个打印图像数据到收据打印机的示例代码。如果我能找到该代码,我想我就可以将韩文字符串打印到打印机上。

背景

我找到一个我几乎想要的代码,链接如下:

如你所知,如果你点击链接,你可以分析源代码。并且,在学习我下面的代码之前,你必须理解这个示例源代码。实际上,你不需要了解所有的示例代码。我使用 'Utils' 类中的函数,因为我将所有文本都作为图像打印。你应该从 'decodeBitmap' 函数开始。

你会发现这个 'printPhoto' 函数无法打印超过 250 像素的图像。所以,我将逐行逐字符串地调用此函数。

Using the Code

以下代码是我开始打印的地方。

// I will send the Byte Array using this List sequentially per Items to Printer.
Val list: Mutablelist<bytearray> = Arraylist()

// First, Init Printer
Val Cmd_init = Bytearrayof(27, 64)
list.add(CMD_INIT)
list.add(byteArrayOf(0x1B, 0x21, 0x03))

// This is the String to print.
// I should process the character,'\n', as Line Feed.
// as you can see the Third Parameter. I should process the alignment for Text String.
Var Command = Getimagedata
              (logger, "Abcdefghijkl\n안녕하세요\nmnopqrstuvwxyg", Paint.Align.CENTER)
If(command != null) list.add((command))

// This is just for separate line. It's not important.
list.add("------------------------------------------\n".toByteArray())

// Current time printing
Val Now = System.currentTimeMillis()
Val Date = Date(now)
Val Sdfnow = Simpledateformat("시간: Yyyy/mm/dd  Hh:mm:ss a")
Val Formatdate = sdfNow.format(date)
Command = Getimagedata(logger, Formatdate)
If(command != null) list.add((command))

// Cutting command
Val Cmd_cut = Bytearrayof(0x1d, 0x56, 0)
list.add(CMD_CUT)

// Send all List Items data to printer
// You should not know about this.
// All you have to know is the codes bolded below.
Var prt: Printer? = Null

Try {
    Prt = Printer.newInstance()

    if (!prt!!.ready()) {
        logger.error("Printer Is Not Ready Before printing.")
        Return
    }

    For (I in list.indices) {
        prt.outputStream.write(list.get(i))
    }

    if (!prt.ready()) {
        logger.error("Printer Is Not Ready After printing.")
        Return
    }

} Catch (e: Throwable) {
    logger.error("An Exception Issued in Printing. $e")
} Finally {
    prt?.close()
}

以下函数是 'getImageData'。这是主要代码。

fun getImageData(logger:Logger, stringData:String, 
                 align:Paint.Align = Paint.Align.LEFT): ByteArray? {

    var command:ByteArray? = null
    try {
        val pnt: Paint = Paint()

        pnt.setAntiAlias(true)
        pnt.setColor(Color.BLACK)
        pnt.setTextSize(23f)

        // A real printlabel width (pixel)
        var xWidth = 385

        // A height per text line (pixel)
        var xHeight = 30

        // it can be changed if the align's value is CENTER or RIGHT
        var xPos = 0f

        // If the original string data's length is over the width of print label,
        // or '\n' character included,
        // it will be increased per line gerneating.
        var yPos = 27f

        // If the original string data's length is over the width of print label,
        // or '\n' character included,
        // each lines splitted from the original string are added in this list
        // 'PrintData' class has 3 members, x, y, and splitted string data.
        var finalStringDatas:MutableList<PrintData> = ArrayList()

        // if '\n' character included in the original string
        var tmpSplitList:List<String> = stringData.split('\n')
        for(i in 0..tmpSplitList.count()-1)
        {
            val tmpString = tmpSplitList[i]

            // calculate a width in each split string item.
            var fWidthOfString = pnt.measureText(tmpString)

            // If the each split string item's length is over the width of print label,
            if (fWidthOfString > xWidth)
            {
                var lastString = tmpString
                while(!lastString.isEmpty()) {

                    var tmpSubString = ""

                    // retrieve repeatedly until each split string item's length is 
                    // under the width of print label
                    while(fWidthOfString > xWidth)
                    {
                        if (tmpSubString.isEmpty())
                            tmpSubString = lastString.substring(0, lastString.length-1)
                        else
                            tmpSubString = tmpSubString.substring(0, tmpSubString.length-1)

                        fWidthOfString = pnt.measureText(tmpSubString)
                    }

                    // this each split string item is finally done.
                    if (tmpSubString.isEmpty())
                    {
                        // this last string to print is need to adjust align
                        if(align == Paint.Align.CENTER)
                        {
                            if(fWidthOfString < xWidth) {
                                xPos = ((xWidth - fWidthOfString) / 2)
                            }
                        }
                        else if(align == Paint.Align.RIGHT)
                        {
                            if(fWidthOfString < xWidth) {
                                xPos = xWidth - fWidthOfString
                            }
                        }
                        finalStringDatas.add(PrintData(xPos, yPos, lastString))
                        lastString = ""
                    }
                    else
                    {
                        // When this logic is reached out here, it means, 
                        // it's not necessary to calculate the x position
                        // 'cause this string line's width is almost the same 
                        // with the width of print label
                        finalStringDatas.add(PrintData(0f, yPos, tmpSubString))

                        // It means line is needed to increase
                        yPos += 27
                        xHeight += 30

                        lastString = lastString.replaceFirst(tmpSubString, "")
                        fWidthOfString = pnt.measureText(lastString)
                    }
                }
            }
            else
            {
                // This split string item's length is 
                // under the width of print label already at first.
                if(align == Paint.Align.CENTER)
                {
                    if(fWidthOfString < xWidth) {
                        xPos = ((xWidth - fWidthOfString) / 2)
                    }
                }
                else if(align == Paint.Align.RIGHT)
                {
                    if(fWidthOfString < xWidth) {
                        xPos = xWidth - fWidthOfString
                    }
                }
                finalStringDatas.add(PrintData(xPos, yPos, tmpString))
            }

            if (i != tmpSplitList.count()-1)
            {
                // It means the line is needed to increase
                yPos += 27
                xHeight += 30
            }
        }

        // If you want to print the text bold
        //pnt.setTypeface(Typeface.create(null as String?, Typeface.BOLD))

        // create bitmap by calculated width and height as upper.
        val bm:Bitmap = Bitmap.createBitmap(xWidth, xHeight, Bitmap.Config.ARGB_8888)
        val canvas: Canvas = Canvas(bm)
        canvas.drawColor(Color.WHITE)

        for(tmpItem in finalStringDatas)
            canvas.drawText(tmpItem.strData, tmpItem.xPos, tmpItem.yPos, pnt)

        command = Utils.decodeBitmap(bm)
    }
    catch (e: Exception) {
        logger.error(e.printStackTrace())
    }

    return command
}

以下类是 'PrintData'。

class PrintData (var xPos:Float, var yPos:Float, var strData:String)

历史

  • 2019年11月14日:首次更新
  • 2019年11月15日:添加了 'PrintData' 类。样式已更改。
© . All rights reserved.