Tekninen artikkeli

Viivakoodit PDF-tiedostoissa Delphillä: QR, PDF417, DataMatrix

Lähetystarrassa tai laskussa olevalla viivakoodilla on vain yksi tehtävä, joka on lukijan onnistunut luku ensimmäisellä kerralla. Sen kestävyys tämän tehtävän suorittamisessa ratkaistaan jo kauan ennen paketin saapumista laiturille. Se ratkaistaan sillä, kuinka symboli sijoitetaan sivulle. Yleisin virhe Delphin raportointiputkessa on renderöidä viivakoodi bittikarttana jossain muualla ja sijoittaa kyseinen kuva PDF-tiedostoon. Se näyttää hyvältä näytöllä yhdellä zoomaustasolla ja heikkenee sitten kaikkialla muualla

Vaihtoehto on piirtää symboli vektorisisältönä suoraan sivulle. PDFlibPas paljastaa piirtokutsujen perheen juuri tähän tarkoitukseen, kattaen 2D-matriisisymbolit QR, PDF417 ja DataMatrix, lineaariset perheet Code128:n ja GS1-128:n kautta, sekä USPS Intelligent Mailin postiautomaatioon. Vektorin puolesta puhuva argumentti ei ole esteettinen. Kyse on siitä, osuvatko viivat sinne, minne lukija odottaa niiden osuvan

Miksi vektori voittaa sijoitetun bittikartan

Viivakoodi on viivojen ja välilyöntien kuvio, tai kahdessa ulottuvuudessa tummien ja vaaleiden moduulien ruudukko. Dekooderi toimii mittaamalla näiden leveyksien suhteen. Mikä tahansa, mikä vääristää suhteita, on kohinaa, joka syö symbolin virhebudjettia. Rasteroitu viivakoodikuva sisältää kiinteitä pikseleitä. Kun PDF renderöidään tulostimelle, jonka pisteet eivät jakaudu tasaisesti kuvaruudukkoon, rasteroijan on näytteistettävä uudelleen, ja moduulien reunat, joiden tulisi olla teräviä, leviävät kahdelle laitepikselille. Kapea viiva voi leventyä, viereinen tila voi kaventua, ja dekoooderin luottama leveyssuhde siirtyy

Vektorisisältönä piirrettynä sama symboli on joukko täytettyjä suorakulmioita, jotka on kuvattu PDF:n käyttäjätilakoordinaateissa. Ei ole kiinteää pikseliruudukkoa, jota vastaan taistella. Tulostushetkellä laite renderöi jokaisen suorakulmion tarkalleen sen resoluutiolla, joka sillä on, joten jokainen moduulin reuna on niin terävä kuin laitteisto sallii, missä tahansa mittakaavassa ja missä tahansa tulostuskoossa. Skaalaa vektorisymboli ylös lavatarraa varten tai kutista se paketille, ja geometria pysyy tarkkana. Tämä tarkkuus on se, mikä pitää ensimmäisen kerran lukunopeuden korkeana, mikä on viivakoodin sivulle laittamisen koko tarkoitus

QR-koodit ja neljä korjaustasoa

QR on 2D-matriisisymboli, joka luetaan kummallakin akselilla kerrallaan, minkä vuoksi se pakkaa paljon tietoa pieneen neliöön. Sen vaurionsietokyky tulee Reed-Solomon-virheenkorjauksesta, jota tarjotaan neljällä tasolla. Taso L palauttaa noin 7 prosenttia koodisanoista, M noin 15 prosenttia, Q noin 25 prosenttia ja H noin 30 prosenttia. Suurempi korjaus ei ole ilmaista. Palautuskoodisanat vievät moduulikapasiteettia, joten kiinteälle datamäärälle korkeampi taso pakottaa tiheämmän tai fyysisesti suuremman symbolin

Vaihtokauppa on kysymys siitä ympäristöstä, jossa symboli elää. Puhdas digitaalinen asiakirja, joka luetaan aina vain näytöltä, voi olla tasolla L ja pysyä kompaktina. Tarra, joka tulostetaan, jota käsitellään, naarmuuntuu ja jonka teippi saattaa peittää osittain, haluaa tasoa Q tai H, koska ylimääräinen redundanssi on se, mikä antaa dekooderille mahdollisuuden rekonstruoida hyötykuorman symbolista, joka ei ole enää koskematon. DrawQRCode ottaa sijainnin ja SymbolSize-arvon, joka kiinnittää piirretyn leveyden ja korkeuden, plus EncodeOptions-arvon, joka valitsee datatilan (0 automaattiselle, tai numeeriset, aakkosnumeeriset, ISO-8859-1- ja UTF-8-variantit) ja DrawOptions-arvon suuntausta varten

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;

