iOS 热敏打印机打印位图

需求是希望通过ipad和iPhone连接局域网内的打印机打印餐馆小票,而小票中需要包含logo图片和二维码。我用的打印机是xprinter,根据开发文档提示,打印位图的命令是“ESC*mnLnHd1...dk”


ASCII码ESC *mnLnHd1...dk

十六进制1B 2AmnLnHd1...dk

十进制27 42mnLnHd1...dk


取值范围m = 0, 1, 32, 33

0 <= nL <= 255

0 <= nH <= 3

0 <= d <= 255

具体的参数解释可以查看对应打印机型号的开发文档,这里主要记录一些重要的点。有个问题就是在打印透明背景图片的时候仍然会出现乱码,把背景换成白色就正常了,暂时还没想到其它的解决办法,图片尺寸过大也会出现乱码


当前的项目是swift和objc结合使用的,因为对objc还不是太熟,swift开发也更快一点。打印机部分原理很简单,把数据直接用socket发送给打印机就可以了。


打印部分的代码:

<span style="white-space:pre">	</span>    let escBmp: Array<UInt8> = [27, 42, 33, 44, 1]<span style="white-space:pre">	</span>//切换到位图模式的命令
            let invoiceTitleImg: UIImage? = common.UIImageFromName("invoice_title") //获取图片
            if invoiceTitleImg != nil {
                for (var i = 0; i < (Int(invoiceTitleImg!.size.height) / 24) + 1; i++) {
                    //setting
                    client!.send(data: getArrayUInt8("\t   "))<span style="white-space:pre">	</span>//打印的图片默认说靠左边,这里是设置的居中,文档中暂时没有找到居中部分的命令,只能先将就这样用着
                    var psplite: Array<UInt8> = [27, 51, 0]
                    client!.send(data: escBmp)
                    var data: Array<UInt8> = [0x1B, 0x33, 0x00]<span style="white-space:pre">	</span>//使用的图片是24点双密度
                    data[0] = 0x00
                    data[1] = 0x00
                    data[2] = 0x00
                    //loop
                    for (var j = 0; j < Int(invoiceTitleImg!.size.width); j++) {
                        for (var k = 0; k < 24; k++) {
                            if ((i * 24) + k) < Int(invoiceTitleImg!.size.height) {
                                let point: CGPoint = CGPoint(x: j, y: ((i * 24) + k))
                                let index = 4*((invoiceTitleImg!.size.width * round(point.y)) + round(point.x))
                                let red = getRed(titleBitmap!, index: Int(index))
                                if red == 0 {
                                    data[k / 8] += Byte(128 >> (k % 8))
                                }
                                //println(red)
                            }
                        }
                        client!.send(data: data)
                        data[0] = 0x00
                        data[1] = 0x00
                        data[2] = 0x00
                    }
                    client!.send(data: _p_space)
                }
            }

获取位图信息的代码,代码从网上找的

+(unsigned char *) getBitmapFromUIImage:(UIImage *)image {
    CGImageRef imageRef = image.CGImage;
    CGContextRef context = [self newBitmapRGBA8ContextFromImage:imageRef];
    if (!context) {
        return NULL;
    }
    size_t width = CGImageGetWidth(imageRef);
    size_t height = CGImageGetHeight(imageRef);
    
    CGRect rect = CGRectMake(0, 0, width, height);
    CGContextDrawImage(context, rect, imageRef);
    
    unsigned char *bitmapData = (unsigned char *)CGBitmapContextGetData(context);
    size_t bytesPerRow = CGBitmapContextGetBytesPerRow(context);
    size_t bufferLength = bytesPerRow * height;
    
    unsigned char *newBitmap = NULL;
    if (bitmapData) {
        newBitmap = (unsigned char *)malloc(sizeof(unsigned char) * bytesPerRow * height);
        if (newBitmap) {
            for (int i = 0; i < bufferLength; ++i) {
                newBitmap[i] = bitmapData[i];
            }
        }
        free(bitmapData);
    }
    CGContextRelease(context);
    return newBitmap;
}

+(CGContextRef) newBitmapRGBA8ContextFromImage:(CGImageRef) image {
    CGContextRef context = NULL;
    CGColorSpaceRef colorSpace;
    uint32_t *bitmapData;
    
    size_t bitsPerPixel = 32;
    size_t bitsPerComponent = 8;
    size_t bytesPerPixel = bitsPerPixel / bitsPerComponent;
    
    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);
    
    size_t bytesPerRow = width * bytesPerPixel;
    size_t bufferLength = bytesPerRow * height;
    
    colorSpace = CGColorSpaceCreateDeviceRGB();
    if (!colorSpace) {
        return NULL;
    }
    bitmapData = (uint32_t *)malloc(bufferLength);
    if (!bitmapData) {
        CGColorSpaceRelease(colorSpace);
        return NULL;
    }
    context = CGBitmapContextCreate(bitmapData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
    if (!context) {
        free(bitmapData);
    }
    CGColorSpaceRelease(colorSpace);
    return context;
}

获取像素信息是从位图byte字节中获取的

    private func getRed(point: UnsafeMutablePointer<UInt8>, index: Int) -> UInt8{
        let red = point[index]
        //println(red)
        return red
    }


*在打印中文的时候碰到点问题,使用utf8编码点字节打印出来说乱码,之后中文档中才看到应该用gb2312,而swift中也没有对应的方法可以直接转换编码的。

utf8对英文使用8位(一个字节)进行编码,而对中文说用24位(3个字节)编码,所以打印的时候只有中文才会出现乱码情况。

NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);

2000年的gb18030是取代gbk1.0的正式国家标准,该标准收录了27484个汉子,同时还收录来藏文,蒙文,维吾尔文等主要的少数民族文字


版权声明:本文为xjmeplws原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。