对接斑马打印机 usb形式

Zebra.Sdk.Printer请使用低版本:2.14.1989

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using Zebra.Sdk.Comm;
using Zebra.Sdk.Printer;
using Zebra.Sdk.Printer.Discovery;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;namespace AIOT.Web.Server.Cloud.Utils
{/// <summary>/// 斑马打印机/// </summary>public static class ZebraPrinterHelper{/// <summary>/// usb打印方式/// </summary>/// <param name="images"></param>/// <param name="iconHeight"></param>/// <param name="iconWidth"></param>public static void PrintByUsb(List<Image> images, int iconHeight = 480, int iconWidth = 640){try{var usbPrints = UsbDiscoverer.GetZebraUsbPrinters(new ZebraPrinterFilter());Connection connection = usbPrints[0].GetConnection();try{if (connection == null){return;}connection.Open();ZebraPrinter printer = ZebraPrinterFactory.GetInstance(connection);string tmpFile = Directory.GetCurrentDirectory() + "\\wwwroot\\pic\\printTemp.txt";//文件存储地方foreach (var image in images){using (StreamWriter sw = new StreamWriter(tmpFile, false)){sw.Write(ImageToZPL(image, iconHeight, iconWidth));}printer.SendFileContents(tmpFile);}//ZebraImageI image = ZebraImageFactory.GetImage("D:\\WorkSpace\\AIOT\\AIOT.Web.Server.HostReport\\AIOT.Web.Server.Host\\wwwroot\\pic\\qrcode_model.png");//printer.PrintImage(image, x, y, 640, 480, false);}catch (ConnectionException e){Console.WriteLine(e.ToString());}catch (ZebraPrinterLanguageUnknownException e){Console.WriteLine(e.ToString());}catch (IOException e){Console.WriteLine(e.ToString());}finally{connection.Close();}}catch{}}/// <summary>/// 本地网络共享批量打印/// </summary>/// <param name="netSharePrinterName">@"\\DESKTOP-B0B1DKB\zd888";//计算机名+打印机共享名</param>/// <param name="images"></param>/// <param name="iconHeight"></param>/// <param name="iconWidth"></param>public static void PrinteByLocalNetShare(string netSharePrinterName, List<Image> images, int iconHeight = 480, int iconWidth = 640){string tmpFile = Directory.GetCurrentDirectory() + "\\wwwroot\\pic\\printTemp.txt";//文件存储地方foreach (var image in images){using (StreamWriter sw = new StreamWriter(tmpFile, false)){sw.Write(ImageToZPL(image, iconHeight, iconWidth));}File.Copy(tmpFile, netSharePrinterName, true);}}/// <summary>/// 图像转化为ZPL/// </summary>/// <param name="sourceImage"></param>/// <param name="iconHeight"></param>/// <param name="iconWidth"></param>/// <returns></returns>private static string ImageToZPL(Image sourceImage,int iconHeight,int iconWidth) {StringBuilder str = new StringBuilder();str.Append("^XA \r\n"); //打印命令开始str.Append($"^LL {iconHeight}^FS \r\n");//定义标签长度 105SL 300 DPI (1mm 12pt) 50mm*12   203 DPI (1mm 8pt)str.Append($"^PW {iconWidth} \r\n");  //定义标签寬度 100mm*12 int totalbytes = 0;int rowbytes = 0;Image fixImage = ImgHelper.ResizeImage(sourceImage, new Size(iconWidth, iconHeight));string hex = ZebraUnityHelper.BitmapToHex(fixImage, out totalbytes, out rowbytes);//将图片转成ASCii码string zpl = string.Format("~DGR:Temp0.GRF,{0},{1},{2}", totalbytes, rowbytes, hex);str.Append(zpl);//结束打印str.AppendFormat("^FO0,0^XGR:Temp0.GRF,1,1^FS");str.Append("^XZ");//结束打印return str.ToString();}}/// <summary>/// 斑马工具类,把图像转换成斑马打印机的命令/// </summary>public class ZebraUnityHelper{#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 ZebraUnityHelper(){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);BitmapData bmpData = grayBmp.LockBits(rect, 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指针而无需再考虑行倒序存储的处理          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}}

对接斑马打印机 usb模式+打印机共享模式相关推荐

  1. AQS之独占模式和共享模式

    AQS之独占模式和共享模式 由于ReentrantLock是一个独占锁,独占锁的知识可以参考AQS之理论知识(一)和AQS之公平锁和非公平锁(二) 两篇文章,本文重点讲解共享模式.并且本文共享模式的讲 ...

  2. 【网摘】Oracle Dedicated server 和 Shared server(专用模式 和 共享模式) 说明

    一.  官网说明 在DBCA 建库的时候,有提示让我们选择连接类型,这里有两种类型:专用服务器模式和共享服务器模式.默认使用专用模式.如下图: Oracle 官方文档对这两种文档的说明如下: Abou ...

  3. 判断release模式_AbstractQueuedSynchronizer共享模式与基于Condition的等待/通知

    共享模式acquire实现流程 上文我们讲解了AbstractQueuedSynchronizer独占模式的acquire实现流程,本文趁热打铁继续看一下AbstractQueuedSynchroni ...

  4. ORACLE专有模式与共享模式

    专有模式:当一个用户请求连接到ORACLE的时候,ORACLE会专门的为这个user process 分配一个server process. 共享模式:一个server process可以服务多个us ...

  5. 计算机通过usb连接打印机,USB连接打印机:见招拆招(上)

    ●USB连接打印机:见招拆招(上) Surface Pro只有一个全尺寸的USB接口,能做的事情有限.在实际的办公应用当中,如果将其是做一台笔记本电脑,那么USB接口的数量极其拮据.我们想到的第一个办 ...

  6. 【Android 高性能音频】AAudio 音频流 音频设备 相关配置 ( 音频设备ID | 音频流方向 | 音频设备共享模式 )

    文章目录 I . AAudio 音频流创建流程 II . AAudio 音频流构建器 设置音频设备 ID AAudioStreamBuilder_setDeviceId III . AAudio 音频 ...

  7. 带网络接口的打印机和USB接口打印机的共享区别

    共享打印机在办公中使用最为常见,它允许多人共用一台打印机,以节省成本. 通常打印机有两种连接电脑的方式,一种是的USB接口,另一种是网线接口的. USB接口打印机共享时,需要一台电脑主机,打印机与电脑 ...

  8. 如何将USB接口打印机转换成RJ45网口并安装到打印服务器上共享使用?

    如何将USB接口打印机转换成RJ45网口并安装到打印服务器上共享使用? ©Lander Zhang 专注外企按需IT基础架构运维服务,IT Helpdesk 实战培训践行者 https://blog. ...

  9. centos usb转网口_如何将USB接口打印机转换成RJ45网口并安装到打印服务器上共享使用?...

    如何将USB接口打印机转换成RJ45网口并安装到打印服务器上共享使用? ©Lander Zhang 专注外企按需IT基础架构运维服务,IT Helpdesk 实战培训践行者 https://blog. ...

最新文章

  1. 二分算法,选择,冒泡排序算法
  2. oracle最新scn补丁,更新:Oracle全面修正了关于DB Link和SCN补丁的公告
  3. 二维vector的声明和初始化
  4. shell awk sed tr grep 语法汇总
  5. oracle set feedback off,Oracle数据库之Oracle导出数据中的prompt,set feedback 等是什么意思...
  6. js日期格式判断(2018/01/30) -方法 小时分秒格式判断((HH:MM)
  7. Error starting userland proxy: listen tcp 0.0.0.0:5601: bind: address already in use
  8. 【斐波那契数列】算法优化笔记
  9. jq输出文本_如何用 Linux 命令行工具解析和格式化输出 JSON | Linux 中国
  10. 朱福喜 java_与朱福喜的教科同步JAVA实验指导书
  11. 怎么选PMP培训机构?
  12. Markdown中设置图片尺寸及添加图注
  13. 任务分解法[WBS]
  14. android 解决ScrollView中的子布局不能够填充整个ScrollView
  15. Matlab的fprintf函数使用百分号问题
  16. 多巴胺PEG多巴胺,Dopamine-PEG-Dopamine
  17. linux 心跳灯_Linux下信号灯的使用
  18. octree与kd-tree对比
  19. 书论95 蒋骥《续书法论》
  20. 程序员的13个外包接私活网站,你有技术就有钱!

热门文章

  1. 英语背单词有用吗_英语背单词真的有用吗?
  2. python怎么实现模糊找色_Python下尝试实现图片的高斯模糊化
  3. C++程序闪退原因定位
  4. SwiftUI 问答之更改 TabView 选项卡时如何运行函数
  5. 看一遍都懂的数组遍历~确定不试试?
  6. #一日一图#一周汇总
  7. 惊心动魄的开源项目“政变”,堪比宫斗...
  8. selenium 模拟键盘事件 复制粘贴、右键、回车等
  9. 电力设备事故演练仿真培训_电力事故VR培训_广州华锐互动
  10. 照片像素化项目(on Github)