Tehnični članak

Ustvarjanje berljivih črtnih kod v PDF-ju s HotPDF v Delphiju

Črtna koda ni slika, s katero okrasite dokument. To je meritev, bralnik (scanner) pa je inštrument, ki jo bere. Ta preokviritev odloča o skoraj vsem, kako jo morate narisati v PDF. Črte s svojo črnino ne nosijo nobenih informacij; informacije živijo v razmerju med širino črt in širino presledkov, bralnik pa jih pridobi tako, da meri čas prehodov, ko laser ali senzor potuje čez. Stisnite to geometrijo, jo zameglite ali pa natrpajte njene robove in ustvarili boste nekaj, kar je videti natanko kot črtna koda in se bere kot packa. HotPDF vam ponuja dva načina za postavljanje kode na stran, razlika med njima pa je natanko razlika med nadzorovanjem te geometrije in predajo le-te

Stran PDF, ki prikazuje mrežo linearnih črtnih kod v različnih simbolologijah, ki jih je narisal HotPDF v Delphiju
Linearne simbolologije črtnih kod, narisane v enem PDF-ju s HotPDF

Kaj HotPDF lahko zakodira

HotPDF riše linearne (enodimenzionalne) simbolologije (symbologies) in nabor je širši, kot ga potrebuje večina projektov. Oštevilčenje (enumeration) THPDFBarcodeType pokriva družino Code 2 of 5 v prepletenih (interleaved), industrijskih in matričnih oblikah; Code 39 in njeno razširjeno različico; tri podmnožice Code 128: A, B in C; Code 93 (navadno in razširjeno); MSI; PostNet; Codabar; maloprodajno skupino UPC in EAN, in sicer EAN-8, EAN-13, UPC-A, stisnjena UPC-E0 in UPC-E1, ter dopolnilna dvo- in petmestna dodatka UPC (supplemental add-ons); in podmnožice GS1-128 (EAN-128). To je dovolj za pokritje nalepk dobavne verige (supply-chain labels), maloprodajnih blagajn in starejših industrijskih kod, ki so še vedno žive v skladiščih

Kar pa ne riše, je dvodimenzionalna družina. Tukaj ni QR, Data Matrix ali PDF417. Te zakodirajo bajte v mrežo z lastno matematiko za odpravljanje napak (error-correction math), in če katera od zahtev imenuje eno od njih, je to napačno orodje in to bi morali vedeti, še preden gradite okoli njega, ne po tem. Za enodimenzionalne kode je praktično vprašanje ožje: katera simbolologija sprejema podatke, ki jih dejansko imate, saj kodiranja niso zamenljiva

Omejitve podatkov so resnične in udarijo v času generiranja. Različice Code 2 of 5 in MSI sprejemajo samo števke (digits). Code 39 nosi velike črke, števke in peščico ločil; če potrebujete male črke ali celoten obseg ASCII, sta to Code 39 Extended ali podmnožica Code 128. Code 128C zapakira dve števki v vsak simbol zaradi gostote, zato potrebuje le numerični niz sodo dolžine (even-length) in nič drugega. EAN-13 pričakuje dvanajst števk in izračuna trinajsto kot preverjanje (check digit); EAN-8 pričakuje sedem in izračuna osmo; UPC-A vzame dvanajst. Predajte simbolologiji podatke, ki jih ne more predstaviti, in ne dobite uporabne izjeme (exception), dobite črtno kodo, ki zakodira smeti, kar je še slabše, saj izgleda v redu, dokler je nekdo ne optično prebere na blagajni

Dve poti risanja, dve ravni nadzora

Metoda, po kateri posežete v produkciji, je DrawBarcode na predmetu strani (page object). Vzame simbolologijo, položaj, višino in en parameter, ki je pomembnejši od ostalih: MUnit, širino modula (module width). Modul je širina najožje črte (narrowest bar), atom, katerega večkratnik je vsaka druga mera v kodi, in tukaj je izražen v točkah. Vse o tem, ali se tiskani rezultat da prebrati, sega nazaj do tega enega celega števila

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;

