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





5.00/5 (1投票)
一种在 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
' 类。样式已更改。