需求是希望通过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版权协议,转载请附上原文出处链接和本声明。