Kod kreskowy to nie obrazek do dekoracji dokumentu. To układ wymiarów, a skaner to instrument, który go odczytuje. Zrozumienie tego decyduje prawie o wszystkim w kontekście tego, jak powinieneś rysować go w PDF. Paski nie niosą informacji poprzez swoją czerń; informacja żyje w stosunku szerokości pasków do szerokości przerw, a czytnik odzyskuje ją, mierząc czas przejść, gdy laser lub sensor przesuwa się po nich. Ściśnij tę geometrię, zamaż ją lub zatłocz jej marginesy, a otrzymasz coś, co wygląda dokładnie jak kod kreskowy, ale skanuje się jak zwykła plama. HotPDF daje dwa sposoby umieszczenia kodu na stronie, a różnica między nimi to dokładnie różnica pomiędzy kontrolowaniem tej geometrii, a poddaniem się jej całkowicie

Co potrafi kodować HotPDF
HotPDF obsługuje liniowe (jednowymiarowe) kody kreskowe, a dostępny zestaw jest szerszy niż potrzebuje większość projektów. Typ wyliczeniowy THPDFBarcodeType obejmuje rodzinę Code 2 of 5 w odmianie Interleaved (z przeplotem), Industrial i Matrix; Code 39 i jego rozszerzony wariant; trzy podzbiory Code 128 (A, B i C); zwykły i rozszerzony Code 93; MSI; PostNet; Codabar; grupę kodów detalicznych UPC i EAN, mianowicie EAN-8, EAN-13, UPC-A, skompresowane UPC-E0 i UPC-E1 oraz 2- i 5-cyfrowe dodatki uzupełniające UPC; a także podzbiory GS1-128 (EAN-128). Jest to wystarczające na pokrycie etykiet łańcucha dostaw, detalicznych punktów sprzedaży i starszych kodów przemysłowych, które wciąż używane są w magazynach
Czego jednak nie kreśli, to kody dwuwymiarowe. Nie ma tutaj kodów QR, Data Matrix, ani PDF417. W nich bajty informacji zakodowane są na siatce przy użyciu własnej matematyki korekcji błędów, i jeśli specyfikacja wymaga jednego z nich, używasz złego narzędzia – i powinieneś to wiedzieć zanim obudujesz wokół niego system, a nie po fakcie. W przypadku kodów jednowymiarowych praktyczne pytanie jest węższe: która symbolika przyjmuje dane, którymi faktycznie dysponujesz, ponieważ kodowania te nie mogą być stosowane zamiennie
Ograniczenia dotyczące danych są realne i dają o sobie znać w momencie generowania. Warianty Code 2 of 5 i MSI przyjmują wyłącznie cyfry. Code 39 przenosi wielkie litery, cyfry i kilka znaków interpunkcyjnych; jeśli potrzebujesz małych liter lub pełnego zakresu ASCII, to zadanie dla Code 39 Extended lub podzbioru Code 128. Code 128C dla gęstości pakuje po dwie cyfry w każdy symbol, więc wymaga ciągu cyfr o parzystej długości i niczego więcej. EAN-13 oczekuje dwunastu cyfr i oblicza trzynastą jako cyfrę kontrolną; EAN-8 oczekuje siedmiu i oblicza ósmą; UPC-A przyjmuje dwanaście. Przekaż symbolice dane, których nie potrafi reprezentować, a nie otrzymasz pomocnego wyjątku - otrzymasz kod kreskowy ze śmieciami, co jest gorsze, ponieważ wygląda on prawidłowo aż do momentu, gdy ktoś zeskanuje go przy kasie
Dwie ścieżki rysowania, dwa poziomy kontroli
Metodą, po którą powinieneś sięgnąć w środowisku produkcyjnym, jest DrawBarcode na obiekcie strony. Przyjmuje ona symbolikę, pozycję, wysokość i jeden parametr, który ma większe znaczenie niż pozostałe: MUnit, szerokość modułu. Moduł to szerokość najwęższego paska, swoisty atom, którego wielokrotnością jest każdy inny wymiar w kodzie, a wyrażany jest w punktach. Wszystko, co decyduje o tym, czy wydrukowany wynik skanuje się poprawnie, sprowadza się do tej jednej liczby całkowitej
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;
Dwa argumenty zasługują na bliższe przyjrzenie się. UseCheckSum dołącza cyfrę kontrolną modulo-10 oczekiwaną przez symbolikę i w przypadku kodów detalicznych prawie zawsze chcesz, by ta opcja była ustawiona na True; wyłącz to tylko wtedy, gdy Twoje dane mają już wstępnie wyliczoną sumę kontrolną, w przeciwnym razie otrzymasz podwojoną cyfrę. Kolor paska i tła to dwa ostatnie parametry, a pokusa do bycia tutaj kreatywnym jest pułapką, omówioną poniżej. Zwróć też uwagę na początek układu współrzędnych: jak każde wywołanie rysujące w HotPDF, parametry X i Y są mierzone od lewego dolnego rogu strony w punktach, a Y rośnie w górę – to ta sama konwencja, którą omawia przykład Hello World
Drugą ścieżką jest DirectDrawBarcode, która przyjmuje dane i ramkę ograniczającą X, Y, Width, Height, i skaluje wzór pasków, aby wypełnić tę szerokość. Jest to wygodne do układania kodów na siatce, ponieważ określasz wielkość obszaru, a metoda dopasowuje paski do niego. Ta wygoda jest zarazem największym zagrożeniem. Podając szerokość, nie ustawiasz już wielkości modułu; metoda dzieli określoną przez ciebie przestrzeń pomiędzy tak wiele pasków, ile wymagają dane, a najwęższy pasek staje się tym, co wyjdzie z tego podziału. Poproś o wygenerowanie gęstego ciągu znaków w standardzie Code 128 wewnątrz zbyt wąskiej ramki, a wymiar modułów po cichu zmniejszy się poniżej możliwości odczytu na skanerze. Do celów, w których kod ma być niezawodnie zeskanowany, preferuj metodę DrawBarcode i świadomie ustawiaj MUnit. Rezerwuj DirectDrawBarcode tylko i wyłącznie na zaprezentowanie samych podglądów, jak również i przy aranżacjach wymiarowanych na testach z których wiadomo na pewno z mierzalnych ujęć, iż generowane ujęcia dają wyraźny obraz i same paski czytane przez skaner nie przynoszą obaw w testowanym obrysie
Szerokość modułu to decyzja o rozdzielczości
Oto matematyka, która decyduje o tym, czy Twoja etykieta będzie działać. Zarówno skaner laserowy, jak i aparat fotograficzny mają najmniejszą cechę (detal), którą są w stanie rozróżnić, a szerokość najwęższego paska po wydrukowaniu musi uplasować się z pewnym zapasem powyżej tej granicy. Powszechnie przywoływana wartość minimalna dla kodów liniowych ogólnego przeznaczenia to najwęższy pasek o grubości 13 mil (tysięcznych cala), czyli około 0,33 mm, a wiele instrukcji branżowych i dla handlu detalicznego traktuje to jako dolne minimum, a nie wartość docelową. Przekładając to na jednostki PDF: jeden punkt to 1/72 cala, czyli z grubsza 0,353 mm, więc jeden punkt szerokości modułu leży dokładnie w tych okolicach. Z tego powodu MUnit := 1 jest najmniejszą wartością, na jakiej powinieneś polegać w przypadku kodu przeznaczonego dla rzeczywistego skanera, i dlatego podwojenie jej na 2 zapewnia dodatkowy margines bezpieczeństwa, który nic nie kosztuje na etykiecie z odpowiednio dużą ilością miejsca
Teraz odnieś to do rozdzielczości wyjściowej, ponieważ moduł musi również przetrwać wydruk. Na drukarce laserowej 300 DPI jedna plamka urządzenia to 1/300 cala, więc moduł o wielkości jednego punktu ma szerokość około czterech plamek. Cztery plamki to zaledwie minimum wystarczające do oddania czystej krawędzi; rozpraszanie tonera i niewielki błąd pasowania (rejestracji) nieco się w to wgryzają, w efekcie czego pasek, który w twoim PDF mierzył jeden punkt, drukuje się grubszy lub węższy niż pozwala na to specyfikacja. Zwiększ moduł do 2 punktów, a zyskasz osiem plamek do dyspozycji, co zaabsorbuje ten szum. Zasada warta zapamiętania: ustalana w punktach szerokość modułu musi bez reszty przeliczać się na pełną, komfortową liczbę plamek dla fizycznej rozdzielczości druku danego urządzenia, a nie rozdzielczości, o której tylko marzyłeś. Kod, który skanuje się bez zarzutu z ekranu, ale zawodzi w przypadku drukarki magazynowej, niemal zawsze nie zdał tego sprawdzianu
Cicha strefa to integralna część symbolu
Najczęstszą przyczyną, dla której poprawnie zakodowany kod kreskowy się nie skanuje, jest cicha strefa (quiet zone), czyli pusty margines po obu stronach pasków. Skanery wykorzystują tę pustą przestrzeń, by odnaleźć miejsce, w którym kod się zaczyna i kończy; bez niej czytnik nie jest w stanie odróżnić pierwszego paska od tego, co akurat znajduje się obok niego na stronie. Standardy podchodzą do tego bardzo rygorystycznie. Większość symbolik liniowych wymaga cichej strefy o szerokości co najmniej dziesięciokrotności szerokości modułu z każdej strony, a w detalicznych kodach UPC i EAN wprost nakazano wykorzystanie marginesu szerokości równej 9 modułom po lewej i 7 modułom z prawej. Przy module o wielkości jednego punktu jest to z grubsza margines rzędu co najmniej dziesięciu punktów, czyli ok 1/7 cala zapewnionej absolutnie pustej białej przestrzeni po bokach
HotPDF rysuje paski i nic poza tym. Nie rezerwuje cichej strefy za ciebie, co oznacza, że to twoja odpowiedzialność i bardzo łatwo o tym zapomnieć. Tryb awarii jest subtelny: umieszczasz kod kreskowy na równi z krawędzią komórki tabeli albo pozwalasz, by logo tłoczyło się tuż obok niego w układzie strony, i kod, który przeszedł każdy test na pustej stronie, przestaje się skanować w momencie, gdy ląduje w prawdziwym dokumencie. Wyraźnie budżetuj miejsce na ten margines. Zanim wywołasz DrawBarcode, zostaw co najmniej 10 szerokości modułu czystej, pustej przestrzeni po obu stronach i traktuj każdą grafikę, linię lub tekst, które wkraczają w ten obszar, jako usterkę, a nie wybór estetyczny
Kolor, kontrast i linia czytelna dla człowieka
Kolory pasków i tła istnieją po to, abyś mógł dopasować je do palety marki, i są one jednocześnie najszybszym sposobem na popsucie działającego kodu. Skanery odczytują kontrast, klasycznie używając światła czerwonego, i oczekują ciemnych pasków na jasnym polu. Czarny na białym to jedyne połączenie, po które powinieneś sięgać bez konieczności testowania. Ciemnoniebieski lub ciemnozielony na białym może przejść; cokolwiek z niskim kontrastem luminancji, a w szczególności paski czerwone, które skaner na światło czerwone traktuje jak tło – absolutnie nie. Jeśli projektant prosi o kolorowe kody kreskowe, szczera odpowiedź powinna brzmieć, że paski pozostają czarne, a kolor wędruje gdzieś indziej na etykiecie
Ścieżka dla metody DrawBarcode potrafi wyrenderować pod paskami również tekst czytelny dla człowieka – to te cyfry, które kasjer wbija z klawiatury w przypadku nieudanego odczytu ze skanera. Ten tekst jest planem awaryjnym (zabezpieczeniem), a nie dekoracją, więc gdy chcesz użyć własnego podpisu pod elementem, pozostaw go z dala od cichej strefy; nazwa symboliki wepchnięta obok w margines boczny, skutecznie niszczy i zakłóca tę pustą i nieskazitelną białą przestrzeń, od której skaner jest absolutnie zależny. Pola, a w tym i użyty do wstawienia TextOut do wyrysowania podpisów z załączonego z góry, gotowego rozwiązania testowego dla wprowadzonych kodów i tekstowych wartości pokazane w przykładzie stanowią dokładne to samo ujęcie u wywołań omówionych precyzyjniej w poradniku tworzenia raportów. Uderzaj z wizytą właśnie i z reguły, zawsze celowo na to pojęcie do omawianej dokumentacji w tamto miejsce w pojęcia wprowadzane, kiedy kod kreskowy jest jednym z elementów na większej złożonej stronie
Krótki nawyk weryfikacyjny
Wektorowe paski to zaleta, o której warto głośno powiedzieć. Ponieważ DrawBarcode zapisuje kod za pomocą systemowych operatorów rysowania PDF, a nie jako obraz rastrowy, paski pozostają niezwykle ostre przy każdym powiększeniu, a sam plik nie wnosi własnej rozdzielczości; jedyną rozdzielczością, która ma znaczenie, jest ta obsługiwana wprost przez drukarkę. To nie zwalnia Cię jednak z testowania, oznacza jedynie, że sprawdzian musi odbyć się na papierze. Wygeneruj próbkę, wydrukuj ją na urządzeniu o najniższej rozdzielczości, z jakim faktycznie zetkną się Twoje kody, i zeskanuj za pomocą czytnika tej samej klasy, jaką dysponują Twoi użytkownicy, a nie za pomocą wysokiej klasy czytnika obrazu, który trzymasz na biurku. Sprawdź strefy ciche za pomocą linijki na wydruku, upewnij się, że szerokość modułu przetrwała przejście z punktów (points) na fizyczne plamki wydruku (dots), i zweryfikuj, czy zdekodowana wartość zgadza się z tym, co zakodowałeś, włącznie z cyfrą kontrolną. Pięć minut spędzonych z prawdziwym skanerem pozwala wychwycić każdą opisaną powyżej usterkę i robi to, zanim na magazyn trafi cała paleta źle oznakowanego asortymentu
Metody DrawBarcode oraz DirectDrawBarcode pokazane w tym artykule stanowią integralną część komponentu HotPDF dla Delphi i C++Builder