2012-01-11 14 views
10

얼룩말에 이미지를 인쇄하는 방법을 찾고 많은 문제가 있습니다. 따라 문서 PNG 이미지를 Zebra 네트워크 프린터에 인쇄

:

B64로 알려진 제 1 인코딩은 상기 MIME Base64로 방식을 사용하여 데이터를 인코딩한다. Base64는 전자 메일 첨부 파일을 인코딩하는 데 사용됩니다.
Base64는 바이트로 6 비트를 인코딩합니다.이 경우 확장되지 않은 데이터에 대해 이 확장됩니다.
Z64로 알려진 두 번째 인코딩 인 은 LZ77 알고리즘을 사용하여 데이터를 압축하여 크기를 줄입니다. (이 알고리즘은 PKZIP에서 사용되며 PNG 그래픽 형식과 상호 연관됩니다.)
압축 된 데이터는 위에서 설명한대로 MIME Base64 체계를 사용하여 인코딩됩니다.
CRC는 Base64로 인코딩 된 데이터에 대해 으로 계산됩니다.

그러나 많은 정보가 없습니다. 그것의 소리, 모두 허용됩니다 B64 또는 Z64 중 하나에서

var initialArray = GetItemFromPath("C:\\RED.png"); 
string converted = Convert.ToBase64String(b); 

