最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了。

这是DEMO的窗体:

下面是打印所需要调用的代码:

因为我们这里主要是打印条形码和二维码,所以以条形码和二维码为例,写了一个小的调用程序(这里把打印图片的方法贴出来):

/// <summary>
/// 打印图片方法
/// </summary>
public void PrintOne()
{
//获取图片
Bitmap bmp = new Bitmap(pictureBox1.Image); //设置字符行间距为n点行
//byte[] data = new byte[] { 0x1B, 0x33, 0x00 };
string send = "" + (char)() + (char)() + (char)();
byte[] data = new byte[send.Length];
for (int i = ; i < send.Length; i++)
{
data[i] = (byte)send[i];
}
lc.Write(data); data[] = (byte)'\x00';
data[] = (byte)'\x00';
data[] = (byte)'\x00'; // Clear to Zero. Color pixelColor; //ESC * m nL nH d1…dk 选择位图模式
// ESC * m nL nH
byte[] escBmp = new byte[] { 0x1B, 0x2A, 0x00, 0x00, 0x00 }; escBmp[] = (byte)'\x21'; //nL, nH
escBmp[] = (byte)(bmp.Width % );
escBmp[] = (byte)(bmp.Width / ); //循环图片像素打印图片
//循环高
for (int i = ; i < (bmp.Height / + ); i++)
{
//设置模式为位图模式
lc.Write(escBmp);
//循环宽
for (int j = ; j < bmp.Width; j++)
{
for (int k = ; k < ; k++)
{
if (((i * ) + k) < bmp.Height) // if within the BMP size
{
pixelColor = bmp.GetPixel(j, (i * ) + k);
if (pixelColor.R == )
{
data[k / ] += (byte)( >> (k % )); }
}
}
//一次写入一个data,24个像素
lc.Write(data); data[] = (byte)'\x00';
data[] = (byte)'\x00';
data[] = (byte)'\x00'; // Clear to Zero.
} //换行,打印第二行
byte[] data2 = { 0xA };
lc.Write(data2);
} // data
lc.Write("\n\n");
}

在打印过程中,出现一个比较低级的错误,因为小票打印机是并口的,而我电脑是串口的,所以一直远程在另一台电脑上测试,所以打印出来的图片中间多了一条横线,这个问题解决了多半天,因为我一直考虑到是打印图片中可能少一层循环的问题,所以顺便把打印图片的原理整理了一下(之前的循环是从网上找到的,感觉应该没问题就没有细研究)。下面分享一下我的理解:

这是打印位图的命令(每一个打印机都会给出这样的说明,可以直接下载到的):

1.  ESC* m nL nH d1…dk   选择位图模式

格式:   ASCII: ESC * m nL nH d1…dk

十进制:  [27] [42] m nL nH d1…dk

十六进制:  [1BH][2AH] m nL nH d1…dk

说明:

.设定位图方式(用m)、点数(用nL,nH)以及位图内容(用dk)。

.m=0,1,32,33;0≤nL≤255,0≤nH≤3,0≤d≤255。

k=nL+nH×256(m=0,1);k=(nL+nH×256)×3(m=32,33)。

.水平方向点数为(nL+nH×256)。

.如果点数超过一行,超过其最大点数(与选择的位图方式有关,详      见下表)的部分被忽略。

.d为位图数据字节,对应位为1则表示该点打印,对应位为0,则  表示该点不打印。(k表示数据个数)

.m用于选择位图方式。

模式

纵向

横向

点数

分辨率

分辨率

数据个数(k)

0

8点单密度

8

67  DPI

100  DPI

nL+nH×256

1

8点双密度

8

67  DPI

200  DPI

nL+nH×256

32

24点单密度

24

200  DPI

100  DPI

(nL+nH×256)×3

33

24点双密度

24

200  DPI

200  DPI

(nL+nH×256)×3

这次用的打印机打印是24点双密度的,所以我这里就只解释下m=33的情况。

从代码中可以看出,打印图片过程主要是通过循环一点点打印的,通过

lc.Write(data);

循环写入,当然前面的lc.Write(escBmp)主要是些ESC * m三个参数很容易理解就不多解释了。而data是一个长度为3的byte数组,这个data在打印中起到什么作用呢?

在打印机m=33的模式纵向每次是打印24个点,也就是说,而byte为8个字节,所以需要3个byte类型的树才能完成模式为24点双密码的位图打印方式,通过三个字符来平凑一个像素宽24个像素长的图片,然后循环宽度,来打印图片宽度大小24个像素高度的图片,在通过每次循环24个像素的高度,最终打印出完成的图片。

需要打印的图片:

第一次循环先是高位24像素

然后把宽度分解开,循环每一像素的宽度,然后打印每一像素宽度的图片:

举个例子,假设数组data[d1,d2,d3],d1= 00000111,d2=11111111,d3 =11111111,所以打印出的一个像素宽,24像素高的图片为:

