配送ラベルや請求書に印刷されたバーコードの役割はただ1つ、最初のスキャンで正しく読み取られることです。その読み取りを無事通過できるかどうかは、パッケージがドックに届くはるか前に決定されています。すなわち、ページ上にシンボルがどのように配置されたかによって決まります。Delphiのレポート作成パイプラインで最もよくある間違いは、バーコードを別の場所でビットマップ画像としてレンダリングし、その画像をPDFに配置することです。画面上ではあるズームレベルで綺麗に見えても、他の場所では品質が劣化してしまいます。
別の方法として、シンボルをベクターコンテンツとしてページに直接描画する方法があります。PDFlibPasはまさにこのために、2Dマトリクスシンボル(QR、PDF417、DataMatrix)、Code128やGS1-128といったリニア(1次元)バーコードファミリー、および郵便自動化用のUSPS Intelligent Mailをカバーする一連の描画APIを公開しています。ベクターを選ぶ理由は美観ではありません。スキャナーが期待する位置に正確にバーが配置されるかどうかです。
ベクター形式が配置されたビットマップに勝る理由
バーコードはバーとスペースのパターンであり、2次元の場合は暗いモジュールと明るいモジュールのグリッドです。デコーダは、それらの幅の比率を測定することによって動作します。比率を歪めるものはすべて、シンボルのエラー許容予算を削るノイズになります。ラスタライズされたバーコード画像は固定されたピクセルを持っています。画像グリッドに均等に分割できないドットを持つプリンターにPDFがレンダリングされると、ラスタライザはリサンプリングを行う必要があり、本来シャープであるべきモジュールの境界が2つのデバイスピクセルに分散してしまいます。細いバーが太くなったり、隣接するスペースが細くなったりして、デコーダが頼りにする幅の比率がずれてしまいます。
ベクターコンテンツとして描画された場合、横幅や縦幅の固定グリッドに対抗する必要はありません。印刷時、デバイスは各長方形を実際の解像度でレンダリングするため、あらゆるスケールや印刷サイズにおいて、ハードウェアが許容する限りモジュールの境界は鮮明になります。パレットラベル用にベクターシンボルを拡大したり、小包用に縮小したりしても、形状は正確に維持されます。この正確さこそが、最初のスキャンでの読み取り率を高く保つ鍵であり、ページにバーコードを配置する目的そのものです。
QRコードと4つの誤り訂正レベル
QRは両方の軸を同時に読み取る2Dマトリクスシンボルであり、そのため小さな正方形に大量のデータを詰め込むことができます。その損傷耐性は、4つのレベルで提供されるリード・ソロモン誤り訂正から得られます。レベルLは約7%のコードワードを復元し、Mは約15%、Qは約25%、Hは約30%を復元します。高い訂正レベルは無料ではありません。復元用コードワードがモジュールの容量を占有するため、一定量のデータに対して訂正レベルを上げると、より密度が高い、あるいは物理的に大きなシンボルが必要になります。
このトレードオフは、シンボルが置かれる環境についての問題です。画面からスキャンされるだけのきれいなデジタルドキュメントであれば、レベルLでコンパクトに維持できます。印刷され、取り扱われ、擦れ、あるいはテープで一部が覆われる可能性があるラベルの場合は、QまたはHが必要になります。追加された冗長性こそが、もはや無傷ではないシンボルからデコーダがペイロードを再構築できるようにするからです。DrawQRCodeは、描画される幅と高さを固定する位置とSymbolSizeに加え、データモード(自動を示す0、または数値、英数字、ISO-8859-1、UTF-8などのバリエーション)を選択するEncodeOptions値、および向きを指定するDrawOptions値を受け取ります。
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;
訂正レベル自体は、要求されたシンボルにデータを適合させるためにエンコーダーによって選択されます。過酷な環境向けに確実に高い訂正レベルが必要な場合は、エンコーダーが適合させるために無理にレベルを下げる必要がないよう、シンボルのサイズを十分に大きくして、冗長性に割り当てるモジュールの予算を確保してください。
IDや配送ラベル向けのPDF417
PDF417はスタックされたリニア(1次元)シンボルです。各行は短いリニアバーコードであり、それらの行が積み重なってブロックを形成します。これが、長方形の領域に広いデータを収める必要がある運転免許証、搭乗券、運送会社の配送ラベルなどに採用されている理由です。その誤り訂正は0から8のスケールで動作します。段階が上がるごとにおおむね訂正コードワードの数が倍増するため、レベル5はレベル1よりもはるかに多くの冗長性を持っていますが、その代償としてページ上のコードワードが多くなります。
PDF417のブロックの形状は調整可能であり、ラベルには配置できる固定領域があるため、これが重要になります。DrawPDF417SymbolExは、基本的な呼び出しでは提供されていない制御パラメータを公開しています。FixedColumnsおよびFixedRowsはデータの列数と行数を固定します(0はエンコーダーの自動選択)。ErrorLevelは、自動を示す-1、または明示的な0から8を受け取ります。ModuleSizeは現在の計測単位における最も細い要素の幅で、HeightWidthRatioは幅に対する各モジュールの高さの比率を設定します。これにより、利用可能なスペースに合わせてブロックを横長にしたり縦長にしたりすることができます。
// 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
列数の固定は、ラベルテンプレートでよく使われる手法です。列数を一定に保つことでブロックの幅が予想しやすくなり、ドキュメント間でエンコードするペイロードの長さが変化しても周囲のレイアウトがずれることがなくなり、エンコーダーは差分を吸収するために行を下方向に追加します。
極小マーキング向けのDataMatrix
DataMatrixは、マーキングを小さくする必要がある場合に選ぶべきシンボルです。これは現代的なリード・ソロモン方式であるECC 200を使用するコンパクトな2Dグリッドであり、同じデータを入れたQRシンボルでは扱いにくくなるような極小サイズでも読み取り可能性を維持します。これにり、直接部品マーキング(DPM)、小型の電子部品、および高密度の物流ラベルなどで標準的な選択肢となっています。
DrawDataMatrixSymbolは、ドットピッチを示すModuleSize、ASCIIコードを示す1を割り当てるEncoding、自動を示す0または10x10から132x132までの標準的な正方形・長方形の寸法のいずれかを示すSymbolSizeを受け取ります。Optionsパラメータは向きとクワイエットゾーン(余白)の幅を組み合わせるもので、100から400を加算することで1〜4モジュール分の白い境界線を設定します。クワイエットゾーンは装飾ではありません。デコーダがシンボルのファインダパターンを検出するためにはこのクリーンな余白が必要であり、他の印刷部分と重なり合っているシンボルは読み取りに失敗します。
// 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
1次元バーコードが依然として支配的な分野
2次元シンボルが注目を集めがちですが、1次元(リニア)バーコードは依然として小売や物流の大部分を支えています。理由は、シングルスキャンを実行するレーザースキャナーのインストールベースが普及しているためです。Code128は英数字データの標準として機能し、その効率性は3つの文字セットから生み出されます。セットAは制御文字と大文字をカバーし、セットBは印刷可能なASCII範囲全体をカバーし、セットCは数値にとって重要です。セットCは一対の数字を単一のシンボル文字にエンコードするため、一連の数値データはセットAまたはBで必要となるシンボル文字の半分で済みます。これが長い数値バーコードを表現する最もコンパクトな方法であり、PDFlibPasのCode128実装はこれを実現するためにセットBとCを自動的に組み合わせます。
GS1-128、以前EAN-128と呼ばれていた規格は、Code128をベースに、後続の数字がシリアル番号、バッチコード、または有効期限であるかどうかを受信システムに伝える括弧付きのプリフィックス(アプリケーション識別子)を保持します。この構造は、シンボルがGS1エンコードされていることを示し、可変長フィールドを区切る特別な非データ文字であるFNC1によってマークされます。PDFlibPasでは、Code128タイプを使用してDrawBarcodeでGS1-128シンボルを描画し、各アプリケーション識別子の開始点となるデータ文字列内にリテラル[FNC1]マーカーを配置します。
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;
郵便用途として、OneCodeとも呼ばれるUSPS Intelligent Mailは、郵便自動化のためにルーティングおよび追跡データを単一の高さ変調バーコードにエンコードします。DrawIntelligentMailBarcodeは、バーの幅、バー全体の高さ、トラッカーの高さ、スペースの幅に関する明示的なジオメトリを受け取り、データは数字のみの20、25、29、または31桁の文字列として提供されます。明示的なバーおよびトラッカーの高さが存在する理由は、各バーがフルバー(full bar)、アセンダー(ascender)、またはディセンダー(descender)のいずれであるかによってシンボルが情報を保持するためであり、郵便リーダーはそれらの高さが仕様通りに保たれていることに依存しています。
ページへの描画とレイアウトのための計測
ここに示したすべての呼び出しは、テキストや画像が配置されるのと同じ表面である、現在選択されているページのコンテンツに描画します。したがって、バーコードは個別のパーツとしてインポートされるのではなく、通常のドキュメント生成の一部として作成されます。シンボルはベクターコンテンツであるため、エンコードするデータとそれが占有するジオメトリはどちらも描画時に判明しており、これによって決定論的に配置することができます。
リニアバーコードファミリーのレイアウトにおいては、事前に計測を行うメリットがあります。GetBarcodeWidthは、指定された細いバーの幅とバーコードタイプに対するバーコードの総描画幅を返すため、ページ構築後に重複に気づいて目測で推測するのではなく、描画を実行する前に正確な水平スペースを予約できます。2Dシンボルは、SymbolSizeまたはModuleSizeを介して描画サイズを直接設定し、シンボルがそのフットプリントを埋めるため、配置がより簡単になります。いずれにせよ規律は同じです。スキャン環境から物理的なサイズを決定し、シンボルが確保したスロットに収まることを確認し、ベクタージオメトリによってスクリーンのプレビューから最終的な印刷まで、すべてのエッジを鮮明に維持します。
これらのバーコードが配置される広範なページ構築ワークフローにおいて、テキスト、画像、およびフォント抽出に関する記事の技術はPDFからコンテンツを読み取る方法をカバーしており、直接アクセスによる大容量PDFの結合・分割ガイドは、大容量ドキュメントを効率的に組み立てる方法を示しています。どちらも、このブログの他の場所で扱われているテキスト、グラフィックス、フォーム、および署名APIと並んで、DelphiおよびC++Builder向けのDelphi PDF Libraryの一部として提供されている、ここで解説した描画APIと深く結びついています。