PrintThis(string.Format(@"~DYRED.PNG,P,P,{1},0,:B64: 
{0} 
^XA 
^F0200,200^XGRED.PNG,1,1^FS 
^XZ", converted .ToString(), initialArray.Length)); 

:

는 기본적으로 나는 다음과 같은 뭔가를 인쇄 할

private byte[] GetItemFromPath(string filepath) 
{ 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     using (Image img = Image.FromFile(filepath)) 
     { 
      img.Save(ms, ImageFormat.Png); 
      return ms.ToArray(); 
     } 
    } 
} 

로 인코딩을 시도하고 있었다.

나는 CRC를 생성하고 '크기'를 계산하는 몇 가지 방법을 시도했다. 그러나 아무 것도 작동하지 않으며 그래픽이 프린터로 다운로드되는 것이 항상 중단됩니다.

누구나 이와 같은 작업을 수행 할 수 있습니까? 또는 내가 어디로 잘못 가고 있는지 아는가?

+1

나는 표준 Windows 인쇄를 사용하여 가장 성공했습니다. 즉 표준 프린터에서와 같이 이미지를 인쇄합니다. 프린터 설정/재고가 올바르게 설정되면 올바르게 인쇄됩니다. –

+1

이것은 내가 조사한 경로이지만, 모든 PC에 드라이버를 설치할 수 있다고는 생각지 않습니다. (모두 Citrix 팜에 있습니다.) 필요할 수있는 각 컴퓨터에 프린터를 로컬로 연결할 수 없습니다 그것. –

+1

그 경우 나는 그것이 과거에 해낸 유일한 방법이므로 확실하지 않습니다. 내가 생각할 수있는 것은 이미지 파일을 찾는 서버에 프로그램을 만든 다음 클라이언트 PC가 해당 폴더에 쓰도록하거나 적절한 클라이언트/서버를 작성하는 것입니다. –

답변

1

ZPL 설명서를보고 나면 CRC (Cyclic Redundancy Check) (CRC)을 계산해야합니다. 여기에 CRC (source)를 계산 약간의 C 코드는 다음과 같습니다

// Update the CRC for transmitted and received data using 
// the CCITT 16bit algorithm (X^16 + X^12 + X^5 + 1). 

unsigned char ser_data; 
static unsigned int crc; 

crc = (unsigned char)(crc >> 8) | (crc << 8); 
crc ^= ser_data; 
crc ^= (unsigned char)(crc & 0xff) >> 4; 
crc ^= (crc << 8) << 4; 
crc ^= ((crc & 0xff) << 4) << 1; 

그것뿐만 아니라 다른 코드 예제가 들어 있으므로 또한, CRC에 위키 백과의 페이지를 참조 할 수 있습니다. 당신이 아래로 보내는 다른

https://en.wikipedia.org/wiki/Cyclic_redundancy_check

모든 것이 좋아 보인다. Zebra SDK 중 하나를 사용해 보겠습니다. 나는 안드로이드가 프린터에 이미지를 보내고 그것을 저장한다는 것을 안다.

+4

그리고 이것만으로도 링크가 죽었다는 이유가있다. - 링크가 죽었다. ( –

12

이 답변에 대한 저의 모든 신용은 LabView Forum 명의 사용자 Raydur입니다. LabView에서 열어 이미지를 전송할 수있는 LabView 솔루션을 게시합니다. 저는 개인적으로 프린터로 실행하지 않았고 올바른 이미지 코드를 알아 내기 위해 사용했습니다. 따라서 코드에서 복제 할 수있었습니다. 내가 누락 된 큰 이유는 내 16 진수 코드를 채우는 것이 었습니다. 예 : 1A는 괜찮지 만, A가있는 경우 0A를 보내기 위해 0을 앞에 붙여야합니다. 전송중인 ZPL의 파일 크기는 데이터의 최종 문자열 표현이 아니라 바이트 배열의 원래 크기이기도합니다.

많은 단순한 작업처럼 보이기 때문에 많은, 많은, 많은 포럼과 Stackoverflow 포스트를 알아 내려고했습니다. 나는 다른 솔루션에 게시 된 모든 단일 솔루션을 사용해 보았지만 내 프린터 (Mobile QLN320)의 설명서가 내장되어 있기 때문에 실제로 .PNG 만 인쇄하려고했습니다. Base64 또는 16 진수로 보내고 둘 다 아무 소용이 없습니다. Base64를하고 싶은 사람은 나이가 많은 매뉴얼에서 보내는 각 패킷에 대한 CRC 코드를 수동으로 계산해야하므로 더 쉬운 16 진법을 선택했습니다. 그래서 여기에 내가 일해야 할 코드가 있습니다!

 string ipAddress = "192.168.1.30"; 
     int port = 6101; 

     string zplImageData = string.Empty; 
     //Make sure no transparency exists. I had some trouble with this. This PNG has a white background 
     string filePath = @"C:\Users\Path\To\Logo.png"; 
     byte[] binaryData = System.IO.File.ReadAllBytes(filePath); 
     foreach (Byte b in binaryData) 
     { 
      string hexRep = String.Format("{0:X}", b); 
      if (hexRep.Length == 1) 
       hexRep = "0" + hexRep; 
      zplImageData += hexRep; 
      } 
      string zplToSend = "^XA" + "^MNN" + "^LL500" + "~DYE:LOGO,P,P," + binaryData.Length + ",," + zplImageData+"^XZ"; 
      string printImage = "^XA^FO115,50^IME:LOGO.PNG^FS^XZ"; 

     try 
     { 
      // Open connection 
      System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient(); 
      client.Connect(ipAddress, port); 

      // Write ZPL String to connection 
      System.IO.StreamWriter writer = new System.IO.StreamWriter(client.GetStream(),Encoding.UTF8); 
      writer.Write(zplToSend); 
      writer.Flush(); 
      writer.Write(printImage); 
      writer.Flush(); 
      // Close Connection 
      writer.Close(); 
      client.Close(); 
     } 
     catch (Exception ex) 
     { 
      // Catch Exception 
     } 
+0

흠, 이건 내게는 효과가 없다 ....이게 GK420t에서 작동하는지 알아? – Calvin

+0

TCP 스트림을 사용하지만 기본적으로 프린터의 전원이 꺼져 있습니다 .TCP가 활성화되어 있고 프린터가/무선을 지원하는지 확인 했습니까? 가져 오는 오류는 무엇입니까? – Warren

+0

base64를 사용하여이 작업을 시도했습니다. 매뉴얼에 따라 CRC 값을 계산할 수는 있지만 작동하지 못했습니다. 16 진수도 사용하게되었습니다. –

6

ZPL II Programming Guide 이미지를 다운로드하도록 명령 ~DG GRF 포맷 (124 페이지) 문서화. Volume Two은 선택적 압축 형식에 대한 세부 사항을 추가합니다 (52 페이지).

먼저 이미지를 1bpp 이중 수준 이미지로 변환 한 다음 16 진수로 인코딩 된 문자열로 변환해야합니다. 전송 시간을 줄이기 위해 이미지를 압축 할 수 있습니다. 그런 다음 ^ID 명령을 사용하여 이미지를 인쇄 할 수 있습니다.

~DY 명령에서 PNG 이미지가 기본적으로 지원되지만 설명이 제대로되어 있지 않으며 일부 프린터 모델에서는 작동하지 않습니다. 기본적으로 ZB64 형식은 문서화되어 있지 않으며 Zebra 지원에서 더 많은 정보를 얻으려는 시도는 효과가 없습니다. ZB64에 마음이 있으면 Java based Zebralink SDK을 사용할 수 있습니다 (ImagePrintDemo.javacom.zebra.sdk.printer.internal.GraphicsConversionUtilZpl.sendImageToStream 참조).

일단 명령 데이터가 있으면 프린터에 인쇄 서버가있는 경우 TCP/IP를 통해 보내거나 RAW 형식으로 프린터에 보낼 수 있습니다.

아래의 코드는 GRF (60 킬로바이트 압축) 압축 된 13 킬로바이트로 5 kB의 PNG를 인쇄 : 나는 B64가 동작하지 않습니다 어떤 이유로

class Program 
{ 
    static unsafe void Main(string[] args) 
    { 
     var baseStream = new MemoryStream(); 
     var tw = new StreamWriter(baseStream, Encoding.UTF8); 

     using (var bmpSrc = new Bitmap(Image.FromFile(@"label.png"))) 
     { 
      tw.WriteLine(ZplImage.GetGrfStoreCommand("R:LBLRA2.GRF", bmpSrc)); 
     } 
     tw.WriteLine(ZplImage.GetGrfPrintCommand("R:LBLRA2.GRF")); 
     tw.WriteLine(ZplImage.GetGrfDeleteCommand("R:LBLRA2.GRF")); 

     tw.Flush(); 
     baseStream.Position = 0; 

     var gdipj = new GdiPrintJob("ZEBRA S4M-200dpi ZPL", GdiPrintJobDataType.Raw, "Raw print", null); 
     gdipj.WritePage(baseStream); 
     gdipj.CompleteJob(); 
    } 
} 

class ZplImage 
{ 
    public static string GetGrfStoreCommand(string filename, Bitmap bmpSource) 
    { 
     if (bmpSource == null) 
     { 
      throw new ArgumentNullException("bmpSource"); 
     } 
     validateFilename(filename); 

     var dim = new Rectangle(Point.Empty, bmpSource.Size); 
     var stride = ((dim.Width + 7)/8); 
     var bytes = stride * dim.Height; 

     using (var bmpCompressed = bmpSource.Clone(dim, PixelFormat.Format1bppIndexed)) 
     { 
      var result = new StringBuilder(); 

      result.AppendFormat("^XA~DG{2},{0},{1},", stride * dim.Height, stride, filename); 
      byte[][] imageData = GetImageData(dim, stride, bmpCompressed); 

      byte[] previousRow = null; 
      foreach (var row in imageData) 
      { 
       appendLine(row, previousRow, result); 
       previousRow = row; 
      } 
      result.Append(@"^FS^XZ"); 

      return result.ToString(); 
     } 
    } 

    public static string GetGrfDeleteCommand(string filename) 
    { 
     validateFilename(filename); 

     return string.Format("^XA^ID{0}^FS^XZ", filename); 
    } 

    public static string GetGrfPrintCommand(string filename) 
    { 
     validateFilename(filename); 

     return string.Format("^XA^FO0,0^XG{0},1,1^FS^XZ", filename); 
    } 

    static Regex regexFilename = new Regex("^[REBA]:[A-Z0-9]{1,8}\\.GRF$"); 

    private static void validateFilename(string filename) 
    { 
     if (!regexFilename.IsMatch(filename)) 
     { 
      throw new ArgumentException("Filename must be in the format " 
       + "R:XXXXXXXX.GRF. Drives are R, E, B, A. Filename can " 
       + "be alphanumeric between 1 and 8 characters.", "filename"); 
     } 
    } 

    unsafe private static byte[][] GetImageData(Rectangle dim, int stride, Bitmap bmpCompressed) 
    { 
     byte[][] imageData; 
     var data = bmpCompressed.LockBits(dim, ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed); 
     try 
     { 
      byte* pixelData = (byte*)data.Scan0.ToPointer(); 
      byte rightMask = (byte)(0xff << (data.Stride * 8 - dim.Width)); 
      imageData = new byte[dim.Height][]; 

      for (int row = 0; row < dim.Height; row++) 
      { 
       byte* rowStart = pixelData + row * data.Stride; 
       imageData[row] = new byte[stride]; 

       for (int col = 0; col < stride; col++) 
       { 
        byte f = (byte)(0xff^rowStart[col]); 
        f = (col == stride - 1) ? (byte)(f & rightMask) : f; 
        imageData[row][col] = f; 
       } 
      } 
     } 
     finally 
     { 
      bmpCompressed.UnlockBits(data); 
     } 
     return imageData; 
    } 

    private static void appendLine(byte[] row, byte[] previousRow, StringBuilder baseStream) 
    { 
     if (row.All(r => r == 0)) 
     { 
      baseStream.Append(","); 
      return; 
     } 

     if (row.All(r => r == 0xff)) 
     { 
      baseStream.Append("!"); 
      return; 
     } 

     if (previousRow != null && MatchByteArray(row, previousRow)) 
     { 
      baseStream.Append(":"); 
      return; 
     } 

     byte[] nibbles = new byte[row.Length * 2]; 
     for (int i = 0; i < row.Length; i++) 
     { 
      nibbles[i * 2] = (byte)(row[i] >> 4); 
      nibbles[i * 2 + 1] = (byte)(row[i] & 0x0f); 
     } 

     for (int i = 0; i < nibbles.Length; i++) 
     { 
      byte cPixel = nibbles[i]; 

      int repeatCount = 0; 
      for (int j = i; j < nibbles.Length && repeatCount <= 400; j++) 
      { 
       if (cPixel == nibbles[j]) 
       { 
        repeatCount++; 
       } 
       else 
       { 
        break; 
       } 
      } 

      if (repeatCount > 2) 
      { 
       if (repeatCount == nibbles.Length - i 
        && (cPixel == 0 || cPixel == 0xf)) 
       { 
        if (cPixel == 0) 
        { 
         if (i % 2 == 1) 
         { 
          baseStream.Append("0"); 
         } 
         baseStream.Append(","); 
         return; 
        } 
        else if (cPixel == 0xf) 
        { 
         if (i % 2 == 1) 
         { 
          baseStream.Append("F"); 
         } 
         baseStream.Append("!"); 
         return; 
        } 
       } 
       else 
       { 
        baseStream.Append(getRepeatCode(repeatCount)); 
        i += repeatCount - 1; 
       } 
      } 
      baseStream.Append(cPixel.ToString("X")); 
     } 
    } 

    private static string getRepeatCode(int repeatCount) 
    { 
     if (repeatCount > 419) 
      throw new ArgumentOutOfRangeException(); 

     int high = repeatCount/20; 
     int low = repeatCount % 20; 

     const string lowString = " GHIJKLMNOPQRSTUVWXY"; 
     const string highString = " ghijklmnopqrstuvwxyz"; 

     string repeatStr = ""; 
     if (high > 0) 
     { 
      repeatStr += highString[high]; 
     } 
     if (low > 0) 
     { 
      repeatStr += lowString[low]; 
     } 

     return repeatStr; 
    } 

    private static bool MatchByteArray(byte[] row, byte[] previousRow) 
    { 
     for (int i = 0; i < row.Length; i++) 
     { 
      if (row[i] != previousRow[i]) 
      { 
       return false; 
      } 
     } 

     return true; 
    } 
} 

internal static class NativeMethods 
{ 
    #region winspool.drv 

    #region P/Invokes 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern bool OpenPrinter(string szPrinter, out IntPtr hPrinter, IntPtr pd); 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern bool ClosePrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern UInt32 StartDocPrinter(IntPtr hPrinter, Int32 level, IntPtr di); 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern bool EndDocPrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern bool StartPagePrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern bool EndPagePrinter(IntPtr hPrinter); 

    [DllImport("winspool.Drv", SetLastError = true, CharSet = CharSet.Unicode)] 
    internal static extern bool WritePrinter(
     // 0 
     IntPtr hPrinter, 
     [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pBytes, 
     // 2 
     UInt32 dwCount, 
     out UInt32 dwWritten); 

    #endregion 

    #region Structs 

    [StructLayout(LayoutKind.Sequential)] 
    internal struct DOC_INFO_1 
    { 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string DocName; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string OutputFile; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string Datatype; 
    } 

    #endregion 

    #endregion 
} 

/// <summary> 
/// Represents a print job in a spooler queue 
/// </summary> 
public class GdiPrintJob 
{ 
    IntPtr PrinterHandle; 
    IntPtr DocHandle; 

    /// <summary> 
    /// The ID assigned by the print spooler to identify the job 
    /// </summary> 
    public UInt32 PrintJobID { get; private set; } 

    /// <summary> 
    /// Create a print job with a enumerated datatype 
    /// </summary> 
    /// <param name="PrinterName"></param> 
    /// <param name="dataType"></param> 
    /// <param name="jobName"></param> 
    /// <param name="outputFileName"></param> 
    public GdiPrintJob(string PrinterName, GdiPrintJobDataType dataType, string jobName, string outputFileName) 
     : this(PrinterName, translateType(dataType), jobName, outputFileName) 
    { 
    } 

    /// <summary> 
    /// Create a print job with a string datatype 
    /// </summary> 
    /// <param name="PrinterName"></param> 
    /// <param name="dataType"></param> 
    /// <param name="jobName"></param> 
    /// <param name="outputFileName"></param> 
    public GdiPrintJob(string PrinterName, string dataType, string jobName, string outputFileName) 
    { 
     if (string.IsNullOrWhiteSpace(PrinterName)) 
      throw new ArgumentNullException("PrinterName"); 
     if (string.IsNullOrWhiteSpace(dataType)) 
      throw new ArgumentNullException("PrinterName"); 

     IntPtr hPrinter; 
     if (!NativeMethods.OpenPrinter(PrinterName, out hPrinter, IntPtr.Zero)) 
      throw new Win32Exception(); 
     this.PrinterHandle = hPrinter; 

     NativeMethods.DOC_INFO_1 docInfo = new NativeMethods.DOC_INFO_1() 
     { 
      DocName = jobName, 
      Datatype = dataType, 
      OutputFile = outputFileName 
     }; 
     IntPtr pDocInfo = Marshal.AllocHGlobal(Marshal.SizeOf(docInfo)); 
     RuntimeHelpers.PrepareConstrainedRegions(); 
     try 
     { 
      Marshal.StructureToPtr(docInfo, pDocInfo, false); 
      UInt32 docid = NativeMethods.StartDocPrinter(hPrinter, 1, pDocInfo); 
      if (docid == 0) 
       throw new Win32Exception(); 
      this.PrintJobID = docid; 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(pDocInfo); 
     } 
    } 

    /// <summary> 
    /// Write the data of a single page or a precomposed PCL document 
    /// </summary> 
    /// <param name="data"></param> 
    public void WritePage(Stream data) 
    { 
     if (data == null) 
      throw new ArgumentNullException("data"); 
     if (!data.CanRead && !data.CanWrite) 
      throw new ObjectDisposedException("data"); 
     if (!data.CanRead) 
      throw new NotSupportedException("stream is not readable"); 

     if (!NativeMethods.StartPagePrinter(this.PrinterHandle)) 
      throw new Win32Exception(); 

     byte[] buffer = new byte[0x14000]; /* 80k is Stream.CopyTo default */ 
     uint read = 1; 
     while ((read = (uint)data.Read(buffer, 0, buffer.Length)) != 0) 
     { 
      UInt32 written; 
      if (!NativeMethods.WritePrinter(this.PrinterHandle, buffer, read, out written)) 
       throw new Win32Exception(); 

      if (written != read) 
       throw new InvalidOperationException("Error while writing to stream"); 
     } 

     if (!NativeMethods.EndPagePrinter(this.PrinterHandle)) 
      throw new Win32Exception(); 
    } 

    /// <summary> 
    /// Complete the current job 
    /// </summary> 
    public void CompleteJob() 
    { 
     if (!NativeMethods.EndDocPrinter(this.PrinterHandle)) 
      throw new Win32Exception(); 
    } 

    #region datatypes 
    private readonly static string[] dataTypes = new string[] 
    { 
     // 0 
     null, 
     "RAW", 
     // 2 
     "RAW [FF appended]", 
     "RAW [FF auto]", 
     // 4 
     "NT EMF 1.003", 
     "NT EMF 1.006", 
     // 6 
     "NT EMF 1.007", 
     "NT EMF 1.008", 
     // 8 
     "TEXT", 
     "XPS_PASS", 
     // 10 
     "XPS2GDI" 
    }; 

    private static string translateType(GdiPrintJobDataType type) 
    { 
     return dataTypes[(int)type]; 
    } 
    #endregion 
} 

public enum GdiPrintJobDataType 
{ 
    Unknown = 0, 
    Raw = 1, 
    RawAppendFF = 2, 
    RawAuto = 3, 
    NtEmf1003 = 4, 
    NtEmf1006 = 5, 
    NtEmf1007 = 6, 
    NtEmf1008 = 7, 
    Text = 8, 
    XpsPass = 9, 
    Xps2Gdi = 10 
} 
+0

방금 ​​생명을 구 했어요! 정말 고맙겠습니다 . –

1

하지만, 다행히 나는 내 방식을 Google에 수 있었다 일반 old JavaScript를 사용하여 Z64를 (3 개의 영혼을 찾는 시대에) 작동하도록 만듭니다.

다른 사람이 (가) CISDFCRC16 명령 우연히 ZPL 프로그래밍 안내서에 어딘가에 -의이 비밀이 될 수 있도록, 왜 안 - 상태 섹션 :

"필드의 값은 CRC-을 계산 CRC16-CCITT 다항식 ( x^16 + x^12 + x^5 + 1)을 사용하여 지정된 파일의 내용 인 에 대해 16입니다.이 값은 0x0000의 초기 CRC를 사용하여 계산됩니다.

Japanglish 옆으로, 당신은 지금 16 비트 (http://reveng.sourceforge.net/crc-catalogue/16.htm)와 parametrised CRC 알고리즘의 카탈로그를 확인하고

width=16 poly=0x1021 init=0x0000 refin=false refout=false 
xorout=0x0000 check=0x31c3 name="XMODEM" 

아하로 일어나는 XMODEM 알고리즘도 찾아보실 수 있습니다. 그때 내가 필요한 코드의 나머지 부분을 찾고 시작하고 다음에 발견 :

그래서 I는 I가 CRC를 계산하는 시점에서 바이트 배열 (Uint8Array), LZ77와 압축 문자열로 파싱 바이트 배열로 그 뒤로 돌려베이스 64을 사용하여 인코딩으로 파일을 읽을 내 ZPL ~ DT 명령에 붙여 넣어 약 40 %의 비용을 절감하십시오. 아름다운.

불행히도 독점 솔루션을 개발하고 있으므로 코드를 게시 할 수 없습니다.

행운을 빈다.

- 한 사람이 다른 사람이 할 수있는 일.

+0

나는 이것을 해결하는 것을 망설이는 것처럼 보입니다. B64를 사용하지 않으면 Z64가 작동하지 않는 것이고 압축 된 파일을로드하지 않은 ZPL은 압축되지 않은 버전으로 기본 설정되어있는 것 같습니다. 드로잉 보드로 돌아 가기 – thor2k

+0

압축 기능이 현재 사용중인 프린터에서 구현되지 않았습니다. 제조업체는 압축 된 개체 (글꼴 또는 이미지)를 처리하는 펌웨어 버전에서 작업하고 있습니다. 나는 너희 모두를 계속 지키겠다! – thor2k

관련 문제