代码:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;namespace Share
{/// <summary>/// 斑马工具类,把图像转换成斑马打印机的命令/// </summary>public class ZebraUnity{#region 定义私有字段/// <summary>/// 线程锁,防止多线程调用。/// </summary>private static object SyncRoot = new object();/// <summary>/// ZPL压缩字典/// </summary>private static List<KeyValuePair<char, int>> compressDictionary = new List<KeyValuePair<char, int>>();#endregion#region 构造方法static ZebraUnity(){InitCompressCode();}#endregion#region 定义属性/// <summary>/// 图像的二进制数据/// </summary>public static byte[] GraphBuffer { get; set; }/// <summary>/// 图像的宽度/// </summary>private static int GraphWidth { get; set; }/// <summary>/// 图像的高度/// </summary>private static int GraphHeight { get; set; }private static int RowSize{get{return (((GraphWidth) + 31) >> 5) << 2;}}/// <summary>/// 每行的字节数/// </summary>private static int RowRealBytesCount{get{if ((GraphWidth % 8) > 0){return GraphWidth / 8 + 1;}else{return GraphWidth / 8;}}}#endregion#region 位图转斑马指令字符串/// <summary>/// 位图转斑马指令字符串/// </summary>/// <param name="bitmap">位图数据</param>/// <param name="totalBytes">总共的字节数</param>/// <param name="rowBytes">每行的字节数</param>/// <returns>斑马ZPL 2命令</returns>public static string BmpToZpl(byte[] bitmap, out int totalBytes, out int rowBytes){try{GraphBuffer = bitmap;byte[] bmpData = getBitmapData();string textHex = BitConverter.ToString(bmpData).Replace("-", string.Empty);string textBitmap = CompressLZ77(textHex);totalBytes = GraphHeight * RowRealBytesCount;rowBytes = RowRealBytesCount;return textBitmap;}catch (Exception ex){throw ex;}}/// <summary>/// 位图转ZPL指令/// </summary>/// <param name="bitmap">位图</param>/// <param name="totalBytes">返回参数总共字节数</param>/// <param name="rowBytes">返回参数每行的字节数</param>/// <returns>ZPL命令</returns>public static string BmpToZpl(Image bitmap, out int totalBytes, out int rowBytes){using (MemoryStream stream = new MemoryStream()){bitmap.Save(stream, ImageFormat.Bmp);return BmpToZpl(stream.ToArray(), out totalBytes, out rowBytes);}}/// <summary>/// 根据图片生成图片的ASCII 十六进制/// </summary>/// <param name="sourceBmp">原始图片</param>/// <param name="totalBytes">总共字节数</param>/// <param name="rowBytes">每行的字节数</param>/// <returns>ASCII 十六进制</returns>public static string BitmapToHex(Image sourceBmp, out int totalBytes, out int rowBytes){// 转成单色图Bitmap grayBmp = ConvertToGrayscale(sourceBmp as Bitmap);// 锁定位图数据    Rectangle rect = new Rectangle(0, 0, grayBmp.Width, grayBmp.Height);System.Drawing.Imaging.BitmapData bmpData = grayBmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, grayBmp.PixelFormat);// 获取位图数据第一行的起始地址     IntPtr ptr = bmpData.Scan0;// 定义数组以存放位图的字节流数据      // 处理像素宽对应的字节数,如不为8的倍数,则对最后一个字节补0    int width = (int)Math.Ceiling(grayBmp.Width / 8.0);// 获取位图实际的字节宽,这个值因为要考虑4的倍数关系,可能大于width  int stride = Math.Abs(bmpData.Stride);// 计算位图数据实际所占的字节数,并定义数组      int bitmapDataLength = stride * grayBmp.Height;byte[] ImgData = new byte[bitmapDataLength];// 从位图文件复制图像数据到数组,从实际图像数据的第一行开始;因ptr指针而无需再考虑行倒序存储的处理          System.Runtime.InteropServices.Marshal.Copy(ptr, ImgData, 0, bitmapDataLength);// 计算异或操作数,以处理包含图像数据但又有补0操作的那个字节         byte mask = 0xFF;// 计算这个字节补0的个数       //int offset = 8 * width - grayBmp.Width;int offset = 8 - (grayBmp.Width % 8);//offset %= 8;offset = offset % 8;// 按补0个数对0xFF做相应位数的左移位操作           mask <<= (byte)offset;// 图像反色处理        for (int j = 0; j < grayBmp.Height; j++){for (int i = 0; i < stride; i++){if (i < width - 1) //无补0的图像数据{ImgData[j * stride + i] ^= 0xFF;}else if (i == width - 1) //有像素的最后一个字节,可能有补0   {ImgData[j * stride + i] ^= mask;}else  //为满足行字节宽为4的倍数而最后补的字节        {//ImgData[j * stride + i] = 0x00;ImgData[j * stride + i] ^= 0x00;}}}// 将位图数据转换为16进制的ASCII字符          string zplString = BitConverter.ToString(ImgData);zplString = CompressLZ77(zplString.Replace("-", string.Empty));totalBytes = bitmapDataLength;rowBytes = stride;return zplString;}#endregion#region 获取单色位图数据/// <summary>/// 获取单色位图数据/// </summary>/// <param name="pimage"></param>/// <returns></returns>private static Bitmap ConvertToGrayscale(Bitmap pimage){Bitmap source = null;// If original bitmap is not already in 32 BPP, ARGB format, then convertif (pimage.PixelFormat != PixelFormat.Format32bppArgb){source = new Bitmap(pimage.Width, pimage.Height, PixelFormat.Format32bppArgb);source.SetResolution(pimage.HorizontalResolution, pimage.VerticalResolution);using (Graphics g = Graphics.FromImage(source)){g.DrawImageUnscaled(pimage, 0, 0);}}else{source = pimage;}// Lock source bitmap in memoryBitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);// Copy image data to binary arrayint imageSize = sourceData.Stride * sourceData.Height;byte[] sourceBuffer = new byte[imageSize];Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);// Unlock source bitmapsource.UnlockBits(sourceData);// Create destination bitmapBitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);// Lock destination bitmap in memoryBitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);// Create destination bufferimageSize = destinationData.Stride * destinationData.Height;byte[] destinationBuffer = new byte[imageSize];int sourceIndex = 0;int destinationIndex = 0;int pixelTotal = 0;byte destinationValue = 0;int pixelValue = 128;int height = source.Height;int width = source.Width;int threshold = 500;// Iterate linesfor (int y = 0; y < height; y++){sourceIndex = y * sourceData.Stride;destinationIndex = y * destinationData.Stride;destinationValue = 0;pixelValue = 128;// Iterate pixelsfor (int x = 0; x < width; x++){// Compute pixel brightness (i.e. total of Red, Green, and Blue values)pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3];if (pixelTotal > threshold){destinationValue += (byte)pixelValue;}if (pixelValue == 1){destinationBuffer[destinationIndex] = destinationValue;destinationIndex++;destinationValue = 0;pixelValue = 128;}else{pixelValue >>= 1;}sourceIndex += 4;}if (pixelValue != 128){destinationBuffer[destinationIndex] = destinationValue;}}// Copy binary image data to destination bitmapMarshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);// Unlock destination bitmapdestination.UnlockBits(destinationData);// Dispose of source if not originally supplied bitmapif (source != pimage){source.Dispose();}// Returnreturn destination;}/// <summary>/// 获取单色位图数据(1bpp),不含文件头、信息头、调色板三类数据。/// </summary>/// <returns></returns>private static byte[] getBitmapData(){MemoryStream srcStream = new MemoryStream();MemoryStream dstStream = new MemoryStream();Bitmap srcBmp = null;Bitmap dstBmp = null;byte[] srcBuffer = null;byte[] dstBuffer = null;byte[] result = null;try{srcStream = new MemoryStream(GraphBuffer);srcBmp = Bitmap.FromStream(srcStream) as Bitmap;srcBuffer = srcStream.ToArray();GraphWidth = srcBmp.Width;GraphHeight = srcBmp.Height;//dstBmp = srcBmp.Clone(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), PixelFormat.Format1bppIndexed);dstBmp = ConvertToGrayscale(srcBmp);dstBmp.Save(dstStream, ImageFormat.Bmp);dstBuffer = dstStream.ToArray();result = dstBuffer;int bfOffBits = BitConverter.ToInt32(dstBuffer, 10);result = new byte[GraphHeight * RowRealBytesCount];读取时需要反向读取每行字节实现上下翻转的效果,打印机打印顺序需要这样读取。for (int i = 0; i < GraphHeight; i++){int sindex = bfOffBits + (GraphHeight - 1 - i) * RowSize;int dindex = i * RowRealBytesCount;Array.Copy(dstBuffer, sindex, result, dindex, RowRealBytesCount);}for (int i = 0; i < result.Length; i++){result[i] ^= 0xFF;}}catch (Exception ex){throw new Exception(ex.Message, ex);}finally{if (srcStream != null){srcStream.Dispose();srcStream = null;}if (dstStream != null){dstStream.Dispose();dstStream = null;}if (srcBmp != null){srcBmp.Dispose();srcBmp = null;}if (dstBmp != null){dstBmp.Dispose();dstBmp = null;}}return result;}#endregion#region LZ77图像字节流压缩方法private static string CompressLZ77(string text){//将转成16进制的文本进行压缩string result = string.Empty;char[] arrChar = text.ToCharArray();int count = 1;for (int i = 1; i < text.Length; i++){if (arrChar[i - 1] == arrChar[i]){count++;}else{result += convertNumber(count) + arrChar[i - 1];count = 1;}if (i == text.Length - 1){result += convertNumber(count) + arrChar[i];}}return result;}private static string DecompressLZ77(string text){string result = string.Empty;char[] arrChar = text.ToCharArray();int count = 0;for (int i = 0; i < arrChar.Length; i++){if (isHexChar(arrChar[i])){//十六进制值result += new string(arrChar[i], count == 0 ? 1 : count);count = 0;}else{//压缩码int value = GetCompressValue(arrChar[i]);count += value;}}return result;}private static int GetCompressValue(char c){int result = 0;for (int i = 0; i < compressDictionary.Count; i++){if (c == compressDictionary[i].Key){result = compressDictionary[i].Value;}}return result;}private static bool isHexChar(char c){return c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103;}private static string convertNumber(int count){//将连续的数字转换成LZ77压缩代码,如000可用I0表示。string result = string.Empty;if (count > 1){while (count > 0){for (int i = compressDictionary.Count - 1; i >= 0; i--){if (count >= compressDictionary[i].Value){result += compressDictionary[i].Key;count -= compressDictionary[i].Value;break;}}}}return result;}private static void InitCompressCode(){//G H I J K L M N O P Q R S T U V W X Y        对应1,2,3,4……18,19。//g h i j k l m n o p q r s t u v w x y z      对应20,40,60,80……340,360,380,400。            for (int i = 0; i < 19; i++){compressDictionary.Add(new KeyValuePair<char, int> (Convert.ToChar(71 + i), i + 1 ));}for (int i = 0; i < 20; i++){compressDictionary.Add(new KeyValuePair<char, int>(Convert.ToChar(103 + i), (i + 1) * 20));}}#endregion}
}

