En streckkod på en fraktsedel eller en faktura jag ett jobb, vilket är att läsas av en skanner vid första försöket. Huruvida den klarar det försöket avgörs långt innan paketet når kajen. Det avgörs av hur symbolen placerades på sidan. Det vanligaste misstaget i en Delphi-rapporteringspipeline är att rendera streckkoden som en bitmapp någon annanstans och placera den bilden i PDF-filen. Det ser bra ut på skärmen vid en zoomnivå och försämras sedan överallt annars
Alternativet är to rita symbolen som vektorinnehåll, direkt på sidan. PDFlibPas exponerar en familj av ritningsanrop för just detta, som täcker 2D-matrissymbolerna QR, PDF417 och DataMatrix, de linjära familjerna via Code128 och GS1-128, samt USPS Intelligent Mail för postautomation. Argumentet för vektorer är inte estetiskt. Det handlar om huruvida strecken hamnar där skannern förväntar sig dem
Praktiskt sammanhang
En streckkod är ett mönster av streck och mellanslag, eller i två dimensioner ett rutnät av mörka och ljusa moduler. Avkodaren fungerar genom att mäta förhållandet mellan dessa bredder. Allt som förvränger förhållandena är brus som äter av symbolens felbudget. En rastrerad streckkodsbild bär på fasta pixlar. När PDF-filen renderas till en skrivare vars punkter inte delar upp sig jämnt i bildrutnätet, måste rastreraren sampla om, och modulkanter som borde vara skarpa sprids över två enhetspixlar. Ett smalt streck kan bli tjockare, ett intilliggande mellanslag kan bli smalare och breddförhållandet som avkodaren litar på glider
Ritad som vektorinnehåll är samma symbol en uppsättning fyllda rektanglar som beskrivs i PDF-användarrymdkoordinater. Det finns inget fast pixelrutnät att kämpa mot. Vid utskrift renderar enheten varje rektangel med den upplösning den faktiskt har, so varje modulkant blir så skarp som hårdvaran tillåter, i valfri skala och utskriftsstorlek. Skala upp en vektorsymbol för en palletikett eller krymp den för ett paket och geometrin förblir exakt. Den precisionen är vad som håller avläsningshastigheten vid första försöket hög, vilket är hela poängen med att placera en streckkod på sidan
Implementeringssteg
QR är en 2D-matrissymbol som läses i båda axlarna samtidigt, vilket är anledningen till att den packar mycket data i en liten kvadrat. Dess skadetolerans kommer från Reed-Solomon-felkorrigering, som erbjuds i fyra nivåer. Nivå L återställer ungefär 7 procent av kodorden, M cirka 15 procent, Q cirka 25 procent och H runt 30 procent. Högre korrigering är inte gratis. Återställningskodorden tar upp modulkapacitet, så för en fast mängd data tvingar en högre nivå fram en tätare eller fysiskt större symbol
Valet är en fråga om miljön som symbolen kommer att leva i. Ett rent digitalt dokument som endast kommer att skannas från en skärm kan ligga på L och förbli kompakt. En etikett som kommer att skrivas ut, hanteras, slitas och kanske delvis täckas av tejp vill ha Q eller H, eftersom den extra redundansen är vad som låter en avkodare rekonstruera nyttolasten från en symbol som inte längre är orörd. DrawQRCode tar positionen och en SymbolSize som fixerar den ritade bredden och höjden, plus ett EncodeOptions-värde som väljer dataläge (0 för automatiskt, eller numeriska, alfanumeriska, ISO-8859-1- och UTF-8-varianter) och ett DrawOptions-värde för orientering
var
Pdf: TPDFlib;
begin
Pdf := TPDFlib.Create(nil);
try
Pdf.NewDocument;
Pdf.SetPageSize('A4');
Pdf.SetMeasurementUnits(1); // 1 = millimetres
Pdf.NewPage;
// 30 mm square QR, automatic encoding, normal orientation
Pdf.DrawQRCode(20, 20, 30, 'https://www.loslab.com/', 0, 0);
Pdf.SaveToFile('Label_QR.pdf');
finally
Pdf.Free;
end;
end;
Själva korrigeringsnivån väljs av kodaren för att passa datan i den symbol du bad om. Om du behöver en garanterat hög nivå för en tuff miljö, dimensionera symbolen generöst så att kodaren har modulbudget att spendera på redundans istället för att tvingas krympa den för att få plats
Kontrollpunkter
PDF417 är en staplad linjär symbol. Varje rad är en kort linjär streckkod, och raderna staplas för att bilda ett block, vilket är anledningen till att den visas på körkort, boardingkort och transportörers fraktsedlar där en bredre dataremsa måste rymmas på en rektangulär yta. Dess felkorrigering körs på en skala från 0 till 8. Varje steg fördubblar ungefär antalet korrigeringskodord, så nivå 5 bär betydligt mer redundans än nivå 1, på bekostnad av fler kodord på sidan
Formen på ett PDF417-block är justerbar, och det spelar roll eftersom etiketten har en fast yta att fylla. DrawPDF417SymbolEx exponerar kontrollerna som det grundläggande anropet inte gör. FixedColumns och FixedRows låser datakolumnantalet och radantalet, där 0 betyder att kodaren får bestämma. ErrorLevel tar -1 för automatiskt eller ett explicit 0 till 8. ModuleSize är bredden på det smalaste elementet i den aktuella måttenheten, och HeightWidthRatio anger hur hög varje modul är i förhållande till sin bredd, vilket är hur du gör blocket kort och brett eller högt och smalt för att matcha det utrymme du har
// Fixed 10 data columns, automatic rows, error level 5,
// module 0.30 mm wide, rows three times the module width tall
Pdf.DrawPDF417SymbolEx(20, 60, 'PDF417 PAYLOAD 0123456789',
0, // Options: 0 = normal orientation
10, // FixedColumns
0, // FixedRows: 0 = automatic
5, // ErrorLevel: 0 to 8
0.30, // ModuleSize, in the current measurement unit
3.0); // HeightWidthRatio
Att låsa kolumner är det vanliga verktyget på en etikettmall. Ett konstant kolumnantal ger blocket en förutsägbar bredd, så att den omgivande layouten inte förskjuts när den kodade nyttolasten ändrar längd från ett dokument till näst, medan kodaren lägger till rader nedåt för att absorbera skillnaden
Praktiskt sammanhang
DataMatrix är symbolen att sträcka sig efter när märkningen måste vara liten. Det är ett kompakt 2D-rutnät som använder ECC 200, det moderna Reed-Solomon-systemet, och det förblir läsbart i storlekar där en QR-symbol med samma data skulle vara otymplig. Det gör den till standardvalet för direkt delmärkning, små elektroniska komponenter och täta logistiketiketter
DrawDataMatrixSymbol tar en ModuleSize för punktavståndet, en Encoding på 1 för ASCII, och en SymbolSize som är antingen 0 för automatisk eller en av de vanliga kvadratiska och rektangulära dimensionerna, från 10x10 upp till 132x132. Parametern Options kombinerar orientering med marginalzonens (quiet zone) bredd, där tillägg av 100 till 400 sätter en till fyra modulers vit ram. Marginalzonen är inte dekoration. En avkodare behöver den tydliga marginalen för att hitta symbolens sökmönster, och en symbol som trängs mot annat bläck är en symbol som inte kan läsas
// Auto-sized ASCII DataMatrix, 0.5 mm module, normal orientation
// with a one-module quiet zone (Options 0 + 100)
Pdf.DrawDataMatrixSymbol(20, 110, 0.5, 'DMX-SN-4408812',
1, // Encoding: 1 = ASCII
0, // SymbolSize: 0 = automatic
100); // Options: normal + one-module quiet zone
Implementeringssteg
Tvådimensionella symboler får mycket uppmärksamhet, men linjära streckkoder äger fortfarande stora delar av detaljhandeln och logistiken, och anledningen är den installerade basen av laserskannrar som läser ett enda svep. Code128 är arbetshästen för alfanumeriska data, och dess effektivitet kommer från tre teckenuppsättningar. Uppsättning A täcker styrtecken och versaler, uppsättning B täcker hela det utskrivbara ASCII-intervallet, och uppsättning C är den som gäller för siffror. Delmängd C kodar ett par siffror i ett enda symboltecken, så en sekvens med numeriska data tar hälften så många symboltecken som den skulle göra i uppsättning A eller B. Detta är det mest kompakta sättet att lägga ut en lång numerisk streckkod, och PDFlibPas Code128-implementering kombinerar B- och C-uppsättningarna automatiskt för att uppnå det
GS1-128, standarden som tidigare hette EAN-128, bygger på Code128 genom att bära applikationsidentifierare (Application Identifiers), de inom parentes placerade prefixen som talar om för ett mottagande system om de efterföljande siffrorna är ett serienummer, en batchkod eller ett utgångsdatum. Strukturen markeras av FNC1, ett speciellt icke-datatecken som flaggar symbolen som GS1-kodad och separerar fält med rörlig längd. I PDFlibPas ritar du en GS1-128-symbol med DrawBarcode med typen Code128 och den bokstavliga [FNC1]-markeringen placerad i datasträngen där varje applikationsidentifierare börjar
var
W: Double;
begin
// Code128, with FNC1 markers this becomes a GS1-128 symbol.
// AI 21 (serial) = ABC123, AI 20 (variant) = 13
Pdf.DrawBarcode(20, 150, 60, 18, '[FNC1]21ABC123[FNC1]2013',
3, // Barcode: 3 = Code128
0); // Options: 0 = default drawing
// Measure the rendered width for a 0.30 mm narrow bar before laying out
W := Pdf.GetBarcodeWidth(0.30, '[FNC1]21ABC123[FNC1]2013', 3);
end;
För post kodar USPS Intelligent Mail, även kallad OneCode, rutt- och spårningsdata i en enda höjdmodulerad streckkod för postautomation. DrawIntelligentMailBarcode tar explicit geometri för streckbredd, full streckhöjd, spårhöjd och mellanrumsbredd, där datan tillhandahålls som en sträng på 20, 25, 29 eller 31 tecken med endast siffror. De explicita streck- och spårhöjderna finns eftersom symbolen bär information om huruvida varje streck är ett helt streck, en uppstapel (ascender) eller en nedstapel (descender), och postläsaren beror på att dessa höjder hålls till specifikationen
Kontrollpunkter
Varje anrop som visas här ritar i innehållet på den för närvarande valda sidan, samma yta som tar emot din text och dina bilder, så en streckkod produceras som en del av normal dokumentgenerering snarare än att importeras som en separat resurs. Eftersen symbolerna är vektorinnehåll är datan de kodar och geometrin de upptar båda kända vid ritningstillfället, vilket är vad som låter dig placera dem deterministiskt
Layout för de linjära familjerna drar nytta av att mäta först. GetBarcodeWidth returnerar den totala ritade bredden på en streckkod för en given bredd på smala streck och streckkodstyp, så att du kan reservera det exakta horisontella utrymmet innan du utför ritningen, snarare än att gissa och upptäcka en överlappning efter att sidan har byggts. 2D-symbolerna är enklare att placera eftersom du ställer in deras ritade storlek direkt via SymbolSize eller ModuleSize, och symbolen fyller det fotavtrycket. Oavsett vilket är disciplinen densamma. Bestäm den fysiska storleken utifrån skanningsmiljön, bekräfta att symbolen passar den plats du har och låt vektorgeometrin hålla varje kant skarp från skärmvisning till slutlig utskrift
För det bredare sidbyggnadsarbetsflödet som dessa streckkoder ingår i, beskriver teknikerna i vår artikel om text-, bild- och teckensnittsutdragning hur man läser tillbaka innehåll från en PDF, och guiden för sammanslagning och uppdelning av stora PDF-filer med direktåtkomst visar hur man monterar dokument med stora volymer effektivt. Båda hör naturligt ihop med det ritnings-API som beskrivs här, vilket levereras som en del av Delphi PDF Library för Delphi och C++Builder, tillsammans med de API:er för text, grafik, formulär och signaturer som beskrivs på andra ställen i denna blogg