最终通过循环宽度与高度,把最终的位图画出来。

这里我举的是24点密度的例子,通过,如果您有兴趣研究的话,也经常看到这样的代码:

for (int i = ; i < ((bmp.Height + ) / ); i++)
{
_serialPort.Write(escBmp, , escBmp.Length); for (int j = ; j < bmp.Width; j++)
{
for (int k = ; k < ; k++)
{
if (((i * ) + k) < bmp.Height) // if within the BMP size
{
pixelColor = bmp.GetPixel(j, (i * ) + k);
if (pixelColor.R == )
{
data[] += (byte)( >> k);
}
}
} _serialPort.Write(data, , );
data[] = (byte)'\x00'; // Clear to Zero.
}

这个很明显就是8点密度的模式,所以他的data长度为1,即需要8个字节就够了。

打印出的效果还是很不错的。

如果大家有兴趣研究网络打印,请参加小崔的博客:http://blog.csdn.net/xiaoxian8023/article/details/8440625#comments

C# 热敏打印机 小票打印机 打印图片的更多相关文章

  1. 转:C#并口热敏小票打印机打印位图

    最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了. 这是DEMO的窗体: 下面是打印所需要调用的代码: class LptControl { private s ...

  2. C#并口热敏小票打印机打印位图

    原文:C#并口热敏小票打印机打印位图 最近一直在研究并口小票打印机打印图片问题,这也是第一次和硬件打交道,不过还好,最终成功了.   这是DEMO的窗体:   下面是打印所需要调用的代码: class ...

  3. C#并口热敏小票打印机打印位图包括芯片的写入

    下面是打印所需要调用的代码: class LptControl { private string LptStr = "lpt1"; public LptControl(string ...

  4. C# Lpt 并口热敏小票打印机打印位图

    class LptControl { private string LptStr = "lpt1"; public LptControl(string l_LPT_Str) { L ...

  5. 【转】C#使用ESC指令控制POS打印机打印小票

    .前言 C#打印小票可以与普通打印机一样,调用PrintDocument实现.也可以发送标注你的ESC指令实现.由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的pos ...

  6. C#使用ESC指令控制POS打印机打印小票

    1.前言 C#打印小票可以与普通打印机一样,调用PrintDocument实现.也可以发送标注你的ESC指令实现.由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的po ...

  7. C# 热敏打印机 Socket 网络链接 打印 图片 (二)

    IPAddress ip = IPAddress.Parse("192.168.1.212"); IPEndPoint iport = );//9100为小票打印机指定端口 Soc ...

  8. C# 热敏打印机 Socket 网络链接 打印 图片 (一)

    using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using Syste ...

  9. C# 热敏打印机 Socket 网络链接 打印 图片

    C# 热敏打印机 Socket 网络链接 打印 图片 (一) http://www.cnblogs.com/rinack/p/4838211.html C# 热敏打印机 Socket 网络链接 打印 ...

随机推荐

  1. Java标识符规范

    1.标识符用来定义包名,类名,方法名,变量名,常量名. 2.标识符必须由字母.下划线.$符号组成,不能以数字开头.不能是Java中的保留关键字.

  2. php 生成不重复的随机字符串

    md5(uniqid(md5(microtime(true)),true))

  3. pgpool如何对数据库节点进行状态检查及相关数据结构描述

    /* * configuration parameters */typedef struct {    char *listen_addresses;            /* hostnames/ ...

  4. ​libz.so.1: cannot open shared object file: No such file or directory

    在虚拟机安装xtrabackup工具时候出现的报错:​​libz.so.1: cannot open shared object file: No such file or directory [ro ...

  5. 七天C#小结

    从基础的理论知识,到最后一天,能够理解并且自己编写出一些经典的事例,自己期初觉得不会这么快,几乎是零基础的自己从什么都不会,到七天后能够独立思考并且编写出100多行的代码,自己还是有些欣慰的,从点到面 ...

  6. python3 pymysql学习笔记

    练手项目需要用到mysql就顺手把mysql也学了,这个模块没什么好说的,比较简单,实际整个过程我都是在学mysql语句,但还是发现了一些问题. fetchall() 获取结果集中的所有行 这个函数难 ...

  7. 执行python manage.py makemigrations时报错TypeError: __init__() missing 1 required positional argument: 'on_delete'

    在执行python manage.py makemigrations时报错: TypeError: __init__() missing 1 required positional argument: ...

  8. Jquery复习总结

    1.选择器: $(".class") $("#id") $("div") $("a p") $(div:first).c ...

  9. Activiti Workflow HelloWorld 示例与测试环境搭建

    作者:Rock 出处:http://www.ecmkit.com/zh-hans/2012/03/21/activiti-workflow-hell Activiti Workflow HelloWo ...

  10. 标题:u-boot 移植步骤详解

    1 U-Boot简介U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目.从FADSROM.8xxROM.PPCBOOT逐步发展演化而来.其源码目录.编译形式与 ...