ESC/POS指令的热敏小票打印机打印bmp纪要

为了在小票上打印二维码,折腾了好多天,终于搞定了,现将关键点做个记录。

  • 二维码的打印,首先是根据内容生成二维码bmp图片,这个我是通过网上找的一个叫qrencode的lib实现的,生成的bmp为24位的图片,我花费好多天没有成功的原因首先就是没搞清ESC/POS指令中关于位图打印的命令需要的是单色位图数据,还有对于命令中的宽度高度等参数没有搞清什么nL,nH的含义,原来是用两个自己来表示的一个数值(低8位和高8位,所以一般传的值就是x%256和x/256),搞清了这两点就是成功的关键。所以需要在qrencode生成的bmp基础上对位图进行调整后才能满足打印命令的需要。
  • 第一步就是对生成的24位二维码bmp进行尺寸修正,这个要视小票宽度来定,比如58mm的纸一般384点/行,两边预留一点的话,基本上最大就是344(此值一般定义为8的倍数,否则打印时补的位会是黑块),所以在调整时对于原始的bmp超过此值的话需要进行缩放至此值(bmp缩放可自行搜索,这个简单),调整好宽度后,再将24位图转换为单色图(1位,这个也不难)。
  • 经过第一步的调整后就可以读取并打印bmp了。我使用的是GS v 0 m xL xH yLyH d1...dk 这个命令来打印的,直接上代码了。此打印函数支持58mm和80mm,_nPaperType=0表示58mm,1表示80mm。其中的Write函数是向打印机写数据的。Feed是调用Write打印空行的。如下:

void printBmp(LPCSTR _file, BOOL _bCenter, int _nPaperType)
{
    long lWidth, lHeight;
    BITMAPFILEHEADER bf;
    BITMAPINFOHEADER bi;
    FILE *fileR;
    fopen_s(&fileR, _file, "rb");
    if (fileR)
    {
        fread(&bf, sizeof(BITMAPFILEHEADER), 1, fileR);
        fread(&bi, sizeof(BITMAPINFOHEADER), 1, fileR);
        RGBQUAD rgb[2];
        fread(rgb, 2 * sizeof(RGBQUAD), 1, fileR);    // 读颜色表信息
        lWidth = bi.biWidth;
        lWidth = (lWidth % 8 == 0) ? (lWidth / 8) : (lWidth / 8 + 1); // 宽度由点数调整为字节数
        long lWidthBmp = (lWidth % 4 == 0) ? lWidth : (lWidth + 4 - (lWidth % 4)); // 如果字节数不是4的倍数,要调整为4的倍数个
        lHeight = bi.biHeight;
        if (lHeight < 0)
        {
            lHeight *= -1; // 高度值为负数时需要转为正的
        }
        long lImageSize = lWidthBmp*lHeight; // 要读取的图像数据长度
        BYTE *pData = new BYTE[lImageSize];
        fread(pData, lImageSize, 1, fileR);
        fclose(fileR);
        Write((BYTE*)"\x1B\x33\x15", 3L);  // 调整行间距,以便图片和上下的内容保持合适的间距
        Feed(1);        // 空一行
        if (_bCenter)
        {
            Write((BYTE*)"\x1B\x61\x01", 3L);  // 居中
        }
        BYTE buf[] = { 0x1d, 0x76, 0x30, 0x00, BYTE(lWidth % 256), BYTE(lWidth / 256), BYTE(lHeight % 256), BYTE(lHeight / 256) };
        Write(buf, 8L);

        // bi.biHeight 为负时,从上到下逐行遍历,反之从下到上
        for (int y = (bi.biHeight < 0)? 0 : (lHeight - 1); (bi.biHeight < 0) ? (y < lHeight) : (y >= 0); y += (bi.biHeight < 0) ? 1 : -1)
        {
            for (int x = 0; x < lWidthBmp; ++x)
            {
                if (x < lWidth)        // 有效数据范围内
                {
                    if (x == lWidth - 1)  // 最后一个有效字节
                    {
                        int n = bi.biWidth % 8;        // 余数,大于0说明有补位
                        if (n > 0)        // 如果最后一位有补位,将补位置为 1,翻转后就不打印
                        {
                            pData[y*lWidthBmp + x] |= (0xff >> n);
                        }
                    }
                    pData[y*lWidthBmp + x] = ~pData[y*lWidthBmp + x];        // 黑白翻转
                    Write(pData + y*lWidthBmp + x, 1L);
                }
            }
        }
        delete pData;
        if (_bCenter)
        {
            Write((BYTE*)"\x1B\x61\x00", 3L);  // 恢复左对齐
        }
        Feed(1);        // 空行
        Write((BYTE*)"\x1B\x32", 2L);  // 恢复默认行间距
    }
}

 

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

starytx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值