Dva argumenta si zaslužita podrobnejši pogled. UseCheckSum doda kontrolno števko modula 10 (modulo-10 check digit), ki jo pričakuje simbolologija, in za maloprodajne kode jo skoraj vedno želite imeti True; izklopite jo samo takrat, ko vaši podatki že nosijo vnaprej izračunano preverjanje, sicer boste dobili podvojeno števko. Barvi črt in ozadja sta zadnja dva parametra, in skušnjava po ustvarjalnosti tukaj je past, o kateri razpravljamo spodaj. Upoštevajte tudi izhodišče koordinat: kot vsak drug klic risanja v HotPDF, X in Y merita od spodnjega levega kota strani v točkah, pri čemer Y raste navzgor, ista konvencija, ki jo obdela primer Hello World

Druga pot je DirectDrawBarcode, ki vzame podatke in omejevalno polje (bounding box), X, Y, Width, Height, ter prilagodi vzorec črt, da zapolni to širino. Primeren je za razporejanje kod na mrežo, ker poimenujete odtis (footprint) in metoda nanj namesti črte. Ta priročnost je hkrati tudi njena nevarnost. Ko ji podate širino, ne nastavljate več velikosti modula; metoda razdeli poljuben prostor, ki ga dovolite, med ne glede na to koliko črt podatki potrebujejo, najožja črta pa postane tisto, kar pade iz te delitve. Zahtevajte gost niz Code 128 znotraj preozkega polja in moduli se tiho skrčijo pod tisto, kar lahko reši (resolve) kateri koli bralnik. Za karkoli, kar se mora zanesljivo brati, raje izberite DrawBarcode in namensko nastavite MUnit. DirectDrawBarcode prihranite za predoglede in ureditve, pri katerih ste izmerili, da nastale črte ostanejo čitljive

Širina modula je odločitev o ločljivosti

Tukaj je aritmetika, ki določa, ali vaša nalepka deluje. Laserski bralnik in kamera imata najmanjšo podrobnost (feature), ki jo lahko razločita, in ozka črta mora po tiskanju pristati udobno nad njo. Široko citirana spodnja meja (floor) za linearne kode splošnega namena je 13 mil (milijonink palca) ozka črta, približno 0,33 mm, in številni maloprodajni in industrijski vodniki to obravnavajo kot minimum in ne kot cilj. Prevedite to v enote PDF: ena točka (point) je 1/72 palca, približno 0,353 mm, tako da ena točka širine modula leži točno na tej meji. To je razlog, zakaj je MUnit := 1 najmanjša vrednost, ki ji smete zaupati za kodo, namenjeno pravemu bralniku, in zakaj njena podvojitev na 2 kupi rezervo, ki na nalepki z dovolj prostora ne stane skoraj nič

Sedaj povežite to z izhodno ločljivostjo (output resolution), ker mora modul preživeti tudi tiskalnik. Na laserskem tiskalniku s 300 DPI (pikami na palec) je ena pika naprave (device dot) 1/300 palca, zato je modul ene točke širok približno štiri pike. Štiri pike so komaj dovolj za izris čistega roba; razlivanje tonerja in rahla napaka pri registraciji odžreta vanj, in črta, ki je v vašem PDF-ju merila eno točko, se natisne debeleje ali tanjše, kot to dopuščajo specifikacije. Povečajte modul na 2 točki in za delo imate osem pik, kar absorbira ta šum. Pravilo, ki si ga je vredno zapomniti: širina modula, ki jo nastavite v točkah, se mora preslikati v celo, udobno število pik naprave pri vaši realni ločljivosti tiska, ne pri ločljivosti, ki bi si jo želeli imeti. Koda, ki se brezhibno bere z zaslona in propade na skladiščnem tiskalniku, skoraj vedno pade pri tem preverjanju

Tiho območje je del simbola

