打印图片到热敏打印机,但结果显示奇怪的字符 Android

huangapple go评论98阅读模式
英文:

Print Image to Printer Thermal but the result give weird character Android

问题

我为Google Chrome浏览器构建了打印服务。从技术上讲,我将PDF转换为图像,然后将其转换为字节数组,然后进行打印。但在某些设备上,结果会出现奇怪的字符。以下是代码:

PrintService.class

byte[] image = bitmapToBytes(rescaledBitmap, false);
byte[][] bytesToPrint = convertGSv0ToEscAsterisk(image);
timestamp = new Timestamp(System.currentTimeMillis());

for (byte[] bytes : bytesToPrint) {
    this.mOutputStream.write(bytes);
    this.mOutputStream.flush();
}
String endLine = "\n\n\n\n\n";
this.mOutputStream.write(endLine.getBytes());
....
....

public static byte[] bitmapToBytes(Bitmap bitmap, boolean gradient) {
    // 省略部分代码
    return imageBytes;
}

public static byte[][] convertGSv0ToEscAsterisk(byte[] bytes) {
    // 省略部分代码
    return returnedBytes;
}

在某些设备上,结果如下所示:

打印图片到热敏打印机,但结果显示奇怪的字符 Android

但在某些设备上,结果也是正常的。我陷入了修复这个问题几天了。是否有其他将位图转换为字节数组以供热敏打印机打印的方法?非常感谢任何建议。

英文:

I build print service for Google Chrome browser. technically I convert the PDF into image then convert it to byte array then do print. But on some device give the weird character on result. Here is the code :

PrintService.class

byte[] image = bitmapToBytes(rescaledBitmap, false);
byte[][] bytesToPrint = convertGSv0ToEscAsterisk(image);
timestamp = new Timestamp(System.currentTimeMillis());

for (byte[] bytes : bytesToPrint) {
    this.mOutputStream.write(bytes);
    this.mOutputStream.flush();
}
String endLine = "\n\n\n\n\n";
this.mOutputStream.write(endLine.getBytes());
....
....

public static byte[] bitmapToBytes(Bitmap bitmap, boolean gradient) {
    int bitmapWidth = bitmap.getWidth();
    int bitmapHeight = bitmap.getHeight();
    int bytesByLine = (bitmapWidth + 7) / 8;
    byte[] imageBytes = new byte[bytesByLine * bitmapHeight + 8];
    int i = 8;
    int greyscaleCoefficientInit = 0;
    int gradientStep = 6;
    double colorLevelStep = 765.0 / (15 * gradientStep + gradientStep - 1);

    for (int posY = 0; posY < bitmapHeight; posY++) {
        int greyscaleCoefficient = greyscaleCoefficientInit;
        int greyscaleLine = posY % gradientStep;

        for (int j = 0; j < bitmapWidth; j += 8) {
            int b = 0;

            for (int k = 0; k < 8; k++) {
                int posX = j + k;

                if (posX < bitmapWidth) {
                    int color = bitmap.getPixel(posX, posY);
                    int red = Color.red(color);
                    int green = Color.green(color);
                    int blue = Color.blue(color);

                    if ((gradient && (red + green + blue) < ((greyscaleCoefficient * gradientStep + greyscaleLine) * colorLevelStep))
                            || (!gradient && (red < 160 || green < 160 || blue < 160))) {
                        b |= 1 << (7 - k);
                    }

                    greyscaleCoefficient += 5;
                    if (greyscaleCoefficient > 15) {
                        greyscaleCoefficient -= 16;
                    }
                }
            }
            imageBytes[i++] = (byte) b;
        }

        greyscaleCoefficientInit += 2;
        if (greyscaleCoefficientInit > 15) {
            greyscaleCoefficientInit = 0;
        }
    }

    imageBytes[4] = (byte) (bytesByLine & 0xFF);
    imageBytes[5] = (byte) ((bytesByLine >> 8) & 0xFF);
    imageBytes[6] = (byte) (bitmapHeight & 0xFF);
    imageBytes[7] = (byte) ((bitmapHeight >> 8) & 0xFF);

    return imageBytes;
}

