Articolo tecnico

Generare codici a barre scansionabili in PDF con HotPDF

Un codice a barre non è un'immagine con cui decorare un documento. È una misurazione, e lo scanner è lo strumento che la legge. Questo cambio di prospettiva decide quasi tutto su come dovreste disegnarne uno in un PDF. Le barre non trasportano informazione con la loro nerezza; l'informazione vive nel rapporto tra le larghezze delle barre e le larghezze degli spazi, e un lettore la recupera cronometrando le transizioni mentre un laser o un sensore le attraversa. Comprimete quella geometria, sfocatela o affollatene i margini, e otterrete qualcosa che assomiglia esattamente a un codice a barre ma si scansiona come una sbavatura. HotPDF vi offre due modi per metterne uno su una pagina, e la differenza tra i due è precisamente la differenza tra controllare quella geometria e abbandonarla al caso

Una pagina PDF che mostra una griglia di codici a barre lineari in diverse simbologie disegnati da HotPDF in Delphi
Simbologie di codici a barre lineari disegnate in un unico PDF con HotPDF

Cosa può codificare HotPDF

HotPDF disegna simbologie lineari (monodimensionali), e l'insieme è più ampio di quanto la maggior parte dei progetti richieda. L'enumerazione THPDFBarcodeType copre la famiglia Code 2 of 5 nelle sue forme interleaved, industrial e matrix; Code 39 e la sua variante estesa; i tre sottoinsiemi di Code 128 A, B e C; Code 93 semplice ed esteso; MSI; PostNet; Codabar; il gruppo retail UPC ed EAN, ossia EAN-8, EAN-13, UPC-A, i compressi UPC-E0 e UPC-E1 e i supplementi UPC a 2 e 5 cifre; nonché i sottoinsiemi GS1-128 (EAN-128). È abbastanza da coprire le etichette della supply chain, i punti vendita retail e i vecchi codici industriali ancora vivi nei magazzini

La famiglia è lineare per progetto. Le simbologie bidimensionali come QR, Data Matrix e PDF417 codificano i byte in una griglia con una propria matematica di correzione degli errori e restano fuori da questa API, quindi stabilize quale famiglia nomina il requisito prima di progettare tutto il resto attorno ad essa. Per i codici monodimensionali la domanda pratica è più stretta: quale simbologia accetta i dati che avete davvero, perché le codifiche non sono intercambiabili

I vincoli sui dati sono reali e si fanno sentire al momento della generazione. Le varianti Code 2 of 5 e MSI accettano solo cifre. Code 39 porta lettere maiuscole, cifre e una manciata di segni di punteggiatura; se vi servono lettere minuscole o l'intero range ASCII, serve Code 39 Extended o un sottoinsieme Code 128. Code 128C comprime due cifre in ogni simbolo per guadagnare densità, quindi vuole una stringa numerica di lunghezza pari e nient'altro. EAN-13 si aspetta dodici cifre e calcola la tredicesima come controllo; EAN-8 si aspetta sette e calcola l'ottava; UPC-A ne prende dodici. Validate i dati contro queste regole prima di chiamare DrawBarcode, perché barre costruite con dati che una simbologia non può rappresentare sembrano a posto a schermo e falliscono solo quando qualcuno le passa sotto lo scanner alla cassa

Due percorsi di disegno, due livelli di controllo

