Artikel Teknis

Barcode di PDF Dengan Delphi: QR, PDF417, DataMatrix

Barcode pada label pengiriman atau faktur memiliki satu tugas, yaitu dibaca oleh pemindai (scanner) pada percobaan pertama. Apakah barcode tersebut berhasil melewati pemindaian itu diputuskan jauh sebelum paket mencapai dermaga. Ini ditentukan oleh bagaimana simbol tersebut diletakkan di halaman. Kesalahan paling umum dalam alur pelaporan Delphi adalah merender barcode sebagai bitmap di tempat lain dan menempatkan gambar tersebut ke dalam PDF. Ini terlihat baik-baik saja di layar pada satu tingkat zoom dan kemudian menurun kualitasnya di tempat lain

Alternatifnya adalah menggambar simbol sebagai konten vektor, langsung ke halaman. PDFlibPas mengekspos keluarga pemanggilan gambar untuk hal ini, yang mencakup simbol matriks 2D QR, PDF417, dan DataMatrix, keluarga linier melalui Code128 dan GS1-128, serta USPS Intelligent Mail untuk otomatisasi pos. Argumen untuk vektor bukanlah soal estetika. Ini tentang apakah garis-garis (bars) mendarat di tempat yang diharapkan oleh pemindai

Mengapa vektor lebih baik daripada gambar bitmap

Barcode adalah pola garis dan ruang, atau dalam dua dimensi berupa kisi-kisi modul gelap dan terang. Dekoder bekerja dengan mengukur rasio lebar tersebut. Apa pun yang mendistorsi rasio adalah noise yang mengurangi batas toleransi kesalahan (error budget) simbol. Gambar barcode yang dirasterisasi membawa piksel tetap. Saat PDF dirender ke printer yang titiknya tidak membagi grid gambar secara merata, rasterizer harus melakukan resampling, dan tepi modul yang semestinya tajam akan tersebar ke dua piksel perangkat. Batang yang sempit bisa menebal, ruang di sebelahnya bisa menipis, dan rasio lebar yang diandalkan dekoder akan bergeser

Digambar sebagai konten vektor, simbol yang sama hanyalah kumpulan persegi panjang terisi yang dinyatakan dalam koordinat ruang-pengguna PDF. Tidak ada grid piksel tetap yang perlu dilawan. Pada saat pencetakan, perangkat merender setiap persegi panjang pada resolusi yang benar-benar dimilikinya, sehingga setiap tepi modul setajam yang diizinkan perangkat keras, pada skala dan ukuran cetak apa pun. Membesarkan simbol vektor untuk label palet atau mengecilkannya untuk paket tetap menjaga geometri tetap tepat. Presisi itulah yang menjaga tingkat pembacaan pada percobaan pertama tetap tinggi, dan itulah inti dari menaruh barcode di halaman

Kode QR dan empat tingkat koreksi kesalahan

QR adalah simbol matriks 2D yang dibaca di kedua sumbu sekaligus, itulah sebabnya ia mengemas banyak data ke dalam kotak kecil. Toleransi kerusakannya berasal dari koreksi kesalahan Reed-Solomon, yang ditawarkan dalam empat tingkat. Tingkat L memulihkan sekitar 7 persen codeword, M sekitar 15 persen, Q sekitar 25 persen, dan H sekitar 30 persen. Koreksi yang lebih tinggi tidak gratis. Codeword pemulihan memakan kapasitas modul, sehingga untuk jumlah data yang tetap, tingkat yang lebih tinggi memaksa simbol menjadi lebih rapat atau lebih besar secara fisik

Pertukaran tersebut adalah pertanyaan tentang lingkungan tempat simbol tersebut akan berada. Dokumen digital bersih yang hanya akan dipindai dari layar dapat berada di tingkat L dan tetap ringkas. Label yang akan dicetak, dipegang, tergores, dan mungkin sebagian tertutup lakban memerlukan Q atau H, karena redundansi ekstra adalah apa yang memungkinkan dekoder merekonstruksi payload dari simbol yang tidak lagi murni. DrawQRCode mengambil posisi dan SymbolSize yang menetapkan lebar dan tinggi gambar, ditambah nilai EncodeOptions yang memilih mode data (0 untuk otomatis, atau varian numerik, alfanumerik, ISO-8859-1, dan UTF-8) serta nilai DrawOptions untuk orientasi

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;