public static byte[][] convertGSv0ToEscAsterisk(byte[] bytes) {
    final byte LF = 0x0A;
    final byte[] LINE_SPACING_30 = {0x1b, 0x33, 0x1e};
    final byte[] LINE_SPACING_24 = {0x1b, 0x33, 0x18};

    int
            xL = bytes[4] & 0xFF,
            xH = bytes[5] & 0xFF,
            yL = bytes[6] & 0xFF,
            yH = bytes[7] & 0xFF,
            bytesByLine = xH * 256 + xL,
            dotsByLine = bytesByLine * 8,
            nH = dotsByLine / 256,
            nL = dotsByLine % 256,
            imageHeight = yH * 256 + yL,
            imageLineHeightCount = (int) Math.ceil((double) imageHeight / 24.0),
            imageBytesSize = 6 + bytesByLine * 24;

    byte[][] returnedBytes = new byte[imageLineHeightCount + 2][];
    returnedBytes[0] = LINE_SPACING_24;
    for (int i = 0; i < imageLineHeightCount; ++i) {
        int pxBaseRow = i * 24;
        byte[] imageBytes = new byte[imageBytesSize];
        imageBytes[0] = 0x1B;
        imageBytes[1] = 0x2A;
        imageBytes[2] = 0x21;
        imageBytes[3] = (byte) nL;
        imageBytes[4] = (byte) nH;
        for (int j = 5; j < imageBytes.length; ++j) {
            int
                    imgByte = j - 5,
                    byteRow = imgByte % 3,
                    pxColumn = imgByte / 3,
                    bitColumn = 1 << (7 - pxColumn % 8),
                    pxRow = pxBaseRow + byteRow * 8;
            for (int k = 0; k < 8; ++k) {
                int indexBytes = bytesByLine * (pxRow + k) + pxColumn / 8 + 8;

                if (indexBytes >= bytes.length) {
                    break;
                }

                boolean isBlack = (bytes[indexBytes] & bitColumn) == bitColumn;
                if (isBlack) {
                    imageBytes[j] |= 1 << 7 - k;
                }
            }
        }
        imageBytes[imageBytes.length - 1] = LF;
        returnedBytes[i + 1] = imageBytes;
    }
    returnedBytes[returnedBytes.length - 1] = LINE_SPACING_30;
    return returnedBytes;
}

On some device, result is like below below :

打印图片到热敏打印机,但结果显示奇怪的字符 Android

But on some device the result is normal too. I stuck fixing this for couple days. Is there another method to convert bitmap to byte array for printing to thermal printer? I really appreciate any suggestion.

答案1

得分: 0

这个问题发生是因为打印处理仍在运行,但套接字已关闭。所以奇怪的字符是之前进程的一部分。但这个问题只在一些打印机设备上发生(具有相同长度的字节)。所以我添加了一些用户界面(以秒为单位)来定义在打印后关闭套接字的时间(默认为0)。

for (byte[] bytes : bytesToPrint) {
    this.mOutputStream.write(bytes);
    this.mOutputStream.flush();
}
String endLine = "\n\n\n\n\n";
this.mOutputStream.write(endLine.getBytes());

Handler handler = new Handler();
handler.postDelayed(() -> {
    try {
        closeBTPrinter();
    } catch (IOException e) {
        e.printStackTrace();
    }
}, socketTimeOut);
英文:

This problem occur because print processing still running but the socket was close. So the weird character is part of previous process. But this problem only occur in some printer devices (with same length bytes). So I add some UI (time in second) for user to define time to close socket after printing (by default still is 0).

for (byte[] bytes : bytesToPrint) {
    this.mOutputStream.write(bytes);
    this.mOutputStream.flush();
}
String endLine = "\n\n\n\n\n";
this.mOutputStream.write(endLine.getBytes());

Handler handler = new Handler();
    handler.postDelayed(() -> {
        try {
            closeBTPrinter();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }, socketTimeOut);

huangapple
  • 本文由 发表于 2023年7月20日 16:43:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76728129.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定