spirngboot + 佳博标签打印机踩坑记录
文章目录
前言:本项目基于
springboot
项目,后端调用打印机,佳博官方提供的Java
版demo
就可以满意整合需求
问题一:打印中文,乱码问题
- 描述:打印中文文字,打印出来的是乱码
- 解决方案:在每次打印前,设置这个参数
System.setProperty("jna.encoding", "GBK");
当时排查时,以为打印机没有这个楷体或者宋体等字体导致的问题,后来翻阅了大量打印机对接代码,突然看到这么一行,拿过来试一试,直接解决。
问题二:打印内容,左边边距坐标不能从(0,0)开始
- 描述:打印内容时,把x轴的坐标设置为0,但是每次打印距离左边都有一定的距离,而且距离有时候还不一样
- 解决方案:一样的参数,但是有时候打印出来的位置看起来有差异,因为卡纸位置没有固定住,用滚轴上的侧边东西把纸固定住;x轴不能从0开始打印,是打印机设计如此,通过佳博提供的官方电脑应用,可以测试出来,预览时,左边距大概默认是2mm;这个只能从产品设计上去规定,打印的内容左边距不能小于
2mm
,然后拿到参数X坐标减去2mm
既可以满足需求
佳博官网提供的打印应用,通过在线客服可以得到下载地址
问题三:打印图片,只能选择PCX和BMP
- 描述:我们产品需求是打印二维码,把二维码图片保存为
png
,jpg
的方法都烂大街了,但是保存为PCX
很少,保存为bmp
的也有,但是如何把bmp
通过代码转化为打印机期望的位深,以及如何发送到打印机内部,这个没研究明白。 - 解决方案:选择了
PCX
,使用的第三方依赖com.github.jai-imageio
,仓库地址
问题四:保存为PCX图片不能打印
- 描述:有时候我们通过代码转化出来的图片是属于RGB的,但是打印机需要的是
Bitmap
的格式的,在new BufferedImage()
时,图片类型设置为BufferedImage.TYPE_BYTE_BINARY
BufferedImage qrCode = new BufferedImage(qrCodeWidth,qrCodeHeight, BufferedImage.TYPE_BYTE_BINARY);
问题五:保存为PCX图片,但是右边有黑色竖线,这个问题独立于打印机,属于代码问题
- 描述:打印的二维码,有些尺寸打印出来有黑色的竖线,但是有的尺寸打印出来没有
- 解决方案:
- 方案一:后来发现只要打印的尺寸,是8的倍数就可以,通过补偿的方式来实现;余数小于等于4则减去余数;余数大于4则减去余数再加8,这样尺寸会有一些偏差,产品上如果能接受,也是可以的
int size = 139;
int remainder = size % 8;
if (remainder <= 4) {
size = size - remainder;
}
if (remainder > 4) {
size = size - remainder + 8;
}
- 方案二:修改
com.github.jai-imageio
的源码,这个方案是在方案一之前尝试的,但是代码注释很少,写的又是很多计算逻辑,也看的不太懂,代码于2018年就停止维护了,后来尝试了一天就战略放弃了,想到了方案一。当方案一处理好之后,灵光一闪,8???好像在代码里见过;直接上PCXImageWriter
的代码
public class PCXImageWriter extends ImageWriter implements PCXConstants {
private ImageOutputStream ios;
private Rectangle sourceRegion;
private Rectangle destinationRegion;
private int colorPlanes, bytesPerLine;
private Raster inputRaster = null;
private int scaleX, scaleY;
public PCXImageWriter(PCXImageWriterSpi imageWriterSpi) {
super(imageWriterSpi);
}
public void setOutput(Object output) {
super.setOutput(output); // validates output
if (output != null) {
if (!(output instanceof ImageOutputStream))
throw new IllegalArgumentException("output not instance of ImageOutputStream");
ios = (ImageOutputStream) output;
ios.setByteOrder(ByteOrder.LITTLE_ENDIAN);
} else
ios = null;
}
public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType, ImageWriteParam param) {
if (inData instanceof PCXMetadata)
return inData;
return null;
}
public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) {
return null;
}
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) {
PCXMetadata md = new PCXMetadata();
md.bitsPerPixel = (byte) imageType.getSampleModel().getSampleSize()[0];
return md;
}
public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
return null;
}
public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam param) throws IOException {
if (ios == null) {
throw new IllegalStateException("output stream is null");
}
if (image == null) {
throw new IllegalArgumentException("image is null");
}
clearAbortRequest();
processImageStarted(0);
if (param == null)
param = getDefaultWriteParam();
boolean writeRaster = image.hasRaster();
sourceRegion = param.getSourceRegion();
SampleModel sampleModel = null;
ColorModel colorModel