Tingkat koreksi itu sendiri dipilih oleh enkoder agar sesuai dengan data ke dalam simbol yang Anda minta. Jika Anda memerlukan jaminan tingkat tinggi untuk lingkungan yang keras, ukurlah simbol dengan longgar sehingga enkoder memiliki anggaran modul untuk dihabiskan pada redundansi daripada dipaksa turun agar muat

PDF417 untuk ID dan label pengiriman

PDF417 adalah simbol linier bertumpuk. Setiap baris adalah barcode linier pendek, dan baris-baris tersebut menumpuk membentuk blok, itulah sebabnya ia muncul di SIM, kartu pas masuk pesawat (boarding pass), dan label pengiriman kurir di mana strip data yang lebih lebar harus berada dalam jejak persegi panjang. Koreksi kesalahannya berjalan pada skala 0 hingga 8. Setiap langkah kira-kira melipatgandakan jumlah codeword koreksi, sehingga tingkat 5 membawa redundansi yang jauh lebih banyak daripada tingkat 1, dengan konsekuensi lebih banyak codeword di halaman

Bentuk blok PDF417 dapat disesuaikan, dan itu penting karena label memiliki area tetap untuk diisi. DrawPDF417SymbolEx mengekspos kontrol yang tidak dimiliki oleh pemanggilan dasar. FixedColumns dan FixedRows menyematkan jumlah kolom data dan jumlah baris, dengan 0 berarti membiarkan enkoder yang memutuskan. ErrorLevel mengambil nilai -1 untuk otomatis atau nilai eksplisit 0 hingga 8. ModuleSize adalah lebar elemen tersempit dalam unit pengukuran saat ini, dan HeightWidthRatio menetapkan seberapa tinggi setiap modul relatif terhadap lebarnya, yang merupakan cara Anda membuat blok menjadi pendek dan lebar atau tinggi dan sempit agar sesuai dengan ruang yang Anda miliki

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

Menetapkan kolom adalah opsi umum pada templat label. Jumlah kolom yang konstan memberikan lebar blok yang dapat diprediksi, sehingga tata letak di sekitarnya tidak bergeser saat panjang payload terenkode berubah dari satu dokumen ke dokumen berikutnya, sementara enkoder menambahkan baris ke bawah untuk menyerap perbedaannya

DataMatrix untuk tanda kecil

DataMatrix adalah simbol yang dicari ketika tanda harus berukuran kecil. Ini adalah kisi 2D kompak yang menggunakan ECC 200, skema Reed-Solomon modern, dan tetap dapat dibaca pada ukuran di mana simbol QR dari data yang sama akan terlihat canggung. Hal itu menjadikannya pilihan standar untuk penandaan komponen langsung (direct part marking), komponen elektronik kecil, dan label logistik yang padat

DrawDataMatrixSymbol mengambil ModuleSize untuk pitch titik, Encoding bernilai 1 untuk ASCII, dan SymbolSize berupa 0 untuk otomatis atau salah satu dimensi persegi dan persegi panjang standar, dari 10x10 hingga 132x132. Parameter Options menggabungkan orientasi dengan lebar zona sunyi (quiet-zone), di mana penambahan 100 hingga 400 menetapkan batas putih modul satu hingga empat. Zona sunyi bukanlah hiasan. Dekoder memerlukan batas yang jelas tersebut untuk menemukan pola pencari (finder pattern) simbol, dan simbol yang berdesakan dengan tinta lain adalah simbol yang gagal diperoleh informasinya

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

Di mana barcode 1D masih berkuasa

