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

这是DEMO的窗体:

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

class LptControl  {  private string LptStr = "lpt1";  public LptControl(string l_LPT_Str)  {  LptStr = l_LPT_Str;  }  [StructLayout(LayoutKind.Sequential)]  private struct OVERLAPPED  {  int Internal;  int InternalHigh;  int Offset;  int OffSetHigh;  int hEvent;  }  //调用DLL.  [DllImport("kernel32.dll")]  private static extern int CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, int lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);  [DllImport("kernel32.dll")]  private static extern bool WriteFile(int hFile, byte[] lpBuffer, int nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED lpOverlapped);  [DllImport("kernel32.dll")]  private static extern bool CloseHandle(int hObject);  private int iHandle;  /// <summary>  /// 打开端口  /// </summary>  /// <returns></returns>  public bool Open()  {  iHandle = CreateFile(LptStr, 0x40000000, 0, 0, 3, 0, 0);  // iHandle = CreateFile(LptStr, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);  if (iHandle != -1)  {  return true;  }  else  {  return false;  }  }  /// <summary>  /// 打印字符串,通过调用该方法可以打印需要的字符串  /// </summary>  /// <param name="Mystring"></param>  /// <returns></returns>  public bool Write(String Mystring)  {  //如果端口为打开,则提示,打开,则打印  if (iHandle != -1)  {  OVERLAPPED x = new OVERLAPPED();  int i = 0;  //byte[] mybyte = System.Text.Encoding.Default.GetBytes(Mystring);  byte[] mybyte = Encoding.GetEncoding("GB2312").GetBytes(Mystring);  bool b = WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x);  return b;  }  else  {  throw new Exception("不能连接到打印机!");  }  }  /// <summary>  /// 打印命令,通过参数,可以打印小票打印机的一些命令,比如换行,行间距,打印位图等。  /// </summary>  /// <param name="mybyte"></param>  /// <returns></returns>  public bool Write(byte[] mybyte)  {  //如果端口为打开,则提示,打开,则打印  if (iHandle != -1)  {  OVERLAPPED x = new OVERLAPPED();  int i = 0;  return WriteFile(iHandle, mybyte, mybyte.Length, ref i, ref x);  }  else  {  throw new Exception("不能连接到打印机!");  }  }  /// <summary>  /// 关闭端口  /// </summary>  /// <returns></returns>  public bool Close()  {  return CloseHandle(iHandle);  }  }  

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

/// <summary>  /// 打印图片方法  /// </summary>  public void PrintOne()  {  //获取图片  Bitmap bmp = new Bitmap(pictureBox1.Image);  //设置字符行间距为n点行  //byte[] data = new byte[] { 0x1B, 0x33, 0x00 };  string send = "" + (char)(27) + (char)(51) + (char)(0);  byte[] data = new byte[send.Length];  for (int i = 0; i < send.Length; i++)  {  data[i] = (byte)send[i];  }  lc.Write(data);  data[0] = (byte)'\x00';  data[1] = (byte)'\x00';  data[2] = (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[2] = (byte)'\x21';  //nL, nH  escBmp[3] = (byte)(bmp.Width % 256);  escBmp[4] = (byte)(bmp.Width / 256);  //循环图片像素打印图片  //循环高  for (int i = 0; i < (bmp.Height / 24 + 1); i++)  {  //设置模式为位图模式
               lc.Write(escBmp);  //循环宽  for (int j = 0; j < bmp.Width; j++)  {  for (int k = 0; k < 24; k++)  {  if (((i * 24) + k) < bmp.Height)  // if within the BMP size
                       {  pixelColor = bmp.GetPixel(j, (i * 24) + k);  if (pixelColor.R == 0)  {  data[k / 8] += (byte)(128 >> (k % 8));  }  }  }  //一次写入一个data,24个像素
                   lc.Write(data);  data[0] = (byte)'\x00';  data[1] = (byte)'\x00';  data[2] = (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 = 0; i < ((bmp.Height + 7) / 8); i++)  {  _serialPort.Write(escBmp, 0, escBmp.Length);  for (int j = 0; j < bmp.Width; j++)  {  for (int k = 0; k < 8; k++)  {  if (((i * 8) + k) < bmp.Height)  // if within the BMP size
                        {  pixelColor = bmp.GetPixel(j, (i * 8) + k);  if (pixelColor.R == 0)  {  data[0] += (byte)(128 >> k);  }  }  }  _serialPort.Write(data, 0, 1);  data[0] = (byte)'\x00'; // Clear to Zero.
                }  

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

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

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

转载于:https://www.cnblogs.com/randyzhuwei/p/5216413.html

C# 热敏打印机 小票打印机 打印图片相关推荐

  1. delphi android 打印机,用delphi控制小票打印机打印图片

    用delphi控制小票打印机打印图片 unit PosPrintBmp; {************************************************************** ...

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

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

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

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

  4. 常见小票打印机打印故障及解决方法汇总视频教程

    通过对"常见小票打印机故障及解决方法汇总视频教程"课程学习,达到以下目的:1.可以独立自主安装打印机驱动以及安装打印机硬件设备 2.可以独立自主排除常见打印机故障 学习教程 常见小 ...

  5. Android 实现系统打印机打印图片,文本,以及二维码生成与解析

    打码机:扫码,生成打印自定义标签   一.Android 打印机要支持,网络.WiFi :手机与打印机在同一网络下才行,本文用WiFi连接 打开系统打印服务: 设置--更多设置--打印--选择默认打印 ...

  6. python打印机打印图片_python连接打印机实现打印文档、图片、pdf文件等功能

    引言 python连接打印机进行打印,可能根据需求的不同,使用不同的函数模块. 如果你只是简单的想打印文档,比如office文档,你可以使用ShellExecute方法,对于微软office的文档.p ...

  7. 打印机打印图片文字有重影

    打印机打印图片出来的文字有重影 解决办法: 打印机属性里面"纸张/质量"选项里"颜色"选项选择黑白,不过打印有彩色有黑字的照片还是个问题

  8. 常见小票打印机打印故障及解决方法汇总视频教程-王西猛-专题视频课程

    常见小票打印机打印故障及解决方法汇总视频教程-548人已学习 课程介绍         通过对"常见小票打印机故障及解决方法汇总视频教程"课程学习,达到以下目的:1.可以独立自主安 ...

  9. 微信小程序连接蓝牙打印机打印图片示例

    微信小程序连接蓝牙打印机示例 完整的代码示例请点击看github 小程序连接蓝牙打印机打印文本与二维码等示例在 github 上都能找到一些,唯独打印图片这个案例几乎没有.希望能帮助到有打印图片需求的 ...

最新文章

  1. 简单了解Vue的自定义组件与生命周期
  2. .Net Core使用Ocelot网关(二) -鉴权认证
  3. 查看windows所有exe的启动参数。
  4. 【图像压缩】基于matlab JEPG图像压缩【含Matlab源码 1167期】
  5. 稳压管(齐纳二极管)封装型号大全
  6. 网维无盘服务器错误代码,网维大师无盘环境INTER傲腾方案常见问题解答?
  7. dqw3721:自己动手写打印机监控程序
  8. cosx的麦克劳林级数是多少_余弦函数的泰勒级数
  9. Win10家庭版安装软件时提示“为了对电脑进行保护,已经阻止此应用”
  10. 正则表达式 /^[0-9]+$/
  11. SNS背后的科学(1)从六度分隔到无尺度网络
  12. 智能穿戴:致我们触手可及的未来?
  13. 在OTFS学习中的一些总结
  14. PTA-L1-007 念数字 (C语言)
  15. [Splay的应用]
  16. [新人向]MySQL和Navicat下载、安装及使用详细教程
  17. 转:数据可视化之美:经典案例与实践解析
  18. 2022年,反思你的 HRIS 是不是为绩效管理而构建
  19. 计算机班教室布置,教室布置班级简介
  20. html语言中行距如何设定,html怎么设置行间距离

热门文章

  1. 常见的WEB2.0开源程序
  2. 复杂度 O、Θ、Ω、o、ω,别再傻傻分不清了!
  3. 【Opencv】基于dlib的人脸关键点检测和闭眼检测
  4. 批量获取力扣做题量工具
  5. 超级卵杰的自动脚本(3)签到 抢分 入团 压分功能。
  6. 字节后端面经(计算机网络部分)
  7. 将base64编码转换成图片
  8. 使用ajaxfileupload.js实现上传文件功能
  9. C语言将原始信息逆序,C语言及逆向2020知到章节期末答案
  10. node-red templete节点设置地图