Enkooderi valitsee itse korjaustason sovittaakseen tiedot pyytämääsi symboliin. Jos tarvitset taatun korkean tason kovaan ympäristöön, mitoita symboli anteliaasti, jotta enkooderilla on moduulibudjettia käytettävän redundanssiin sen sijaan, että se pakotettaisiin alas sovittumaan

PDF417 henkilökorteille ja lähetystarroille

PDF417 on pinottu lineaarinen symboli. Jokainen rivi on lyhyt lineaarinen viivakoodi, ja rivit pinoutuvat lohkoksi, minkä vuoksi se näkyy ajokorteissa, tarkastuskorteissa ja kuriirien lähetystarroissa, joissa leveämmän tietokaistaleen on sovittava suorakulmaiseen tilaan. Sen virheenkorjaus tapahtuu asteikolla 0–8. Jokainen askel suunnilleen kaksinkertaistaa korjauskoodisanojen määrän, joten taso 5 sisältää paljon enemmän redundanssia kuin taso 1, useampien koodisanojen kustannuksella sivulla

PDF417-lohkon muoto on säädettävissä, ja sillä on merkitystä, koska tarralla on kiinteä täytettävä alue. DrawPDF417SymbolEx paljastaa kontrollit, joita peruskutsu ei paljasta. FixedColumns ja FixedRows kiinnittävät datasarakkeiden määrän ja rivien määrän, missä 0 tarkoittaa anna enkooderin päättää. ErrorLevel ottaa -1:n automaattista varten tai eksplisiittisen arvon 0–8. ModuleSize on nykyisen mittayksikön kapeimman elementin leveys, ja HeightWidthRatio määrittää kuinka pitkä kukin moduuli on suhteessa sen leveyteen, jolloin teet lohkosta lyhyen ja leveän tai pitkän ja kapean vastaamaan käytettävissä olevaa tilaa

// 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

Sarakkeiden kiinnittäminen on tavallinen vipu tarramallissa. Vakiosarakemäärä antaa lohkolle ennakoitavan leveyden, jotta ympäröivä asettelu ei siirry, kun koodatun hyötykuorman pituus muuttuu asiakirjasta toiseen, kun taas enkooderi lisää rivejä alaspäin vaimentaakseen eron

DataMatrix pienille merkeille

DataMatrix on se symboli, johon kannattaa tarttua, kun merkin on oltava pieni. Se on kompakti 2D-ruudukko, joka käyttää ECC 200:a, modernia Reed-Solomon-menetelmää, ja se pysyy luettavana ko'oissa, joissa saman tiedon QR-symboli olisi hankala. Tämä tekee siitä vakio valinnan osien suoramerkintään (direct part marking), pieniin elektronisiin komponentteihin ja tiheisiin logistiikkatarroihin

DrawDataMatrixSymbol ottaa ModuleSize:n pisteväliä varten, Encoding on 1 ASCII:lle, ja SymbolSize on joko 0 automaattiselle tai yksi standardeista neliömäisistä tai suorakulmaisista mitoista, arvosta 10x10 arvoon 132x132. Options-parametri yhdistää suuntauksen hiljaisen alueen (quiet-zone) leveyteen, missä lisäämällä arvoja 100 - 400 asetetaan yhden - neljän moduulin valkoinen reuna. Hiljainen alue ei ole koristelua. Dekooderi tarvitsee tämän selkeän marginaalin symbolin etsintäkuvion löytämiseksi, ja symboli, joka on ahtautettu muuta mustetta vasten, on symboli, jota ei onnistuta hankkimaan

// 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

Missä 1D-viivakoodit edelleen hallitsevat

