You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求ZPL的Binary B64与压缩Z64编码的C#实现示例

ZPL Z64编码C#实现及~DY命令参数说明

一、~DY命令参数t和w的明确说明

在ZPL命令~DYd:f,b,x,t,w,data中:

  • t(文件总字节数):必须填写压缩前的原始位图数据总字节数
  • w(每行总字节数):必须填写压缩前的原始位图每行字节数(即(位图宽度 +7)/8的计算值)

打印机依赖这两个原始参数确定图像的尺寸和像素排列规则,压缩仅针对data部分,不影响图像基础属性的定义。

二、Z64编码完整实现代码

以下是可直接运行的C#代码,实现从位图(文件或内存对象)生成Z64编码的GRF数据,并输出正确的ZPL命令:

1. CRC16-CCITT校验类(Z64要求的校验算法)

public class Crc16Ccitt
{
    private const ushort Polynomial = 0x1021;
    private readonly ushort _initialValue;
    private ushort _crc;

    public enum InitialCrcValue { Zeros, NonZero }

    public Crc16Ccitt(InitialCrcValue initialValue)
    {
        _initialValue = initialValue == InitialCrcValue.Zeros ? (ushort)0 : (ushort)0xFFFF;
        Reset();
    }

    public void Reset()
    {
        _crc = _initialValue;
    }

    public ushort ComputeChecksum(byte[] bytes)
    {
        foreach (byte b in bytes)
        {
            for (int i = 0; i < 8; i++)
            {
                bool bit = ((b >> (7 - i) & 1) == 1);
                bool c15 = ((_crc >> 15 & 1) == 1);
                _crc <<= 1;
                if (c15 ^ bit)
                    _crc ^= Polynomial;
            }
        }
        return _crc;
    }
}

2. 位图转Z64编码核心方法

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Globalization;

[SupportedOSPlatform("windows")]
private static string BitmapToZ64Grf(Bitmap bitmap, out int originalTotalBytes, out int originalRowWidth, out ushort crcValue)
{
    BitmapData bitmapData = null;
    try
    {
        // 锁定1bpp索引格式的位图数据(ZPL仅支持单色位图)
        bitmapData = bitmap.LockBits(
            new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            ImageLockMode.ReadOnly,
            PixelFormat.Format1bppIndexed);

        // 计算原始数据的每行字节数和总字节数
        originalRowWidth = (bitmap.Width + 7) / 8;
        int stride = Math.Abs(bitmapData.Stride);
        originalTotalBytes = stride * bitmap.Height;

        // 读取原始像素数据并反色(ZPL中0代表黑色,1代表白色,与.NET位图逻辑相反)
        byte[] originalData = new byte[originalTotalBytes];
        IntPtr scanPtr = bitmapData.Scan0;
        for (int y = 0; y < bitmap.Height; y++)
        {
            byte[] rowData = new byte[stride];
            Marshal.Copy(scanPtr, rowData, 0, stride);
            // 仅保留有效行数据(stride因内存对齐可能大于originalRowWidth)
            for (int x = 0; x < originalRowWidth; x++)
            {
                originalData[y * originalRowWidth + x] = (byte)~rowData[x];
            }
            scanPtr = (IntPtr)(scanPtr.ToInt64() + bitmapData.Stride);
        }

        // 使用Deflate压缩原始数据(Z64的压缩标准)
        byte[] compressedData;
        using (MemoryStream msCompress = new MemoryStream())
        {
            using (DeflateStream deflateStream = new DeflateStream(msCompress, CompressionMode.Compress, leaveOpen: true))
            {
                deflateStream.Write(originalData, 0, originalData.Length);
            }
            compressedData = msCompress.ToArray();
        }

        // 转换为Base64编码,得到Z64格式数据
        string z64Data = Convert.ToBase64String(compressedData);

        // 计算CRC校验值(针对压缩后的字节数组)
        Crc16Ccitt crc = new Crc16Ccitt(Crc16Ccitt.InitialCrcValue.Zeros);
        crcValue = crc.ComputeChecksum(compressedData);

        return z64Data;
    }
    finally
    {
        // 释放资源
        if (bitmapData != null)
        {
            bitmap.UnlockBits(bitmapData);
        }
        bitmap.Dispose();
    }
}

三、生成ZPL输出示例

调用上述方法生成完整的ZPL打印命令:

// 加载位图(示例:从文件加载)
using Bitmap bmp = new Bitmap("test.bmp");
string z64Data = BitmapToZ64Grf(bmp, out int originalTotalBytes, out int originalRowWidth, out ushort crc);

// 构造~DY命令:D:表示存储在打印机DRAM,TEST.GRF是文件名,Z代表Z64编码
string zplCommand = $"^XA~DYD:TEST.GRF,Z,{originalTotalBytes},{originalRowWidth},{crc:X4},{z64Data}^XZ";

// 输出或发送ZPL到打印机
Console.WriteLine(zplCommand);

四、对用户提供代码的修正说明

用户原代码存在几个关键问题:

  1. 未将bitmapData中的像素数据复制到处理数组,导致处理空数据
  2. 压缩后未关闭DeflateStream,无法获取完整压缩数据
  3. CRC校验错误计算Base64字符串的ASCII字节,正确校验对象是压缩后的原始字节数组
  4. 未处理位图反色逻辑,会导致打印图像颜色反转

内容的提问来源于stack exchange,提问作者Chris Ward

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 07:25:57