Najpogostejši razlog, zakaj se pravilno zakodirana črtna koda ne prebere, je tiho območje (quiet zone), prazen rob na vsaki strani črt. Bralniki uporabljajo to praznino, da ugotovijo, kje se koda začne in konča; brez nje bralnik ne more ločiti prve črte od česar koli, kar se nahaja zraven na strani. Standardi so specifični. Večina linearnih simbolologij zahteva tiho območje najmanj desetkratne širine modula na vsaki strani, maloprodajne kode UPC in EAN pa zahtevajo devet modulov na levi in sedem na desni. Pri modulu ene točke je to približno deset točk, približno sedmina palca, zajamčenega belega prostora, ki obdaja črte

HotPDF nariše črte in nič drugega. Tihega območja ne rezervira za vas, kar pomeni, da je odgovornost vaša in na to je enostavno pozabiti. Način odpovedi je subtilen: črtno kodo postavite poravnano z obrobo celice tabele ali pa pustite, da jo postavitev strani utesni z logotipom, in koda, ki je na prazni strani prestala vsak preizkus, se preneha brati v trenutku, ko se odpošlje znotraj pravega dokumenta. Eksplicitno predvidite rob v proračunu. Preden pokličete DrawBarcode, pustite vsaj deset širin modula prostega prostora na obeh straneh in vsako grafiko, ravnilo ali besedilo, ki vdre v ta pas, obravnavajte kot okvaro, ne kot kozmetično izbiro

Barva, kontrast in človeku berljiva vrstica

Barvi črt in ozadja obstajata zato, da se lahko ujemata z barvno paleto znamke, hkrati pa sta najhitrejši način, kako pokvariti delujočo kodo. Bralniki berejo kontrast, klasično z rdečo svetlobo, in pričakujejo temne črte na svetlem polju. Črna na belem je edina kombinacija, po kateri bi smeli poseči brez testiranja. Temno modra ali temno zelena na belem lahko preide; karkoli z nizkim luminančnim kontrastom (luminance contrast) in še posebej rdeče črte, ki jih bralnik z rdečo lučjo vidi kot ozadje, pa ne. Če oblikovalec zahteva barvne črtne kode, je pošten odgovor ta, da črte ostanejo črne, barva pa gre nekam drugam na nalepki

Pot DrawBarcode lahko prav tako upodobi človeku berljivo besedilo pod črtami (human-readable text), torej števke, ki jih vnese prodajalec, ko branje ne uspe. To besedilo je zadnja možnost in ne okras, zato ga takrat, ko vstavljate svoj lasten napis, držite stran od tihega območja; oznaka simbolologije, strpana v stranski rob, izniči isti prazen prostor, od katerega je odvisen bralnik. Polja v tem primeru, vključno s TextOut za morebitne okoliške oznake, so enaki klici risanja, ki jih zajema vodnik za izpisovanje poročil (report output guide), ki je pravo mesto, kadar je črtna koda en element na večji sestavljeni strani

Kratka navada za preverjanje

Vektorske črte so prednost, ki jo je vredno omeniti. Ker DrawBarcode zapiše kodo kot operaterje risanja v PDF-ju namesto kot rastrirano sliko (rasterized image), ostanejo črte ostre pri vsaki povečavi, datoteka pa ne nosi lastne ločljivosti; edina pomembna ločljivost je ločljivost tiskalnika. To vas ne odvezuje od testiranja, to le pomeni, da se mora test zgoditi na papirju. Ustvarite vzorec, ga natisnite na napravi z najnižjo ločljivostjo, s katero se bodo vaše kode dejansko srečale, in ga preberite z enakim razredom bralnika, kot ga uporabljajo vaši uporabniki, ne pa z vrhunskim slikovnikom (imager) na vaši mizi. Z ravnilom preverite tiha območja na izpisu, potrdite, da je širina modula preživela prehod iz točk v pike tiskalnika, in preverite, ali se dekodirana vrednost ujema s tistim, kar ste zakodirali, vključno s kontrolno števko in vsem. Pet minut s pravim bralnikom ulovi vsako zgoraj opisano napako in jih ulovi preden to stori paleta napačno označenega blaga

Metodi DrawBarcode in DirectDrawBarcode, prikazani tukaj, sta del komponente HotPDF Component za Delphi in C++Builder