Kaksiulotteiset symbolit saavat huomion, mutta lineaariset viivakoodit omistavat edelleen suuria osia vähittäiskaupasta ja logistiikasta, ja syynä on asennettujen laserlukijoiden kanta, jotka lukevat yhden pyyhkäisyn. Code128 on työjuhta aakkosnumeeriselle tiedolle, ja sen tehokkuus perustuu kolmeen merkistöön. Joukko A kattaa ohjausmerkit ja isot kirjaimet, joukko B kattaa täyden tulostettavan ASCII-alueen, ja joukko C on se, jolla on väliä numeroille. Alijoukko C koodaa numeroparin yhdeksi symbolimerkiksi, joten numeerisen tiedon sarja vie puolet niistä symbolimerkeistä kuin mitä se veisi joukossa A tai B. Tämä on kompaktein tapa laatia pitkä numeerinen viivakoodi, ja PDFlibPas Code128 -toteutus yhdistää B- ja C-joukot automaattisesti sen saavuttamiseksi

GS1-128, standardi, joka tunnettiin aiemmin nimellä EAN-128, rakentuu Code128:n päälle kantamalla sovellustunnisteita (Application Identifiers), suluissa olevia etuliitteitä, jotka kertovat vastaanottavalle järjestelmälle, ovatko seuraavat numerot sarjanumero, eräkoodi vai viimeinen käyttöpäivä. Rakenteen merkitsee FNC1, erityinen ei-data-merkki, joka merkitsee symbolin GS1-koodatuksi ja erottaa vaihtuvanpituiset kentät. PDFlibPas-kirjastossa piirrät GS1-128-symbolin DrawBarcode-toiminnolla käyttämällä Code128-tyyppiä ja kirjaimellista [FNC1]-merkintää, joka on sijoitettu datamerkkijonoon sinne, mistä kukin sovellustunniste alkaa

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;

Postille USPS Intelligent Mail, jota kutsutaan myös OneCodeksi, koodaa reititys- ja seurantatiedot yhteen korkeusmoduloidun viivakoodin postiautomaatiota varten. DrawIntelligentMailBarcode ottaa eksplisiittisen geometrian tangon leveydelle, koko tangon korkeudelle, seurantalaitteen korkeudelle ja tilan leveydelle, ja tiedot toimitetaan 20, 25, 29 tai 31 numeron merkkijonona. Eksplisiittiset viivan ja seurantalaitteen korkeudet ovat olemassa siksi, että symboli sisältää tietoa siitä, onko kukin viiva kokonainen viiva, nouseva (ascender) vai laskeva (descender), ja postinlukija luottaa siihen, että nämä korkeudet pidetään määritysten mukaisina

Sivulle piirtäminen ja asettelun mittaaminen

Jokainen tässä esitetty kutsu piirtää parhaillaan valitun sivun sisältöön, samalle pinnalle, joka vastaanottaa tekstisi ja kuvasi, joten viivakoodi tuotetaan osana normaalia dokumentin luontia sen sijaan, että se tuotaisiin erillisenä resurssina. Koska symbolit ovat vektorisisältöä, niiden koodaama data ja niiden viemä geometria ovat molemmat tiedossa piirtohetkellä, mikä antaa sinun sijoittaa ne deterministisesti

Lineaaristen perheiden asettelu hyötyy mittaamisesta ensin. GetBarcodeWidth palauttaa viivakoodin kokonaisleveyden tietylle kapealle viivaleveydelle ja viivakoodityypille, joten voit varata tarkan vaakasuoran tilan ennen kuin teet piirron, sen sijaan että arvaat ja huomaat päällekkäisyyden sivun rakentamisen jälkeen. 2D-symbolit ovat yksinkertaisempia sijoittaa, koska asetat niiden piirretyn koon suoraan SymbolSize- tai ModuleSize-ominaisuuden kautta, ja symboli täyttää kyseisen jalanjäljen. Kummassakin tapauksessa kuri on sama. Päätä fyysinen koko lukuympäristöstä, varmista, että symboli sopii sinulla olevaan paikkaan, ja anna vektorigemetrian pitää jokainen reuna terävänä näytön esikatselusta lopulliseen tulosteeseen

Laajempaan sivunrakennustyönkulkuun, johon nämä viivakoodit putoavat, pdflibpas-text-image-font-extraction.html-artikkelimme tekniikat kattavat sisällön lukemisen takaisin PDF-tiedostosta, ja pdflibpas-large-pdf-merge-split-direct-access.html-opas näyttää, kuinka suurten asiakirjojen asennus hoidetaan tehokkaasti. Molemmat yhdistyvät luonnollisesti tässä kuvatun piirto-API:n kanssa, joka toimitetaan osana Delphi PDF Library -kirjastoa Delphille ja C++Builderille muiden tekstin, grafiikan, lomakkeen ja allekirjoituksen API:iden ohella, joita käsitellään muualla tässä blogissa