zplCore.comzplCore.com

ZPL-Optimierer

ZplOptimizer.Optimize verkleinert ZPL ohne Pixeländerung (geprüft am gesamten Labelary-Korpus): Safe entfernt redundante Zustandsbefehle (^BY, ^CF …), Aggressive zusätzlich Zeilenumbrüche und Standardparameter und komprimiert Grafiken neu (GraphicCompression Hex/ACS/Z64). Felddaten bleiben unangetastet, bei ^CC/^CT bleibt die Eingabe unverändert. Im Label-Modell: Label.Optimization.

string safe = ZplOptimizer.Optimize(zpl, ZplOptimization.Safe);              // doppelte ^BY/^CF/... entfernen
string small = ZplOptimizer.Optimize(zpl, ZplOptimization.Aggressive,        // + Zeilenumbrüche, Standardparameter
    GraphicCompression.Z64);                                                 // + Grafiken neu komprimieren

label.Optimization = ZplOptimization.Aggressive;     // gilt für ToZpl und die Datenbindung
label.GraphicCompression = GraphicCompression.Z64;

ZPL-Formatter & ZPL-Diff

ZplFormatter.Format (= ZplDocument.Parse(zpl).ToZpl(new ZplOutputOptions { PrettyPrint = true })) schreibt einen Befehl pro Zeile und rückt Etiketteninhalt und Feldblöcke (^FO/^FT … ^FS) ein, optional mit einem ^FX-Kommentar je Feld; ZplFormatter.Minify entfernt Leerraum und Kommentare. Felddaten (^FD/^FV), ^FH-Escapes und ~DG/^GF-Nutzdaten bleiben Byte für Byte erhalten, nach Felddaten wird nie ein Zeilenumbruch eingefügt – die Ausgabe ergibt dieselben Befehle und rendert pixelgleich (getestet am gesamten Beispiel- und Labelary-Korpus). ZplDiff.Compare rendert zwei Versionen und liefert je Etikett ein Overlay-PNG (rot entfernt, grün neu, grau unverändert), die Zahl geänderter Pixel, Bounding-Boxen der Änderungen und einen Zeilen-Diff der formatierten Quellen. Kommandozeile: zplcore format und zplcore diff.

string pretty = ZplFormatter.Format(zpl);                    // ein Befehl pro Zeile, Feldblöcke eingerückt
string commented = ZplFormatter.Format(zpl, new ZplOutputOptions
{
    PrettyPrint = true, Indent = 4, AddComments = true,      // ^FX-Kommentar je Feld (Text, Barcode, Box …)
});
string minified = ZplFormatter.Minify(zpl);                  // ohne Leerraum zwischen Befehlen und ohne ^FX
string viaModel = ZplDocument.Parse(zpl).ToZpl(ZplOutputOptions.Pretty);

var diff = ZplDiff.Compare(zpl, zplNew, new ZplRenderSettings { Dpi = 203 });
foreach (var l in diff.Labels)                               // rot = entfernt, grün = neu, grau = gleich
    File.WriteAllBytes($"diff-{l.Index + 1}.png", l.OverlayPng!);
Console.WriteLine($"{diff.ChangedPixels} Pixel geändert, Regionen: {diff.Labels[0].Regions.Count}");
foreach (var d in diff.TextDiff.Where(d => d.Kind != ZplDiffLineKind.Unchanged))
    Console.WriteLine((d.Kind == ZplDiffLineKind.Added ? "+ " : "- ") + d.Text);

Online ausprobieren auf zplCloud.com: ZPL-Formatter · ZPL-Diff

Font-Download, Speicher umbenennen & Elemente als JSON

Label.FontDownloadZpl() liefert nur die ~DY/~DU-Befehle der Label-Fonts, FontManager.Convert wandelt jede TTF in einen Download-Befehl, Label.FontAsGraphicThreshold sendet große Fonts stattdessen als Grafik. Der ZplResourceStore kann Grafiken, Formate und Fonts umbenennen und dekodierte Grafiken cachen. ZplRenderResult.RenderedElementsAsJson() gibt die getracten Elemente mit Typ, Daten, Bounds, Rotation und Quellposition aus.

var label = new Label(LabelUnit.Mm, 50, 20).AddFont("MYFONT.TTF", ttf);
label.Add(new TextItem { Text = "Hallo", Font = "E:MYFONT.TTF" });
string fonts = label.FontDownloadZpl();                         // nur ~DY…, einmalig an den Drucker
string du = label.FontDownloadZpl(FontDownloadCommand.DU);
string raw = FontManager.Convert(ttf, "R:OTHER", FontDownloadCommand.DU); // beliebige TTF → ZPL
label.FontAsGraphicThreshold = 512 * 1024;                     // größere Fonts als ^GFA-Grafik
var r = new ZplRenderer();
r.Render("~DGR:OLD.GRF,8,1,FFFFFFFFFFFFFFFF");
r.Store.RenameGraphic("OLD", "E:LOGO.GRF");
r.Store.RenameFormat("A", "C");
r.Store.RenameFont("E:F1.TTF", "F2.TTF");
r.Store.CacheGraphics = true;               // dekodierte ^GF-Grafiken wiederverwenden
int cached = r.Store.CachedGraphicCount;
var renderer = new ZplRenderer(new ZplRenderSettings { TraceElements = true });
foreach (var res in renderer.Render(zpl))
{
    // [{"type":"A","data":"Hi","bounds":{"x":..},"rotation":90,"sourceOffset":..,"sourceLength":..}, ...]
    string json = res.RenderedElementsAsJson(indented: true);
    res.Bitmap.Dispose();
}

15ZPL-Objektmodell

ZplDocument.Parse zerlegt ZPL in ZplFormats mit typisierten Befehlen – je ZPL-Befehl eine Unterklasse von ZplCommandBase (FieldOriginCommand, Code128Command, Pdf417Command …, unbekannte als UnknownCommand). Eigenschaften ändern, ToString() schreibt wieder ZPL. ZplBuilder baut Formate fluent auf.

// typisiertes Objektmodell: parsen, ändern, wieder schreiben
ZplDocument doc = ZplDocument.Parse(zplIn);
foreach (ZplFormat format in doc.LabelFormats)
{
    foreach (FieldOriginCommand fo in format.OfType<FieldOriginCommand>())
        fo.X += 20;                                       // alles 20 Punkte nach rechts
    foreach (Code128Command bc in format.OfType<Code128Command>())
        bc.Height = 60;
}
string moved = doc.ToString();

// oder von Grund auf mit dem ZplBuilder
string zpl = new ZplBuilder()
    .Format(f => f
        .Encoding(28)
        .Text(30, 30, "ZplBuilder", height: 40)
        .FieldOrigin(30, 90).BarcodeDefaults(2, height: 70).Code128().FieldData("BUILD-42")
        .FieldOrigin(330, 30).QrCode(magnification: 4).FieldData("QA,ZplDocument")
        .FieldOrigin(20, 20).GraphicBox(540, 200, 3, rounding: 2).FieldSeparator())
    .ToString();

Ausgabe des ZplBuilder

Mit ZplBuilder erzeugtes Etikett
ZPL