ถ้าคุณส่งสินค้าจริง สุดท้ายคุณต้องพิมพ์ GS1-128 ที่เครื่องสแกนจริงในคลังสินค้าจริงอ่านได้ ภายใต้แสงและระยะจริง เรื่องนี้ดูเหมือนรายละเอียดเล็ก ๆ แต่ใน PDF generation มันเป็นหนึ่งในจุดล้มเหลวที่สร้างปัญหามากที่สุด
บทความนี้อธิบายว่า “ความแม่นยำ 0.1 mm” ของ GS1-128 หมายถึงอะไร ทำไม renderer ที่อิง HTML/CSS จึงรักษาเรขาคณิตนี้ได้ยาก และกฎใดช่วยลดการถูกปฏิเสธโดย scanner ของ DHL, FedEx, USPS และ Amazon inbound
Barcode precision หมายถึงอะไร
GS1-128 (เดิม UCC/EAN-128) เข้ารหัสข้อมูลด้วย ความกว้างของแท่งและช่องว่าง ในสัดส่วนที่แน่นอน หน่วยพื้นฐานคือ X-dimension หรือความกว้างของแท่ง/ช่องที่แคบที่สุด ความกว้างอื่นคือหลายเท่าของ X
Scanner วัดความกว้างสัมพัทธ์ ไม่ได้ดูแค่ว่าภาพคมชัดหรือไม่ ปัญหาที่พบใน production บ่อยที่สุดคือ:
- X-dimension ไม่สม่ำเสมอใน symbol เดียวกัน: renderer ทำ sub-pixel rounding ต่างกันระหว่างแท่งที่ติดกัน
- ความยาวรวมหรือ scaling ผิด: render symbol แล้วถูกย่อ/ขยาย ทำให้ X-dimension ต่ำกว่าค่า GS1 minimum ซึ่งโดยมากคือ 0.495 mm ที่ 1.0×
อาการมักหลอกตา: sample หนึ่งใบอ่านได้ แต่ batch จริงมี rejection 1 ใน 30 เครื่อง dev scanner มักให้อภัยมากกว่า scanner ในคลัง
กฎ 0.1 mm
precision ที่สำคัญคือ ความยาวรวมของ barcode ต้องอยู่ใน tolerance 0.1 mm จาก target ของ spec ไม่ได้หมายความว่าแต่ละแท่งกว้าง 0.1 mm; โดยทั่วไปแท่งกว้าง 0.495 mm หรือมากกว่า
สำหรับ GS1-128 ที่มีตัวเลข 18 หลัก:
- Symbol มีแท่งและช่องว่างประมาณ 120 ส่วน
- ความยาวรวมที่ 1.0× ประมาณ 58 mm
- tolerance 0.1 mm เท่ากับความแม่นยำรวม ~0.17%
- budget ต่อแท่งประมาณ 0.001 mm
ดังนั้นแท่งที่ควรเป็น 7.4 px แต่ถูกวาดเป็น 7 px อาจทำให้ scan fail ได้ เพราะ error สะสมตลอด symbol
ทำไม HTML/CSS ถึงยาก
วิธีที่พบบ่อยคือสร้าง SVG จากข้อมูล GS1-128, ฝังใน HTML แล้ว render PDF ด้วย Puppeteer หรือ Prince ทุกขั้นตอนมีโอกาสขยับ geometry
1. Browser rasterisation ทำ rounding
แม้แต่ SVG ใน HTML ก็ผ่าน painter ของ browser ต้องมี shape-rendering="crispEdges", boundary ที่ตรงกับ integer pixel และความสัมพันธ์ DPI กับ bar width ที่สะอาด
2. CSS scale ได้แบบเงียบ ๆ
transform: scale(0.95) ที่เคยเพิ่มเพื่อแก้ layout อื่น จะบิด barcode ทุกตัวบนหน้า PDF ดูปกติ แต่ scanner วัดไม่ตรง
3. PDF emitter quantize coordinates
บาง engine snap coordinates ไปยัง internal grid ตอนเขียน PDF ผลลัพธ์ดูเกือบถูก แต่ error สะสม
4. Font Code 128 เสี่ยงกว่า
Font เป็น vector ก็จริง แต่ font hinting ปรับความกว้างเล็ก ๆ เพื่อให้มนุษย์อ่านสบาย นั่นไม่ใช่สิ่งที่ scanner ต้องการ
Structured rendering approach
gPdf คำนวณ pattern ของแท่งและช่องว่างจาก GS1-128 specification แล้วเขียน PDF vector primitives โดยตรง: ไม่มี HTML, ไม่มี SVG translation, ไม่มี font hinting
{
"pages": [{
"size": "label_100_150",
"elements": [
{
"type": "barcode",
"format": "gs1128",
"content": "(00)123456789012345678",
"x": 4,
"y": 8,
"width": 58.0,
"height": 18.0,
"barcode_text": { "enabled": true, "position": "bottom" }
}
]
}]
}
ใน element barcode, width คือ ความยาวรวมของ symbol หน่วย mm ซึ่งวัดได้ด้วย caliper บน label ที่พิมพ์แล้ว เมื่อใช้ width: 58.0:
- Renderer คำนวณ X-dimension จาก target length และจำนวน bar
- ทุก bar ถูกวาดด้วย X-dimension เดียวกัน
- ความกว้างถูกเขียนลง PDF เป็น floating-point coordinates
- ไม่มี CSS pixel rounding, layout scaling หรือ font hinting
ถ้า printer ไม่เพิ่ม scaling เอง ความยาวรวมจะอยู่ภายใน 0.1 mm จาก target
ควรพิมพ์อย่างไร
กฎ 1: ระบุความยาวรวม
width คือ control ที่ถูกต้องเพราะวัดได้ หากระบุแค่ X-dimension ความยาว symbol จะเปลี่ยนตามข้อมูลที่ encode
- Shipping label 4×6 in: กว้าง 100 mm; GS1-128 มักอยู่ที่ ~58–72 mm
- Compliance label 4×4 in: ~45–58 mm
- Carton label 2×1 in (Amazon UPC): ไม่ใช่ GS1-128; ใช้ UPC-A
กฎ 2: ต้องมี quiet zones
GS1-128 ต้องการ quiet zones ≥ 10X ทั้งสองด้าน ที่ 1.0× (X = 0.495 mm) คือพื้นที่ขาวอย่างน้อย 4.95 mm การวาง barcode ที่ x: 0 อาจทำให้ scanner หา edge เริ่มต้นไม่เจอ gPdf reserve พื้นที่นี้อัตโนมัติ
กฎ 3: ทดสอบกับ scanner เป้าหมาย
กล้องมือถือให้อภัยมากกว่า Honeywell หรือ Zebra industrial scanner พิมพ์ 50 labels ด้วย production printer ที่ความเร็วจริง แล้ว scan ด้วยอุปกรณ์จริง ถ้า read rate ต่ำกว่า 99% ให้ตรวจ X-dimension consistency
ความจริงของหลาย format
Label มักไม่ได้มีแค่ GS1-128:
| Symbol | ใช้สำหรับ | Spec source |
|---|---|---|
| GS1-128 | Logistics units, GTIN + serial + lot | GS1 General Specifications |
| QR with FNC1 | Ecommerce ที่สแกนด้วย mobile | ISO/IEC 18004 |
| Data Matrix | Pharmaceutical (DSCSA / EU FMD) | ISO/IEC 16022 |
| PDF417 | Drivers’ licences, boarding passes | ISO/IEC 15438 |
| Aztec | Transport tickets | ISO/IEC 24778 |
| MaxiCode | UPS specifically | ISO/IEC 16023 |
Renderer ที่รองรับแค่ GS1-128 จะทำให้ต้องใช้ tool ที่สองในภายหลัง Workflow ด้าน logistics มักต้องใช้มากกว่าหนึ่ง format
ตรวจ scanner rejection ใน production
- เก็บ label ที่ fail จริง ไม่ใช่ดูแค่ metric
- วัดด้วย caliper ทั้งความยาวรวมและ X-dimension
- ตรวจ human-readable text ใต้ barcode
- วัด quiet zones ทั้งสองด้าน
- ลอง scanner model อื่น
- เทียบกับ known-good reference label
TL;DR
GS1-128 precision ไม่ใช่การพิมพ์แท่งให้บางที่สุด แต่คือการรักษา X-dimension ให้สม่ำเสมอตลอด symbol HTML/CSS เพิ่ม sub-pixel drift หลายจุด ส่วน renderer ที่เขียน PDF vector primitives โดยตรงจะเลี่ยงแหล่ง drift เหล่านี้
ถ้า PDF stack ปัจจุบันมี scanner rejection 1–5% ให้เริ่มตรวจที่นี่ Playground สามารถ render GS1-128 ด้วย width ตาม label spec ของคุณ แล้วนำไปพิมพ์และวัดด้วย caliper