使用:

string data = ZebraUnity.BitmapToHex(image, out int to, out int row);
string zpl = string.Format("~DGR:Temp0.GRF,{0},{1},{2}", to, row, data);
cmd.Append(zpl);cmd.AppendFormat("^FO0,0^XGR:Temp0.GRF,1,1^FS");

打印一个图片的ZPL指令:

^XA
^LH0,0^LL80^PW580
~DGR:Temp0.GRF,5120,32,uK01E07Ci0F038Q03C0F8hJ07818Q01E07hK07818Q01E06hK07818Q01F06hK07C18Q01F06hK07E18Q01F86hK06E18Q01F86hK06E180FC1HFBEI01B86hK067181CF0E71CI019C603F83FE78gV067183870E318I019C6071C18E3gW0639870386398I018E60E0E1CE3gW0639870387398I018E60C0E1CE6gW063D87038H79J018F61C071CE6gW061F87HF8H7BJ018761C070CF6gW061F8FI03HFJ0187E1IF0DF6gW060F87I03HFJ0183E1CI0HFCgW060F87I03DFJ0183E1CI0HFCgW060787I03DEJ0181E1CI0FBCgW0607870183CEJ0181E1C02073CgW0603838301CEJ0180E0E060738gW060381HE018EJ0180E0F0C0738gV01F01807C018CJ01C0607FC0718hR03E0601FH0218zzzzzzkN03C0F8hY01E06i01E06i01F06i01F06i01F86i01F86i01B86H04H03048hQ019C603F83DE78hQ019C6071C18E3hR018E60E0E1CE2hR018E61C0E1CE6hR018761C061CE6hR018761C0F0CF6hR0187E1IF0DF6hR0183E1CI0HFChR0183E1CI0HFChR0181E1CI0F3ChR0181E1C06073ChR0180E0E060738hR0180E070C0738hR03C0603F80718hR024J06zzzzzzoS0781Fi0380EhK0F03EQ03C0ChK07818Q03C0ChK07808Q03E0ChK07C18Q03E0ChK07C18Q03F0ChK07E18Q0370ChK06E18Q0378C07F0HFCFgW06F1803C0HFDEI0H38C0E3871C6gW067180HF0F38EI0H3HC1C1C31C4gW067981C38738CI031HC181C39HCgW063983838738CI031EC381C39HCgW063C8301C7398I030EC381E39HCgW061C8701CH3D8I030FC3HFE1BECgW061E8701CH3D8I0307C38H01HF8gW060F87HFC3BD8I0307C38H01HF8gW060F87I03HFJ0303C38H01E78gW060787I03EFJ0303C38041E78gW060787I01EFJ0301C1C0C0E7gX0603838081CFJ0301C1C180E7gX0603838181CFJ03H0C0HFH0E7gX060181C301C6J0FC0C03EH042gX0F8180FEH0C6zhQ0^FO30,0^XGR:Temp0.GRF,1,1^FS
^XZ

