对接斑马打印机 usb模式+打印机共享模式

4 篇文章 0 订阅
这段代码展示了如何使用Zebra SDK通过USB连接进行打印,主要涉及ZPL语言的使用。首先,它发现并连接USB打印机,然后将图像转换为ZPL指令,写入临时文件并发送到打印机。此外,还提供了网络共享打印的实现。代码中包含了图像的二进制数据处理、位图到ZPL指令的转换以及LZ77压缩方法。
摘要由CSDN通过智能技术生成

对接斑马打印机 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 convert
            if (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 memory
            BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            // Copy image data to binary array
            int imageSize = sourceData.Stride * sourceData.Height;
            byte[] sourceBuffer = new byte[imageSize];
            Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);

            // Unlock source bitmap
            source.UnlockBits(sourceData);

            // Create destination bitmap
            Bitmap destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);

            // Lock destination bitmap in memory
            BitmapData destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);

            // Create destination buffer
            imageSize = 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 lines
            for (int y = 0; y < height; y++)
            {
                sourceIndex = y * sourceData.Stride;
                destinationIndex = y * destinationData.Stride;
                destinationValue = 0;
                pixelValue = 128;

                // Iterate pixels
                for (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 bitmap
            Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);

            // Unlock destination bitmap
            destination.UnlockBits(destinationData);

            // Dispose of source if not originally supplied bitmap
            if (source != pimage)
            {
                source.Dispose();
            }

            // Return
            return 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
    }

}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
斑马标签打印机是一种常用于商业场景中打印标签的设备。Java作为一种广泛应用于软件开发的编程语言,能够与斑马标签打印机进行对接,实现标签的自动打印。 在Java中,对接斑马标签打印机的案例需要通过使用打印机的SDK(Software Development Kit)或者API(Application Programming Interface)来实现。 首先,需要将斑马标签打印机的驱动程序安装在计算机上,确保能够正常识别打印机设备。然后,在Java项目中引入斑马标签打印机的SDK或API,通常是将其作为一个库文件导入到项目中。 接下来,通过Java代码实现对打印机的控制。需要使用相关的类和方法来连接打印机,并设置打印参数,例如标签尺寸、打印内容等。可以创建一个打印任务,将需要打印的标签内容传递给打印机,然后调用打印方法进行打印操作。 在实际的应用场景中,可以根据项目需求自定义标签的样式和内容。例如,可以使用Java的字符串拼接或者模板引擎技术生成标签的文本内容,然后将生成的内容传递给打印机进行打印。 需要注意的是,对接斑马标签打印机时,需要对打印机进行一些配置和设置,例如选择打印机型号、连接打印机的通信方式等。此外,还需要处理可能出现的异常情况,例如打印机故障、连接错误等,以保证整个打印流程的稳定和可靠。 总之,通过使用Java对接斑马标签打印机,可以实现标签的自动打印,提高工作效率。这需要使用斑马标签打印机的SDK或API,并编写相应的Java代码来实现打印控制和数据传输等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值