You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android热敏打印机打印高度超255px的Bitmap问题求助

Android热敏打印机Bitmap打印问题解决方案

1. 修复高度超过255px时的打印异常

问题根源

原decodeBitmap函数因单字节高度限制(<=255px)返回null,直接移除限制后打印空标签,是因为:

  • 原指令使用了仅支持单字节高度的ESC/POS模式,高度超过255时参数传递错误
  • Bitmap转二值化字节数组的逻辑可能存在错误,导致输出全空数据

解决方案

改用支持双字节高度的ESC/POS位图指令模式,同时修正二值化转换逻辑:

public byte[] decodeBitmap(Bitmap bitmap) {
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    // 计算每行字节数(每字节表示8个纵向点)
    int bytesPerLine = (width + 7) / 8;
    byte[] bitmapBytes = new byte[bytesPerLine * height];

    // 二值化转换(亮度阈值可根据打印效果调整)
    int threshold = 127;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int pixel = bitmap.getPixel(x, y);
            int gray = (Color.red(pixel) + Color.green(pixel) + Color.blue(pixel)) / 3;
            int byteIdx = y * bytesPerLine + (x / 8);
            int bitPos = 7 - (x % 8);
            // 低于阈值标记为黑点(置1),否则白点(置0)
            if (gray < threshold) {
                bitmapBytes[byteIdx] |= (1 << bitPos);
            } else {
                bitmapBytes[byteIdx] &= ~(1 << bitPos);
            }
        }
    }

    // 构建ESC/POS打印指令(模式3支持双字节宽高)
    byte[] cmdHeader = new byte[]{
        0x1B, 0x2A, // ESC * 指令前缀
        0x03,       // 模式3(24点密度,适配多数热敏打印机)
        (byte)(width & 0xFF), (byte)((width >> 8) & 0xFF), // 宽度低/高字节
        (byte)(height & 0xFF), (byte)((height >> 8) & 0xFF), // 高度低/高字节
        0x0A        // 换行指令(可选,按需添加)
    };

    // 合并指令与位图数据
    byte[] printData = new byte[cmdHeader.length + bitmapBytes.length];
    System.arraycopy(cmdHeader, 0, printData, 0, cmdHeader.length);
    System.arraycopy(bitmapBytes, 0, printData, cmdHeader.length, bitmapBytes.length);

    bitmap.recycle();
    return printData;
}

2. 实现Bitmap旋转与2倍缩放

针对窄幅面打印机,通过Matrix实现旋转(适配宽度)+ 2倍缩放,同时注意内存回收:

public Bitmap transformBitmap(Bitmap original) {
    Matrix matrix = new Matrix();
    // 旋转90度(根据打印机幅面方向调整为270度)
    matrix.postRotate(90);
    // 2倍缩放(宽高同时放大)
    matrix.postScale(2f, 2f);
    // 生成转换后的Bitmap
    Bitmap transformed = Bitmap.createBitmap(
        original, 0, 0, original.getWidth(), original.getHeight(),
        matrix, true
    );
    // 回收原Bitmap避免内存泄漏
    original.recycle();
    return transformed;
}

3. 完整打印流程示例

// 假设已获取打印机输出流
OutputStream printerStream = ...;

try {
    // 加载原图片
    Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.print_image);
    // 旋转缩放处理
    Bitmap readyBitmap = transformBitmap(originalBitmap);
    // 转换为打印字节数组
    byte[] printBytes = decodeBitmap(readyBitmap);
    // 发送至打印机
    printerStream.write(printBytes);
    printerStream.flush();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    // 回收资源
    if (readyBitmap != null && !readyBitmap.isRecycled()) {
        readyBitmap.recycle();
    }
    try {
        if (printerStream != null) {
            printerStream.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

注意事项

  • 不同打印机的ESC/POS指令可能存在差异,若模式3不兼容,可尝试模式1(单字节高度,需拆分大图分块打印)
  • 二值化阈值可根据实际打印效果调整(建议范围100-150)
  • 处理大图片时,建议先压缩原Bitmap尺寸,避免OOM

内容的提问来源于stack exchange,提问作者Eder Alexis Pirsch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 20:50:13