Il metodo da preferire in produzione è DrawBarcode, sull'oggetto pagina. Accetta la simbologia, una posizione, un'altezza e un parametro che conta più degli altri: MUnit, la larghezza del modulo. Il modulo è la larghezza della barra più stretta, l'atomo di cui ogni altra misura nel codice è un multiplo, e qui è espresso in punti. Tutto ciò che determina se il risultato stampato si scansiona risale a quel singolo intero

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'label.pdf';
    Pdf.BeginDoc;

    // BCType, X, Y, Height, MUnit (larghezza del modulo in punti), angolo,
    // data, UseCheckSum, bar color, background color.
    Pdf.CurrentPage.DrawBarcode(
      bcCodeEAN13,           // symbology
      72, 72,                // X, Y dell'angolo in alto a sinistra, in punti
      60,                    // bar height
      1,                     // MUnit: 1pt narrowest bar
      0,                     // no rotation
      '123456789012',        // 12 digits; the 13th is the check
      True,                  // aggiunge la cifra di controllo modulo 10
      clBlack, clWhite);     // bars black, background white

    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Due argomenti meritano uno sguardo più attento. UseCheckSum aggiunge la cifra di controllo modulo-10 che la simbologia si aspetta, e per i codici retail lo volete quasi sempre True; disattivatelo solo quando i vostri dati contengono già un controllo precalcolato, altrimenti otterrete una cifra duplicata. I colori di barre e sfondo sono gli ultimi due parametri, e la tentazione di essere creativi lì è una trappola discussa più avanti. Notate anche l'origine delle coordinate: come ogni altra chiamata di disegno di pagina in HotPDF, X e Y si misurano dall'angolo in alto a sinistra della pagina in punti, con Y crescente verso il basso, e individuano l'angolo in alto a sinistra delle barre, la stessa convenzione illustrata nell'esempio Hello World

Il secondo percorso è DirectDrawBarcode, che accetta i dati e un riquadro di delimitazione, X, Y, Width, Height, e scala il pattern di barre per riempire quella larghezza. È comodo per disporre codici su una griglia perché indicate l'ingombro e il metodo vi adatta le barre. Quella comodità è anche il suo pericolo. Quando gli date una larghezza, non state più impostando la dimensione del modulo; il metodo divide lo spazio che concedete tra quante barre servono ai dati, e la barra più stretta diventa quel che risulta da quella divisione. Chiedete una stringa Code 128 densa dentro un riquadro troppo stretto e i moduli si rimpiccioliscono sotto ciò che qualsiasi scanner può risolvere, silenziosamente. Per tutto ciò che deve scansionarsi in modo affidabile, preferite DrawBarcode e impostate MUnit deliberatamente. Riservate DirectDrawBarcode alle anteprime e alle disposizioni in cui avete misurato che le barre risultanti restano leggibili

La larghezza del modulo è una decisione di risoluzione

Ecco l'aritmetica che determina se la vostra etichetta funziona. Uno scanner laser e una fotocamera hanno entrambi una caratteristica minima che riescono a distinguere, e la barra stretta deve collocarsi comodamente al di sopra di essa dopo la stampa. Il limite inferiore citato più spesso per i codici lineari di uso generale è una barra stretta da 13 mil, circa 0,33 mm, e molte guide retail e industriali lo trattano come un minimo piuttosto che come un obiettivo. Traducetelo in unità PDF: un punto è 1/72 di pollice, circa 0,353 mm, quindi un singolo punto di larghezza del modulo si trova proprio su quel limite. Ecco perché MUnit := 1 è il valore più piccolo di cui dovreste fidarvi per un codice destinato a uno scanner reale, e perché raddoppiarlo a 2 compra un margine che non costa quasi nulla su un'etichetta con spazio da vendere

Ora collegate questo alla risoluzione di output, perché il modulo deve anche sopravvivere alla stampante. Su una stampante laser a 300 DPI un punto del dispositivo è 1/300 di pollice, quindi un modulo da un punto è largo circa quattro punti dispositivo. Quattro punti sono appena sufficienti a rendere un bordo pulito; la diffusione del toner e un leggero errore di registrazione lo erodono, e la barra che misurava un punto nel vostro PDF si stampa più grassa o più magra di quanto la specifica consenta. Alzate il modulo a 2 punti e avete otto punti dispositivo con cui lavorare, il che assorbe quel rumore. La regola da interiorizzare: la larghezza del modulo che impostate in punti deve corrispondere a un numero intero e comodo di punti del dispositivo alla vostra reale risoluzione di stampa, non alla risoluzione che vorreste avere. Un codice che si scansiona impeccabilmente sullo schermo e fallisce sulla stampante del magazzino quasi sempre ha fallito questa verifica

