En streckkod är inte en bild du dekorerar ett dokument med. Det är en mätning, och skannern är instrumentet som läser av den. Denna omformulering (reframing) avgör nästan allt om hur du ska rita in en i en PDF. Strecken bär ingen information genom sin svärta; informationen lever i förhållandet mellan streckens och mellanrummens bredd, och en läsare återvinner den genom att klocka övergångarna när en laser eller sensor sveper över. Kläm ihop den geometrin, gör den suddig, eller träng in på dess marginaler, och du producerar något som ser exakt ut som en streckkod och skannas som en fläck. HotPDF ger dig två sätt att placera en på en sida, och skillnaden mellan dem är exakt skillnaden mellan att kontrollera den geometrin och att ge upp den

Vad HotPDF kan koda (encode)
HotPDF ritar linjära (endimensionella) symbologier, och uppsättningen är bredare än vad de flesta projekt behöver. Enumerationen THPDFBarcodeType täcker Code 2 of 5-familjen i dess interleaved, industrial och matrix-former; Code 39 och dess utökade variant; de tre Code 128-underuppsättningarna (subsets) A, B och C; Code 93 vanlig och utökad; MSI; PostNet; Codabar; detaljhandelns UPC- och EAN-grupp, nämligen EAN-8, EAN-13, UPC-A, de komprimerade UPC-E0 och UPC-E1, och de kompletterande UPC-tilläggen (add-ons) med 2 och 5 siffror; samt GS1-128 (EAN-128)-underuppsättningarna. Det är tillräckligt för att täcka leveranskedjeetiketter (supply-chain labels), detaljhandelns kassa (point of sale), och de äldre industriella koder som fortfarande lever i lagerlokaler
Vad den inte ritar är den tvådimensionella familjen. Det finns ingen QR, Data Matrix eller PDF417 här. Dessa kodar byte i ett rutnät med sin egen felkorrigeringsmatematik, och om ett krav nämner en av dem är detta fel verktyg och du bör veta det innan du bygger runt det snarare än efter. För endimensionella koder är den praktiska frågan smalare: vilken symbologi accepterar den data du faktiskt har, eftersom kodningarna (encodings) inte är utbytbara
Databegränsningarna är verkliga och de slår till vid genereringstillfället. Code 2 of 5-varianterna och MSI tar endast siffror. Code 39 bär versaler, siffror och en handfull skiljetecken; om du behöver gemener eller hela ASCII-området, är det Code 39 Extended eller en Code 128-underuppsättning. Code 128C packar två siffror i varje symbol för densitet, så den vill ha en numerisk sträng med jämn längd och inget annat. EAN-13 förväntar sig tolv siffror och beräknar den trettonde som en kontroll (check); EAN-8 förväntar sig sju och beräknar den åttonde; UPC-A tar tolv. Ge en symbologi data den inte kan representera och du får inget hjälpsamt undantag (exception), du får en streckkod som kodar skräp, vilket är värre, eftersom det ser bra ut tills någon skannar det i en kassa
Två ritvägar, två nivåer av kontroll
Den metod man ska sträcka sig efter i produktion är DrawBarcode, på sidobjektet. Den tar symbologin, en position, en höjd och en parameter som spelar större roll än resten: MUnit, modulbredden (module width). Modulen är bredden på det smalaste strecket, den atom (atom) som alla andra mått i koden är en multipel av, och den uttrycks här i punkter (points). Allt om huruvida det utskrivna resultatet kan skannas spåras tillbaka till det enda heltalet
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'label.pdf';
Pdf.BeginDoc;
// BCType, X, Y, Height, MUnit (module width in points), angle,
// data, UseCheckSum, bar color, background color.
Pdf.CurrentPage.DrawBarcode(
bcCodeEAN13, // symbology
72, 680, // X, Y in points from the bottom-left
60, // bar height
1, // MUnit: 1pt narrowest bar
0, // no rotation
'123456789012', // 12 digits; the 13th is the check
True, // append the modulo-10 check digit
clBlack, clWhite); // bars black, background white
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
Två argument förtjänar en närmare titt. UseCheckSum lägger till modulo-10-kontrollsiffran (check digit) som symbologin förväntar sig, och för detaljhandelskoderna vill du nästan alltid att det ska vara True; stäng av den endast när dina data redan bär en förberäknad kontroll, annars får du en dubblerad siffra. Streckens och bakgrundens färger är de två sista parametrarna, och frestelsen att vara kreativ där är en fälla som diskuteras nedan. Notera också koordinatorigon: precis som alla andra ritanrop (drawing calls) i HotPDF, mäter X och Y från sidans nedre vänstra hörn i punkter, med Y växande uppåt, samma konvention som Hello World-exemplet går igenom
Den andra vägen är DirectDrawBarcode, som tar datan och en avgränsningsruta (bounding box), X, Y, Width, Height, och skalar streckmönstret för att fylla den bredden. Det är bekvämt för att lägga ut koder på ett rutnät eftersom du anger fotavtrycket (footprint) och metoden anpassar strecken till det. Den bekvämligheten är också dess fara (hazard). När du ger den en bredd ställer du inte längre in modulstorleken; metoden dividerar det utrymme du tillåter mellan de streck datan behöver, och det smalaste strecket blir det som faller ut av den divisionen. Be om en tät (dense) Code 128-sträng inuti en för smal låda och modulerna krymper under vad någon skanner kan upplösa (resolve), helt tyst. För allt som måste skannas tillförlitligt, föredra DrawBarcode och ställ in MUnit medvetet. Reservera DirectDrawBarcode för förhandsgranskningar och för arrangemang där du har mätt (measured) att de resulterande strecken förblir läsliga
Modulbredd är ett upplösningsbeslut (resolution decision)
Här är aritmetiken som avgör om din etikett fungerar. En laserskanner och en kamera har båda en minsta funktion de kan urskilja, och det smala strecket måste landa bekvämt över det efter utskrift. Det allmänt citerade golvet (floor) för generella linjära koder är ett 13 mils (mils) smalt streck, cirka 0,33 mm, och många detaljhandels- och industriguider behandlar det som ett minimum snarare än ett mål. Översätt det till PDF-enheter: en punkt (point) är 1/72 tum, ungefär 0,353 mm, så en enda punkt i modulbredd ligger precis på det golvet. Det är därför MUnit := 1 är det minsta värdet du bör lita på för en kod avsedd för en riktig skanner, och varför en fördubbling till 2 köper en marginal som kostar nästan ingenting på en etikett med utrymme till övers
Koppla nu det till utdataupplösningen (output resolution), eftersom modulen också måste överleva skrivaren. På en 300 DPI-laserskrivare är en enhetsprick (device dot) 1/300 tum, så en enpunktsmodul är cirka fyra prickar bred. Fyra prickar är knappt tillräckligt för att rita (render) en ren kant; tonerspridning (toner spread) och litet registreringsfel (registration error) äter in på det, och strecket som mätte en punkt i din PDF skrivs ut tjockare eller tunnare än vad specifikationen tillåter. Höj modulen till 2 punkter och du har åtta prickar att arbeta med, vilket absorberar det bruset (noise). Regeln värd att internalisera: modulbredden du ställer in i punkter måste mappas till ett helt, bekvämt antal enhetsprickar vid din verkliga utskriftsupplösning, inte den upplösning du önskar att du hade. En kod som skannas felfritt från skärmen och misslyckas från lagrets skrivare har nästan alltid misslyckats med denna kontroll
Den tysta zonen (quiet zone) är en del av symbolen
Den enskilt vanligaste anledningen till att en korrekt kodad streckkod inte kan skannas är den tysta zonen (quiet zone), den tomma marginalen på varje sida om strecken. Skannrar använder den tomheten för att hitta var koden börjar och slutar; utan den kan inte läsaren skilja det första strecket från vad som än sitter bredvid det på sidan. Standarderna är specifika. De flesta linjära symbologier vill ha en tyst zon på minst tio gånger modulbredden på varje sida, och UPC- och EAN-detaljhandelkoderna (retail codes) kräver nio moduler till vänster och sju till höger. Med en enpunktsmodul är det ungefär tio punkter, cirka en sjundedels tum, av garanterat vitt utrymme som flankerar strecken
HotPDF ritar strecken och inget annat. Det reserverar inte den tysta zonen åt dig, vilket innebär att ansvaret är ditt och det är lätt att glömma. Felbeteendet (failure mode) är subtilt: du placerar en streckkod kant i kant (flush) med en tabellcellkant (table cell border), eller du låter sidlayouten tränga en logotyp intill den, och koden som klarade varje test på en tom sida slutar att kunna skannas i det ögonblick den levereras (ships) inuti ett verkligt dokument. Budgetera marginalen uttryckligen. Innan du anropar DrawBarcode, lämna minst tio modulbredder av klart utrymme på båda sidor, och behandla all grafik, linje (rule) eller text som inkräktar (intrudes) på det bandet som en defekt (defect), inte ett kosmetiskt val
Färg, kontrast och den läsbara raden (human-readable line)
Streckens och bakgrundens färger finns så att du kan matcha en varumärkespalett, och de är det snabbaste sättet att bryta en fungerande kod. Skannrar läser kontrast, klassiskt sett med rött ljus, och de förväntar sig mörka streck på ett ljust fält. Svart på vitt är den enda kombinationen du bör välja utan att testa. Mörkblått eller mörkgrönt på vitt kan passera; allt med låg luminanskontrast (luminance contrast), och i synnerhet röda streck, som en rödljus-skanner ser som bakgrund, fungerar inte. Om en designer ber om färgade streckkoder är det ärliga svaret att strecken förblir svarta och att färgen får vara någon annanstans på etiketten
DrawBarcode-vägen kan också rita ut den läsbara texten (human-readable text) under strecken, siffrorna som en expedit (clerk) knappar in när en skanning misslyckas. Den texten är ett reservalternativ (fallback), inte en dekoration, så när du placerar din egen bildtext (caption), håll den fri från den tysta zonen; en etikett av symbologin som klämts in i sidomarginalen motverkar (defeats) samma tomma utrymme som skannern är beroende av. Fälten i exemplet här, inklusive TextOut för alla omgivande etiketter, är samma ritanrop som täcks i report output guide, vilket är stället att gå till när streckkoden är ett element i en större komponerad sida
En kort verifikationsvana
Vektorstreck är en fördel värd att nämna. Eftersom DrawBarcode skriver koden som PDF-ritoperatorer (drawing operators) snarare än en rastrerad bild, förblir strecken skarpa (crisp) vid vilken zoom som helst och filen har ingen egen upplösning; den enda upplösning som spelar roll är skrivarens. Det befriar (excuse) dig inte från att testa, det betyder bara att testet måste ske på papper. Generera ett prov (sample), skriv ut det på den enhet med lägst upplösning som dina koder faktiskt kommer att stöta på, och skanna det med samma klass av läsare som dina användare håller i, inte högpresterande imager-enheten på ditt skrivbord. Kontrollera de tysta zonerna med en linjal på utskriften, bekräfta att modulbredden överlevde resan från punkter till prickar (dots), och verifiera att det avkodade värdet matchar vad du kodade, inklusive kontrollsiffra. Fem minuter med en riktig skanner fångar varje fel som beskrivs ovan, och det fångar dem innan en pall med felmärkta varor gör det
Metoderna DrawBarcode och DirectDrawBarcode som visas här är en del av HotPDF-komponenten för Delphi och C++Builder