~DG指令

使用TSC TE344打印机,正常

转自:https://www.cnblogs.com/chuci/p/4462378.html

【C#】打印机ZPL指令打印图片,将图片转成十六进制指令相关推荐

  1. iOS 连接打印机 ESC/POS 指令打印 打印图片二维码

    最近公司给商户做的App 允许App把卖出的商品信息通过打印机 打印标签 所以了解了一下iOS 和 打印机 之间的交互 (Ps:用的不是UIPrinter 那个扫面打印机 发送信息打印的那个框架) 主 ...

  2. zpl java_java关于zpl打印黑白贴纸图片

    参考: (1)打印前的图片处理:https://www.doc88.com/p-9713794083891.html (3)zpl命令大全:https://blog.csdn.net/tianqin2 ...

  3. uniapp微信小程序连接蓝牙打印机 打印文字、图片

    首先感谢几位的文章分享 https://blog.csdn.net/guairena/article/details/127941515 https://blog.csdn.net/qq_379700 ...

  4. C#调用系统默认打印机打印文字和图片

    本方法适用于有打印驱动的打印机打印.直接用电脑默认打印机进行打印文字和图片. 首先安装打印机驱动,然后在设备和打印机中将要用的打印机设为默认打印机,然后调用该方法即可 Pulic Void Print ...

  5. ZPL指令打印 斑马打印机指令打印

    首先ZPL(Zebra Programming language)是斑马家搞的ZPL语言,用于和打印机通讯打印开发的指令.然后理解了这个只是个指令的东西后,我们接着就想想怎么弄,本着怎么简单怎么来的原 ...

  6. linux下打印图片不显示出来的,为什么打印机打印不了图片_解决打印机打印不了图片的方法-系统城...

    在办公室上班的都会接触到打印机,大家在使用打印机会碰到打印不出图片的情况,为什么会这样呢?出现这种情况排除打印机驱动外,一般是由于打印机的设置不当造成的.针对此疑问,小编教你解决打印机打印不了图片的方 ...

  7. Unity调用打印机打印文本或者图片

    Unity调用打印机打印文本或者图片 通过windows命令行使用记事本打印文本 private void PrintTxt(){//picPath=Application.streamingAsse ...

  8. java关于zpl打印黑白贴纸图片

    参考: (1)打印前的图片处理:https://www.doc88.com/p-9713794083891.html (2)常用的zpl命令:https://www.cnblogs.com/LiGen ...

  9. C# 博思得 POSTEK 打印机 打码机 SDK 二次开发 指令打印

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.调用SDK实现打印 前言 提示: 公司要实现 BarTender的类似功能.POSTEK 提供了开发C++ 的 S ...

  10. Win7图片查看器打印不了图片怎么办

    当我们想浏览电脑中的图片文件时,可以选择系统自带的图片查看器或者第三方看图工具打开,但是有些win7用户发现自己想通过windows图片查看器打印图片却没有反应,Win7图片查看器打印不了图片怎么办? ...

最新文章

  1. 回顾与展望:大热的AutoML究竟是什么? | 技术头条
  2. APMServ伪静态设置
  3. js事件(Event)知识整理
  4. Visual Studio各版本工程文件之间的转换 [转载]
  5. python3.6手册中文版-python3.6文档中文版
  6. linux下载哪个python版本-Linux下切换Python版本的几种方法
  7. 希尔排序Linux下C实现
  8. [译]管理IIS日志的存储
  9. Material delta download的deletion处理原理
  10. ELK篇---------elasticsearch集群安装配置
  11. 20170808上课笔记
  12. Java NIO学习篇之缓冲区ByteBuffer详解
  13. SQL Server 2012 开发新特性:文件表
  14. 为 Analysis Services 数据库使用扩展字段属性(SQL Server 2005 联机丛书(2008 年 11 月))...
  15. java.sql 拒绝连接_java.sql.SQLException: ORA-01017: 用户名/口令无效; 登录被拒绝
  16. python 中的意义_python3中 -的意义
  17. MySQL之流程控制
  18. SQLServer------基本操作
  19. [Java][Android][Process] Process 创建+控制+分析 经验浅谈
  20. 热门论坛排行top100--2010年07月11日[转]

热门文章

  1. python超链接程序,python超链接
  2. 数据分析之 AB测试(AB Test)
  3. 中国古代文化常识【1】
  4. cissp证书(cissp证书)
  5. 网页设计专家票选的16款常用英文字体
  6. LVGL开发 | lv_lib_100ask之lvgl数字对拼图小游戏(lv_100ask_memory_game)-接口简单、使用便捷
  7. 开关插头插座寿命试验机标准
  8. 使用 cajViewer 将 caj文件 转换 pdf文件
  9. 手动揪出电脑中毒导致的空间自动发广告的元凶
  10. DataGear 制作自适应任意屏幕尺寸的数据可视化看板