Si envía productos físicos, tarde o temprano tendrá que imprimir un código de barras GS1-128 que un escáner portátil real lea con luz real de almacén y a una distancia real. Suena aburrido. En generación de PDF, de hecho, es una de las fuentes de fallo más ruidosas.
Este artículo explica qué significa realmente “0,1 mm de precisión” en un código GS1-128, por qué los renderizadores basados en HTML/CSS tienen dificultades para entregarla y qué pequeño conjunto de reglas de diseño hace que un código de barras se imprima correctamente a la primera en DHL, FedEx, USPS y también en escáneres de recepción de Amazon.
Qué significa “precisión” en un código de barras
GS1-128 (antes UCC/EAN-128) codifica datos mediante anchos de barras y espacios con proporciones estrictas. La unidad atómica es la dimensión X: el ancho de la barra o espacio más estrecho. Todo lo demás son múltiplos de X (1X, 2X, 3X, 4X en patrones internos de Code 128).
Los escáneres decodifican midiendo anchos relativos. Si los anchos impresos se desvían, la decodificación falla.
Los dos fallos más comunes en producción:
- Dimensión X inconsistente dentro del símbolo: el renderizador redondea subpíxeles de forma distinta para barras vecinas. Las tres primeras barras salen de 8 px y luego aparece una de 7 px en medio. El escáner ve un patrón inconsistente.
- Longitud total o escalado incorrectos: el renderizador escala el símbolo después de generarlo y distorsiona la dimensión X por debajo del mínimo GS1 (normalmente 0,495 mm con factor de magnificación 1,0×).
Ambos se manifiestan igual: el escáner pita una vez en una muestra suelta, pero en un lote de producción aparece una tasa de rechazo de 1 entre 30. No se detecta en QA porque el escáner de desarrollo suele perdonar más que el escáner del almacén.
La regla de 0,1 mm
La precisión relevante es la longitud total del código de barras dentro de una tolerancia de 0,1 mm respecto al objetivo de la especificación. No significa que cada barra mida 0,1 mm; las barras normalmente miden 0,495 mm o más. El límite de 0,1 mm aplica a la exactitud dimensional acumulada del símbolo completo.
En un GS1-128 típico con 18 caracteres numéricos:
- El símbolo contiene unas 120 barras y espacios
- Longitud total con magnificación 1,0×: unos 58 mm
- Tolerancia total de 0,1 mm = aproximadamente 0,17% de exactitud en toda la longitud
- Eso deja un presupuesto de consistencia de unos 0,001 mm por barra, muy por debajo del ancho de cualquier barra individual
Por eso es fatal que el renderizador dibuje una barra de 7 px donde debería ser de 7,4 px. El redondeo subpíxel se acumula a lo largo de 120 barras, y la tolerancia de 0,1 mm se rompe en algún punto entre la barra 50 y la 80.
Por qué HTML/CSS lo pone difícil
La ruta en la que tropiezan muchos equipos es esta: codificar los datos GS1-128 como una cadena, generar un SVG (o peor, barras individuales con <div>), incrustarlo en HTML y convertir la página a PDF con Puppeteer o Prince.
Cada eslabón introduce deriva:
1. El navegador redondea al rasterizar
Incluso un SVG dentro de HTML se redondea a subpíxeles en el pintor del navegador, salvo que shape-rendering="crispEdges" esté definido, el contenedor circundante caiga en un límite de píxel entero y el DPI del PDF multiplique limpiamente los anchos de barra. Tres restricciones, todas fáciles de violar por accidente.
2. La composición CSS puede escalar
Un transform: scale(0.95) en su hoja de estilos — añadido seis meses antes para arreglar otro problema de composición — distorsiona silenciosamente todos los códigos de barras de la página. No hay aviso. El PDF se ve bien. El escáner no.
3. El emisor PDF cuantiza coordenadas
Cuando el navegador serializa a PDF, convierte el resultado pintado en operadores de dibujo PDF. Algunos emisores (notablemente el de Chromium) ajustan a una rejilla interna fija del PDF. Para un código de barras SVG situado en coordenadas que no se alinean con esa rejilla, obtiene una salida cuantizada que está casi bien pero acumula error.
4. Las fuentes de Code 128 son peor opción
Algunos equipos usan una fuente Code 128 ({ font: "Code128" }), escriben los datos y esperan lo mejor. Las fuentes son vectoriales y, en teoría, escalan; pero el ajuste óptico de la fuente (hinting) en tamaños pequeños desplaza anchos para mejorar la lectura humana. Ese objetivo es exactamente lo contrario de lo que necesita un escáner.
El enfoque de renderizado estructurado
gPdf toma los datos, calcula el patrón de barras y espacios desde la especificación GS1-128 y emite primitivas vectoriales PDF directamente: sin HTML, sin traducción SVG, sin ajuste óptico de fuentes.
{
"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" }
}
]
}]
}
En un elemento barcode, width es la longitud total del símbolo en mm, lo que mediría con un calibre sobre la etiqueta impresa. Ese es el control correcto, y esto es lo que garantiza width: 58.0:
- El renderizador calcula la dimensión X dividiendo la longitud objetivo por el número de barras del símbolo, que queda determinado por los datos.
- Dibuja cada barra con exactamente la misma dimensión X.
- Escribe esos anchos en el PDF como coordenadas de punto flotante (unidad PDF = 1/72 de pulgada, más fina de lo necesario a resolución de escaneo).
- No hay ajuste óptico de fuentes, redondeo de píxeles CSS ni distorsión por una pasada de composición.
El resultado mantiene la longitud total dentro de 0,1 mm del objetivo solicitado en toda impresora que no aplique su propio escalado (la mayoría no lo hace por defecto).
Qué conviene imprimir
Tres reglas evitan el 95% de los fallos de escáner en producción.
Regla 1: especifique longitud total, no dimensión X
El campo width es el control correcto porque se puede medir: puede tomar un calibre, medir una etiqueta impresa y verificarlo directamente. Si especifica la dimensión X, la longitud del símbolo depende de la longitud de los datos codificados, lo que hace más difícil el QA de etiquetas (SKU distinto = ancho de código distinto).
- Etiqueta de envío 4×6 in: 100 mm de ancho; GS1-128 suele quedar en unos 58-72 mm
- Etiqueta de conformidad 4×4 in: unos 45-58 mm
- Etiqueta de caja 2×1 in (Amazon UPC): no es territorio GS1-128; use UPC-A
Regla 2: zonas silenciosas siempre
GS1-128 necesita zonas silenciosas ≥ 10X a ambos lados: espacio blanco vacío que el escáner usa para encontrar los bordes del símbolo. A 1,0× (X = 0,495 mm), son al menos 4,95 mm de espacio limpio.
El fallo clásico: el desarrollador coloca el código en x: 0 para encajarlo junto a otros elementos de la etiqueta, y el escáner no puede encontrar el inicio. El renderizador debería reservar zonas silenciosas automáticamente (gPdf lo hace); compruebe el suyo.
Regla 3: pruebe con el escáner objetivo, no con el de desarrollo
La cámara del móvil perdona más que un Honeywell o Zebra industrial. El camino estándar de QA:
- Imprima 50 etiquetas en la impresora real de producción, a velocidad de producción.
- Páselas por el tipo de escáner real, a la velocidad real de la cinta.
- Una tasa de lectura < 99% significa que algo está mal, normalmente la consistencia de la dimensión X.
No envíe a socios logísticos basándose en “escaneaba bien con la cámara de mi MacBook”.
Realidad multiformato
Una etiqueta rara vez usa solo GS1-128:
| Símbolo | Uso | Fuente de especificación |
|---|---|---|
| GS1-128 | Unidades logísticas, GTIN + serie + lote | GS1 General Specifications |
| QR con FNC1 | Comercio electrónico escaneable desde móvil | ISO/IEC 18004 |
| Data Matrix | Farmacéutica (DSCSA / EU FMD) | ISO/IEC 16022 |
| PDF417 | Permisos de conducir, tarjetas de embarque | ISO/IEC 15438 |
| Aztec | Billetes de transporte | ISO/IEC 24778 |
| MaxiCode | UPS específicamente | ISO/IEC 16023 |
Un renderizador que solo cubre GS1-128 terminará empujándole a una segunda herramienta. Agrupamos los seis formatos en un único renderizador porque los flujos de envío y logística casi siempre necesitan al menos dos.
Cómo diagnosticar rechazos en producción
Si ya está en producción con un problema de rechazo de escáner, el orden de diagnóstico es:
- Muestree las etiquetas fallidas: no se base en métricas agregadas. Obtenga la etiqueta física real que falló.
- Mida con calibre: longitud total y dimensión X. Si no están dentro de la tolerancia de la especificación, ese es el bug.
- Revise el texto legible bajo el símbolo; los escáneres que fallan con las barras suelen probar una ruta alternativa de OCR. Si ambos fallan, el símbolo está realmente mal formado.
- Verifique zonas silenciosas: mida el espacio blanco a ambos lados. Si algo se imprimió demasiado cerca (un logotipo, una línea divisoria, otro código de barras), ese es el problema.
- Pruebe otro modelo de escáner: algunos escáneres tienen particularidades de firmware. Si el modelo A lee la etiqueta y el modelo B no, el problema es de interoperabilidad, no necesariamente de su renderizador.
- Compare contra una etiqueta de referencia conocida como correcta: los proveedores publican imágenes de referencia con especificaciones exactas. Si la suya no coincide visualmente, retroceda desde la diferencia.
TL;DR
La precisión GS1-128 no va de lo finas que pueda imprimir las barras: va de mantener la dimensión X constante en todo el símbolo dentro de una fracción de milímetro. Los renderizadores basados en HTML/CSS introducen deriva subpíxel en varias etapas del proceso; los renderizadores estructurados que emiten primitivas vectoriales PDF directamente omiten por completo esas fuentes de deriva.
Si ve una tasa de rechazo de escáner de 1-5% con su pila PDF actual, esa es la señal. El Playground puede renderizar una muestra GS1-128 con el campo width fijado exactamente a la especificación de su etiqueta: imprima la salida y mídala con un calibre.