Simbol dua dimensi menarik banyak perhatian, tetapi barcode linier masih menguasai sebagian besar bidang ritel dan logistik, dan alasannya adalah basis terpasang pemindai laser yang membaca satu sapuan saja. Code128 adalah pekerja keras untuk data alfanumerik, dan efisiensinya berasal dari tiga set karakter. Set A mencakup karakter kontrol dan huruf besar, set B mencakup rentang penuh ASCII yang dapat dicetak, dan set C adalah yang penting untuk angka. Subset C mengodekan sepasang digit dalam satu karakter simbol tunggal, sehingga rangkaian data numerik mengambil setengah dari karakter simbol yang dibutuhkannya pada set A atau B. Itu adalah cara paling ringkas untuk menuliskan barcode numerik yang panjang, dan implementasi Code128 PDFlibPas menggabungkan set B dan C secara otomatis untuk mencapainya

GS1-128, standar yang sebelumnya bernama EAN-128, dibangun di atas Code128 dengan membawa Application Identifier, awalan dalam tanda kurung yang memberi tahu sistem penerima apakah digit berikutnya merupakan nomor seri, kode batch, atau tanggal kedaluwarsa. Strukturnya ditandai oleh FNC1, karakter non-data khusus yang menandai simbol sebagai terenkode-GS1 dan memisahkan kolom dengan panjang variabel. Di PDFlibPas Anda menggambar simbol GS1-128 dengan DrawBarcode menggunakan tipe Code128 dan penanda literal [FNC1] yang ditempatkan di string data di mana setiap pengidentifikasi aplikasi dimulai

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;

Untuk surat, USPS Intelligent Mail, juga disebut OneCode, mengodekan data rute dan pelacakan dalam satu barcode termodulasi-tinggi untuk otomatisasi pos. DrawIntelligentMailBarcode mengambil geometri eksplisit untuk lebar garis (bar width), tinggi garis penuh, tinggi pelacak (tracker height), dan lebar ruang, dengan data yang disediakan sebagai string 20, 25, 29, atau 31 digit saja. Tinggi garis dan pelacak yang eksplisit ada karena simbol membawa informasi tentang apakah setiap garis merupakan garis penuh, ascender, atau descender, dan pembaca pos bergantung pada tinggi tersebut yang harus sesuai spesifikasi

Menggambar ke dalam halaman dan mengukur untuk tata letak

Setiap panggilan yang ditampilkan di sini menggambar ke dalam konten halaman yang saat ini dipilih, permukaan yang sama yang menerima teks dan gambar Anda, sehingga barcode diproduksi sebagai bagian dari pembuatan dokumen normal, bukan diimpor sebagai aset terpisah. Karena simbol adalah konten vektor, data yang mereka kodekan dan geometri yang mereka tempati sama-sama diketahui pada waktu penggambaran, yang memungkinkan Anda menempatkannya secara deterministik

Tata letak untuk keluarga linier mendapat manfaat dari pengukuran terlebih dahulu. GetBarcodeWidth mengembalikan total lebar gambar barcode untuk lebar garis sempit (narrow-bar width) dan tipe barcode yang diberikan, sehingga Anda dapat memesan ruang horizontal yang tepat sebelum Anda melakukan penggambaran, daripada menebak-nebak dan menemukan tumpang tindih setelah halaman dibuat. Simbol 2D lebih mudah ditempatkan karena Anda menetapkan ukuran gambarnya secara langsung melalui SymbolSize atau ModuleSize, dan simbol tersebut mengisi jejak tersebut. Apa pun pilihannya, disiplinnya sama. Tentukan ukuran fisik dari lingkungan pemindaian, konfirmasikan bahwa simbol tersebut cocok dengan slot yang Anda miliki, dan biarkan geometri vektor menjaga setiap tepi tetap tajam dari pratinjau layar hingga cetakan akhir

Untuk alur kerja pembuatan halaman yang lebih luas tempat barcode ini masuk, teknik dalam artikel kami tentang ekstraksi teks, gambar, dan font mencakup pembacaan konten kembali keluar dari PDF, dan panduan untuk penggabungan dan pemisahan PDF besar dengan akses langsung menunjukkan cara menyusun dokumen bervolume tinggi secara efisien. Keduanya berpasangan secara alami dengan API penggambaran yang dijelaskan di sini, yang dikirimkan sebagai bagian dari Delphi PDF Library untuk Delphi dan C++Builder bersama dengan API teks, grafis, formulir, dan tanda tangan yang dibahas di bagian lain pada blog ini