La zona di quiete fa parte del simbolo

La ragione singola più comune per cui un codice a barre correttamente codificato non si scansiona è la zona di quiete, il margine bianco su ciascun lato delle barre. Gli scanner usano quel vuoto per individuare dove il codice inizia e finisce; senza di esso, il lettore non può distinguere la prima barra da qualsiasi cosa le stia accanto sulla pagina. Gli standard sono specifici. La maggior parte delle simbologie lineari vuole una zona di quiete di almeno dieci volte la larghezza del modulo su ciascun lato, e i codici retail UPC ed EAN richiedono nove moduli a sinistra e sette a destra. Con un modulo da un punto sono circa dieci punti, circa un settimo di pollice, di spazio bianco garantito ai fianchi delle barre

HotPDF disegna le barre esattamente dove le piazzate voi, e la zona di quiete attorno fa parte del layout della vostra pagina, il che rende facile dimenticarla. La modalità di guasto è subdola: piazzate un codice a barre a filo del bordo di una cella di tabella, o lasciate che il layout stringa un logo accanto, e il codice che superava ogni prova su pagina bianca smette di farsi leggere appena finisce dentro un documento vero. Pianificate il margine in modo esplicito. Prima di chiamare DrawBarcode, lasciate almeno dieci larghezze di modulo di spazio libero su entrambi i lati, e trattate qualsiasi grafica, linea o testo che invade quella fascia come un difetto, non come una scelta estetica

Colore, contrasto e la riga leggibile dall'uomo

I colori di barre e sfondo esistono perché possiate abbinare una palette di brand, e sono il modo più rapido per rompere un codice funzionante. Gli scanner leggono il contrasto, classicamente con luce rossa, e si aspettano barre scure su campo chiaro. Nero su bianco è l'unica combinazione da usare senza test. Blu scuro o verde scuro su bianco possono passare; qualsiasi cosa con basso contrasto di luminanza, e in particolare le barre rosse, che uno scanner a luce rossa vede come sfondo, no. Se un designer chiede codici a barre colorati, la risposta onesta è che le barre restano nere e il colore va da qualche altra parte sull'etichetta

Il percorso DrawBarcode può anche rendere il testo leggibile dall'uomo sotto le barre, le cifre che un addetto digita quando una scansione fallisce. Quel testo è un ripiego, non una decorazione, quindi quando posizionate una didascalia vostra tenetela lontana dalla zona di quiete; un'etichetta della simbologia stipata nel margine laterale vanifica lo stesso spazio bianco da cui lo scanner dipende. I campi dell'esempio qui, incluso TextOut per eventuali etichette circostanti, sono le stesse chiamate di disegno trattate nella guida all'output di report, che è il posto dove andare quando il codice a barre è un elemento in una pagina composita più ampia

Una breve abitudine di verifica

Le barre vettoriali sono un vantaggio che vale la pena nominare. Poiché DrawBarcode scrive il codice come operatori di disegno PDF anziché come immagine rasterizzata, le barre restano nitide a qualsiasi zoom e il file non porta con sé alcuna risoluzione propria; l'unica risoluzione che conta è quella della stampante. Questo non vi esonera dai test, significa solo che il test deve avvenire su carta. Generate un campione, stampatelo sul dispositivo a risoluzione più bassa che i vostri codici incontreranno davvero e scansionatelo con la stessa classe di lettore che i vostri utenti hanno in mano, non con l'imager di fascia alta sulla vostra scrivania. Controllate le zone di quiete con un righello sulla stampa, confermate che la larghezza del modulo sia sopravvissuta al viaggio dai punti ai punti dispositivo e verificate che il valore decodificato corrisponda a ciò che avete codificato, cifra di controllo compresa. Cinque minuti con uno scanner reale intercettano ogni fallimento descritto sopra, e li intercettano prima che lo faccia un pallet di merce etichettata male

I metodi DrawBarcode e DirectDrawBarcode mostrati qui fanno parte del HotPDF Delphi Component per Delphi e C++Builder