Tiempo estimado de lectura: 10 minutos | Tecnología |
Basta con sacar el teléfono móvil, enfocar con la cámara una pequeña superficie cuadrada llena de diminutos cuadrados blancos y negros, y permitir que una interfaz invisible traduzca al instante esa geometría abstracta en una página web, un menú digital, una tarjeta de embarque o una transacción financiera. Este gesto, hoy completamente cotidiano, encierra una sofisticada combinación de matemáticas aplicadas, ingeniería industrial y teoría de la información.
Lo que a simple vista parece un mero estampado decorativo es, en realidad, una de las herramientas de codificación de datos más eficientes y resistentes jamás diseñadas. Para comprender cómo un dispositivo electrónico es capaz de extraer significado de un mosaico monocromo, es necesario retroceder en el tiempo hasta una fábrica de automóviles en Japón y adentrarse en los intrincados mecanismos de la corrección de errores y el álgebra lineal.
Los orígenes de un código que lo abarca todo
La historia de esta tecnología no comenzó en el mundo del marketing ni en el ecosistema digital de los teléfonos inteligentes, sino en el suelo industrial de la industria automovilística a principios de la década de 1990. En aquel entonces, el código de barras lineal unidimensional, inventado décadas antes, dominaba el control de inventarios. Sin embargo, su capacidad de almacenamiento era extremadamente limitada: apenas albergaba unas pocas decenas de caracteres alfanuméricos, lo equivalente a una breve referencia numérica o un precio. A medida que las cadenas de montaje de automóviles se volvieron más complejas y diversificadas, los operarios necesitaban escanear múltiples códigos de barras en una misma pieza para registrar su trazabilidad, componentes y destinos, lo que ralentizaba los procesos de producción y generaba errores frecuentes.
Ante esta frustración operativa, una filial de la multinacional japonesa Toyota llamada Denso Wave decidió poner en marcha un proyecto de investigación en 1994 para desarrollar un nuevo tipo de código que superara estas restricciones físicas. El equipo encargado de la tarea, liderado por el ingeniero Masahiro Hara, se propuso un objetivo ambicioso: diseñar un código capaz de almacenar una cantidad de información exponencialmente mayor, que pudiera leerse a una velocidad vertiginosa y que fuera omnidireccional, es decir, escaneable desde cualquier ángulo sin importar la orientación del lector.
La solución adoptada consistió en abandonar el formato lineal de barras verticales y apostar por una matriz bidimensional basada en celdas cuadradas, denominadas módulos. Tras meses de pruebas analizando la proporción de áreas blancas y negras en documentos impresos, periódicos y revistas para evitar interferencias visuales, el equipo determinó los patrones geométricos exactos que garantizarían una lectura fiable. Lejos de buscar un beneficio económico exclusivo, Denso Wave decidió liberar la patente del código para que cualquier industria pudiera utilizarlo libremente, un movimiento estratégico que sembró el terreno para su masificación global décadas más tarde.
La arquitectura invisible de una matriz de puntos
Para que una cámara fotográfica o un escáner óptico interpreten correctamente un código de este tipo, la matriz no es un simple conjunto aleatorio de puntos, sino una estructura altamente reglamentada donde cada zona cumple una función específica. Si se examina con detenimiento cualquier matriz estándar, es posible identificar elementos geométricos fijos que actúan como puntos de referencia fundamentales para el software de lectura.
Los patrones de detección y orientación
El rasgo más característico de la matriz son los tres grandes cuadrados concéntricos situados en tres de sus esquinas, habitualmente la superior izquierda, la superior derecha y la inferior izquierda. Estos elementos reciben el nombre de patrones de detección de posición o finder patterns. Su diseño incluye una proporción geométrica muy precisa de franjas negras y blancas en una relación exacta, lo que permite al software del dispositivo identificar inmediatamente la presencia del código en el encuadre, sin importar si la cámara está ladeada, invertida o alejada. La ausencia de este cuarto patrón en la esquina inferior derecha no es un error de diseño, sino una estrategia deliberada que permite al algoritmo determinar de inmediato la orientación espacial de la matriz y enderezar la perspectiva de la imagen capturada antes de proceder al análisis de los datos.
Elementos auxiliares de calibración
Además de las esquinas de posicionamiento, la matriz incorpora otros componentes estructurales esenciales:
- Patrones de alineación: Presentes en las versiones más grandes del código, son pequeños cuadrados concéntricos situados en el interior de la matriz que ayudan a corregir posibles distorsiones ópticas causadas por superficies curvas o arrugadas.
- Líneas de temporización: Franjas alternas de módulos blancos y negros dispuestas entre los patrones de posicionamiento que permiten al escáner calcular la densidad exacta de la cuadrícula y determinar el tamaño de cada celda individual.
- Área de formato y versión: Pequeñas zonas situadas junto a los detectores que informan al lector sobre el nivel de corrección de errores aplicado y el tamaño de la matriz.
Cómo se transforma la información en píxeles
El proceso mediante el cual un mensaje de texto, una dirección de internet o una coordenada geográfica se convierte en una matriz de puntos negros y blancos sigue un protocolo de codificación riguroso. En primer lugar, la información original se traduce a un formato binario de ceros y unos según diferentes modos de codificación disponibles, tales como numérico, alfanumérico, binario de 8 bits o kanji, optimizando el espacio según el tipo de caracteres empleados.
Una vez convertidos los datos en una secuencia binaria, el sistema aplica un algoritmo matemático avanzado de corrección de errores, comúnmente basado en la codificación de Reed-Solomon. Este paso es crucial porque añade redundancia matemática al mensaje original, generando bloques adicionales de datos que permitirán reconstruir la información incluso si el código físico sufre daños, manchas o roturas parciales. A continuación, la secuencia binaria resultante se distribuye por la matriz siguiendo un recorrido en zigzag estandarizado que evita aglomeraciones de un solo color.
Finalmente, antes de generar la imagen definitiva, el algoritmo aplica un patrón de enmascaramiento predefinido. Este paso consiste en invertir los colores de determinados módulos siguiendo una fórmula matemática específica para evitar que aparezcan grandes áreas vacías o demasiado oscuras que puedan confundir al sistema óptico del lector. Se añade un indicador sobre qué máscara se ha utilizado para que el dispositivo receptor sepa exactamente cómo deshacer la operación al escanearlo.
El proceso inverso: de la cámara a la pantalla
Cuando un usuario enfoca un código con su teléfono, el dispositivo ejecuta una secuencia informática compleja en fracciones de segundo. El sensor de la cámara captura una imagen bidimensional en color. El software procesa la imagen convirtiéndola a escala de grises y buscando los tres característicos cuadrados de las esquinas. Al detectarlos, el procesador calcula la matriz geométrica, corrige la perspectiva y enderezando la imagen aunque haya sido tomada desde un ángulo oblicuo.
Una vez aislada y normalizada la matriz, el software lee los módulos celda por celda según la retícula de temporización. Identifica la máscara aplicada, revierte la inversión de colores, extrae la secuencia binaria y comprueba los bloques de redundancia mediante el algoritmo Reed-Solomon para verificar que no existan errores de lectura. Si algún sector del código está borroso o deteriorado, el sistema corrige los datos faltantes en tiempo real antes de ensamblar el mensaje final y ejecutar la acción asociada, como abrir un navegador web o mostrar un texto.
Capacidad, versiones y niveles de corrección
La versatilidad de esta tecnología radica en su escalabilidad. No existe un único diseño estático, sino una familia estructurada en diferentes versiones que van desde la versión 1, compuesta por una retícula de veintiún por veintiún módulos, hasta la versión 40, que alcanza una descomunal matriz de ciento setenta y siete por ciento setenta y siete módulos, ofreciendo una densidad de información muy elevada.
La capacidad de almacenamiento varía drásticamente según la versión seleccionada y el tipo de datos que se introduzcan, pudiendo albergar desde unas pocas decenas de caracteres hasta un máximo teórico de algo más de siete mil caracteres numéricos o cerca de tres mil bytes de datos binarios en su formato más complejo. Sin embargo, en la práctica cotidiana se suelen utilizar versiones intermedias para evitar que los módulos se vuelvan demasiado pequeños y difíciles de escanear por cámaras de dispositivos móviles estándar.
Un aspecto técnico fundamental que define la fiabilidad de estos códigos es el nivel de corrección de errores implementado durante su generación. Existen cuatro niveles estandarizados que determinan cuánta superficie del código puede quedar ilegible sin que se pierda la información contenida:
- Nivel L: Permite recuperar hasta un 7 por ciento de los datos dañados. Es útil cuando se requiere la máxima capacidad de almacenamiento y el soporte físico es limpio y estable.
- Nivel M: Recupera hasta un 15 por ciento de información dañada. Es el estándar más habitual en soportes impresos comerciales e industriales.
- Nivel Q: Capaz de restaurar hasta un 25 por ciento de datos perdidos, adecuado para entornos donde el código puede sufrir desgaste moderado.
- Nivel H: Ofrece una tolerancia de hasta un 30 por ciento de daño. Se emplea en entornos industriales extremos, maquinaria pesada o aplicaciones donde el código se expone a suciedad, grasa o arañazos constantes.
Esta robustez explica por qué es posible imprimir logotipos en el centro de un código o perforar parte de su superficie sin que deje de funcionar, siempre que los daños no superen el porcentaje de redundancia establecido y los patrones de posicionamiento de las esquinas permanezcan intactos.
Crea tu propio código QR, ¿te atreves?
Es posible crear un código QR manualmente, pero no consiste simplemente en dibujar cuadrados al azar. El código QR no es un dibujo decorativo, sino una matriz de datos protegida con cálculos matemáticos y debemos realizar a mano todo el proceso matemático de codificación. Para que el proceso sea comprensible, podemos usar un ejemplo muy corto: crear un código QR que contenga la palabra HOLA.
Para hacerlo desde cero habría que
- Elegir un contenido muy corto, «HOLA».
- Escoger el modo de codificación: numérico, alfanumérico o binario.
- Convertir el texto en una secuencia de bits.
- Añadir los bits que indican el tipo de codificación y la longitud del mensaje.
- Completar la secuencia con bits de relleno hasta alcanzar el tamaño de la versión elegida.
- Calcular los códigos de corrección de errores mediante el algoritmo Reed-Solomon.
- Dibujar una cuadrícula, normalmente de 21 × 21 módulos para un código QR de versión 1.
- Colocar los tres patrones cuadrados grandes de las esquinas.
- Añadir los patrones de sincronización y la zona reservada para la información de formato.
- Introducir los bits del mensaje siguiendo el recorrido obligatorio en zigzag.
- Aplicar una de las máscaras oficiales y escoger la que produzca un patrón más fácil de leer.
- Dibujar la información de formato y dejar un margen blanco alrededor.
- Escanear el resultado para comprobar si funciona.
Desarrollando el proceso
Un código QR está formado por pequeños cuadrados llamados módulos. Cada módulo puede ser blanco o negro, como si representara un 0 o un 1.
Convertir cada letra en un número
Los ordenadores asignan un número a cada letra mediante una tabla llamada ASCII:
Tabla ASCII
| Código | Hex. | Carácter | Código | Hex. | Carácter |
|---|---|---|---|---|---|
| 0 | 00 | NUL | 64 | 40 | @ |
| 1 | 01 | SOH | 65 | 41 | A |
| 2 | 02 | STX | 66 | 42 | B |
| 3 | 03 | ETX | 67 | 43 | C |
| 4 | 04 | EOT | 68 | 44 | D |
| 5 | 05 | ENQ | 69 | 45 | E |
| 6 | 06 | ACK | 70 | 46 | F |
| 7 | 07 | BEL | 71 | 47 | G |
| 8 | 08 | BS | 72 | 48 | H |
| 9 | 09 | TAB | 73 | 49 | I |
| 10 | 0A | LF | 74 | 4A | J |
| 11 | 0B | VT | 75 | 4B | K |
| 12 | 0C | FF | 76 | 4C | L |
| 13 | 0D | CR | 77 | 4D | M |
| 14 | 0E | SO | 78 | 4E | N |
| 15 | 0F | SI | 79 | 4F | O |
| 16 | 10 | DLE | 80 | 50 | P |
| 17 | 11 | DC1 | 81 | 51 | Q |
| 18 | 12 | DC2 | 82 | 52 | R |
| 19 | 13 | DC3 | 83 | 53 | S |
| 20 | 14 | DC4 | 84 | 54 | T |
| 21 | 15 | NAK | 85 | 55 | U |
| 22 | 16 | SYN | 86 | 56 | V |
| 23 | 17 | ETB | 87 | 57 | W |
| 24 | 18 | CAN | 88 | 58 | X |
| 25 | 19 | EM | 89 | 59 | Y |
| 26 | 1A | SUB | 90 | 5A | Z |
| 27 | 1B | ESC | 91 | 5B | [ |
| 28 | 1C | FS | 92 | 5C | \ |
| 29 | 1D | GS | 93 | 5D | ] |
| 30 | 1E | RS | 94 | 5E | ^ |
| 31 | 1F | US | 95 | 5F | _ |
| 32 | 20 | Espacio | 96 | 60 | ` |
| 33 | 21 | ! | 97 | 61 | a |
| 34 | 22 | « | 98 | 62 | b |
| 35 | 23 | # | 99 | 63 | c |
| 36 | 24 | $ | 100 | 64 | d |
| 37 | 25 | % | 101 | 65 | e |
| 38 | 26 | & | 102 | 66 | f |
| 39 | 27 | ‘ | 103 | 67 | g |
| 40 | 28 | ( | 104 | 68 | h |
| 41 | 29 | ) | 105 | 69 | i |
| 42 | 2A | * | 106 | 6A | j |
| 43 | 2B | + | 107 | 6B | k |
| 44 | 2C | , | 108 | 6C | l |
| 45 | 2D | – | 109 | 6D | m |
| 46 | 2E | . | 110 | 6E | n |
| 47 | 2F | / | 111 | 6F | o |
| 48 | 30 | 0 | 112 | 70 | p |
| 49 | 31 | 1 | 113 | 71 | q |
| 50 | 32 | 2 | 114 | 72 | r |
| 51 | 33 | 3 | 115 | 73 | s |
| 52 | 34 | 4 | 116 | 74 | t |
| 53 | 35 | 5 | 117 | 75 | u |
| 54 | 36 | 6 | 118 | 76 | v |
| 55 | 37 | 7 | 119 | 77 | w |
| 56 | 38 | 8 | 120 | 78 | x |
| 57 | 39 | 9 | 121 | 79 | y |
| 58 | 3A | : | 122 | 7A | z |
| 59 | 3B | ; | 123 | 7B | { |
| 60 | 3C | < | 124 | 7C | | |
| 61 | 3D | = | 125 | 7D | } |
| 62 | 3E | > | 126 | 7E | ~ |
| 63 | 3F | ? | 127 | 7F | DEL |
Así:
- H = 72
- O = 79
- L = 76
- A = 65
Convertir los números en ceros y unos
Para transformar un número decimal en un grupo de ocho bits, tienes que comprobar qué potencias de 2 caben dentro de ese número.
Las ocho posiciones son:
| Posición | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|
Cada posición solo puede tener un 1 o un 0:
- 1 significa que utilizamos ese número.
- 0 significa que no lo utilizamos.
Ejemplo: convertir H, cuyo valor ASCII es 72.
- ¿Cabe 128 en 72?
No. Escribimos 0.
- ¿Cabe 64 en 72?
Sí. Escribimos 1 y restamos:
72 − 64 = 8
- ¿Cabe 32 en 8?
No. Escribimos 0.
- ¿Cabe 16 en 8?
No. Escribimos 0.
- ¿Cabe 8 en 8?
Sí. Escribimos 1 y restamos:
8 − 8 = 0
- Ya no queda nada, así que escribimos 0 en las posiciones restantes.
El resultado es:
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
Por tanto:
72 = 01001000
La comprobación es:
64 + 8 = 72
Para la palabra «HOLA»:
- H = 72 = 01001000
- O = 79 = 01001111
- L = 76 = 01001100
- A = 65 = 01000001
Así que «HOLA» se transforma en:
01001000 01001111 01001100 01000001
Indicar que estamos usando texto
Un código QR no empieza directamente con las letras. Primero necesita dos datos:
- Qué tipo de información va a recibir.
- Cuántos caracteres tendrá esa información.
Es parecido a enviar una caja:
- Primero pones una etiqueta que dice qué hay dentro.
- Después escribes cuántos objetos contiene.
- Finalmente introduces los objetos.
- ¿Qué significa 0100?
Los cuatro bits 0100 son una etiqueta que, dentro del sistema QR, significa:
“Los datos están escritos en modo byte”.
El modo byte permite guardar letras, números, símbolos y caracteres variados. Por ejemplo:
- H
- O
- L
- A
- !
- @
- ?
- 7
Por eso, para nuestro ejemplo elegimos:
0100
Importante: 0100 no significa simplemente “texto”. Significa concretamente “voy a guardar los datos como bytes”.
- ¿Qué significa 00000100?
Después hay que decir cuántos caracteres contiene el mensaje.
La palabra HOLA tiene cuatro caracteres:
H – O – L – A
El número 4 escrito en ocho bits es:
00000100
¿Por qué?
Porque las ocho posiciones tienen estos valores:
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
Solo está activada la posición del número 4:
4 = 00000100
Por tanto:
- 0100 significa “voy a utilizar el modo byte”.
- 00000100 significa “mi mensaje tiene cuatro caracteres”.
Después de esas dos indicaciones ya se colocan los datos de las letras:
0100 00000100 01001000 01001111 01001100 01000001
La secuencia se lee así:
- 0100: modo byte.
- 00000100: cuatro caracteres.
- 01001000: H.
- 01001111: O.
- 01001100: L.
- 01000001: A.
Una aclaración importante: existen varios modos de codificación QR. Para la palabra «HOLA» también podría utilizarse el modo alfanumérico, que empieza por 0010 y utiliza otra forma de organizar los datos. En nuestro ejemplo usamos 0100 porque es más sencillo de entender: cada letra se convierte directamente en ocho bits.
Indicar el final del mensaje
Añadimos cuatro ceros para señalar que el mensaje ha terminado:
0000
La secuencia queda así:
0100 00000100 01001000 01001111 01001100 01000001 0000
Después se añaden ceros hasta completar grupos de ocho bits.
Separar la información en grupos de ocho
Los datos quedan organizados en estos grupos:
- 01000000
- 01000100
- 10000100
- 11110100
- 11000100
- 00010000
Cada grupo representa un módulo formado por ocho ceros y unos.
Añadir protección contra errores
Un código QR puede seguir funcionando aunque esté parcialmente manchado o roto. Para conseguirlo, se añaden datos adicionales mediante un sistema matemático llamado Reed-Solomon.
Esta es la parte más complicada. Hay que realizar operaciones matemáticas especiales para obtener siete grupos adicionales de corrección. Sin ellos, el código podría dejar de funcionar si se deteriora una pequeña parte.
Imagina que escribes una palabra en una hoja y haces una copia de seguridad. Si una parte de la primera hoja se rompe, puedes utilizar la copia para reconstruirla.
En un código QR ocurre algo parecido, pero la protección no consiste en repetir las letras. Se añaden unos datos matemáticos especiales que permiten descubrir qué información falta y recuperarla.
Ejemplo:
La palabra HOLA se convierte en estos datos:
H = 01001000
O = 01001111
L = 01001100
A = 01000001
El código QR calcula nuevos datos a partir de esos números. Estos datos adicionales no representan letras normales, sino resultados matemáticos relacionados con todo el mensaje.
Por ejemplo:
- Datos originales: HOLA.
- Datos de protección: varios números calculados a partir de HOLA.
- Si se manchan algunos cuadrados, el teléfono analiza los datos que quedan.
- Después utiliza los números de protección para averiguar qué parte falta.
- Finalmente reconstruye el mensaje original.
El sistema utilizado se llama Reed-Solomon. Funciona de una manera parecida a las piezas de un puzle: aunque falten algunas piezas, las demás contienen suficientes pistas para saber cómo eran las piezas desaparecidas.
En un código QR pequeño de versión 1 y nivel de corrección L:
- Hay espacio para 19 grupos de datos.
- Se añaden 7 grupos adicionales de corrección.
- Esos 7 grupos permiten recuperar parte de la información si el código está dañado.
Por eso se habla de “siete grupos adicionales”. No son siete letras ni siete palabras, sino siete bytes matemáticos.
Un byte es un grupo de ocho bits. Por ejemplo:
01001000
Este grupo contiene ocho bits y puede representar el número 72, que en ASCII corresponde a la letra H.
La cantidad de información que un código QR puede recuperar depende del nivel de corrección elegido:
| Nivel | Daño aproximado que puede soportar |
|---|---|
| L | 7 % |
| M | 15 % |
| Q | 25 % |
| H | 30 % |
Cuanto mayor es la protección, más fácil resulta leer un código deteriorado. Sin embargo, también queda menos espacio para guardar el mensaje, porque hay que utilizar más módulos para los datos de corrección.
La parte difícil es que Reed-Solomon no se calcula sumando los números normalmente. Utiliza operaciones con polinomios y una tabla matemática especial. Por eso, una persona puede entender perfectamente para qué sirve la protección contra errores, pero calcularla completamente a mano resulta bastante complicado.
En resumen, la protección contra errores funciona así:
- Se convierte el mensaje en números.
- Se realizan cálculos matemáticos con esos números.
- Se crean datos adicionales de protección.
- Los datos originales y los de protección se introducen en el código QR.
- Si algunos módulos se dañan, el teléfono utiliza la información restante para reconstruir el mensaje.
Para nuestro ejemplo «HOLA», vamos a utilizar un código QR de versión 1-L.
Esto significa:
- La cuadrícula tendrá 21 × 21 módulos.
- El nivel de protección será L.
- Habrá 19 bytes para los datos.
- Se añadirán 7 bytes de protección.
Los datos originales que ya calculamos son:
40 44 84 F4 C4 10 EC 11 EC 11 EC 11 EC 11 EC 11 EC 11 EC
Estos números están escritos en hexadecimal. Ahora vamos a calcular los 7 bytes de protección.
- Añadir siete grupos vacíos
Como queremos obtener siete bytes de protección, añadimos siete grupos de ceros al final:
40 44 84 F4 C4 10 EC 11 EC 11 EC 11 EC 11 EC 11 EC 11 EC 00 00 00 00 00 00 00
Los siete últimos 00 son espacios reservados para los futuros datos de protección.
- Utilizar el polinomio de Reed-Solomon
Para obtener la protección, el estándar QR utiliza un polinomio especial de siete niveles:
01 7F 7A 9A A4 0B 44 75
No son números escogidos al azar. Son los valores establecidos por el sistema Reed-Solomon para calcular siete bytes de corrección.
- Comparar el primer byte
Comenzamos con el primer byte de nuestros datos:
40
Ahora multiplicamos 40 por cada número del polinomio. Estas multiplicaciones no son multiplicaciones normales, sino operaciones matemáticas especiales del sistema QR.
El resultado es:
40 B6 EB 49 72 FA D0 0C
- Comparar los datos mediante XOR
Ahora comparamos esos resultados con los primeros ocho bytes del mensaje:
Datos originales:
40 44 84 F4 C4 10 EC 11
Resultados calculados:
40 B6 EB 49 72 FA D0 0C
La operación XOR funciona así:
- Si los dos bits son iguales, el resultado es 0.
- Si los dos bits son diferentes, el resultado es 1.
Por ejemplo:
0100 XOR 0110 = 0010
Al hacer esta comparación, el primer 40 desaparece porque:
40 XOR 40 = 00
Después se desplaza todo un lugar hacia la izquierda y se repite el mismo proceso con el siguiente byte que quede al principio.
- Repetir el proceso
El procedimiento se repite una y otra vez:
- Se mira el primer byte que queda.
- Se multiplica por el polinomio.
- Se comparan los resultados con los ocho bytes siguientes mediante XOR.
- Se elimina el primer byte.
- Se continúa con el siguiente.
En nuestro ejemplo, los bytes que se utilizan como referencia en cada repetición son:
| Paso | Byte utilizado |
|---|---|
| 1 | 40 |
| 2 | F2 |
| 3 | AE |
| 4 | 8B |
| 5 | 52 |
| 6 | 3C |
| 7 | 30 |
| 8 | C9 |
| 9 | 22 |
| 10 | 2B |
| 11 | 75 |
| 12 | D8 |
| 13 | B5 |
| 14 | 80 |
| 15 | 1A |
| 16 | F2 |
| 17 | 26 |
| 18 | 40 |
| 19 | FA |
Estos valores van apareciendo durante las sucesivas operaciones XOR.
- Obtener los siete bytes finales
Cuando terminamos las 19 repeticiones, los siete valores que quedan al final son los bytes de protección:
AE D2 43 CD 65 AF 74
En números decimales son:
174, 210, 67, 205, 101, 175 y 116.
- Unir los datos y la protección
Ahora juntamos los datos originales con los siete bytes de corrección:
Datos originales:
40 44 84 F4 C4 10 EC 11 EC 11 EC 11 EC 11 EC 11 EC 11 EC
Bytes de protección:
AE D2 43 CD 65 AF 74
Secuencia completa:
40 44 84 F4 C4 10 EC 11 EC 11 EC 11 EC 11 EC 11 EC 11 EC AE D2 43 CD 65 AF 74
Esta es la información que después se colocará dentro de la cuadrícula del código QR.
La idea sencilla es esta: los 19 primeros bytes contienen el mensaje «HOLA» y los 7 últimos funcionan como pistas matemáticas. Si algunos cuadrados se estropean, el teléfono utiliza esas pistas para reconstruir los datos que faltan.
Hay que ser exactos con un detalle: Reed-Solomon no utiliza sumas y multiplicaciones normales. Trabaja con una tabla matemática especial llamada campo de Galois. Por eso podemos mostrar el proceso completo y los resultados de nuestro ejemplo, pero calcular todos los pasos a mano sin una tabla de apoyo sería demasiado complicado.
Dibujar la cuadrícula
Para un mensaje corto como «HOLA» se puede utilizar una cuadrícula de 21 cuadrados de ancho por 21 de alto.
Antes de colocar los datos, hay que dibujar:
- Un cuadrado grande en la esquina superior izquierda.
- Otro cuadrado grande en la esquina superior derecha.
- Un tercer cuadrado grande en la esquina inferior izquierda.
- Las líneas de sincronización que atraviesan la cuadrícula.
- Un margen blanco alrededor de todo el código.
Colocar los ceros y los unos
Los ceros y unos restantes se colocan en los espacios libres de la cuadrícula. El orden no es aleatorio: hay que empezar por la esquina inferior derecha y avanzar en zigzag, subiendo y bajando por columnas.
La idea es más sencilla de lo que parece. Imagina que la cuadrícula del código QR es una hoja llena de casillas vacías.
Cada bit ocupa una casilla:
- 1 = casilla negra.
- 0 = casilla blanca.
Pero no podemos colocarlos donde queramos. El código QR tiene un camino obligatorio.
Imagina solo una pequeña parte de la cuadrícula:
Se empieza por la parte inferior derecha y se utilizan dos columnas juntas. Primero se sube:
| 4 | 3 | ||
|---|---|---|---|
| 5 | 2 | ||
| 6 | 1 | ||
| 7 | 0 |
El orden sería:
- Primera casilla inferior derecha.
- Casilla situada a su izquierda.
- Subimos a la siguiente casilla de la derecha.
- Pasamos a la casilla de su izquierda.
- Seguimos subiendo.
- Cuando llegamos arriba, bajamos por las dos columnas siguientes.
Por eso se llama recorrido en zigzag: se sube, después se baja, después se vuelve a subir y así sucesivamente.
Con los primeros bits de «HOLA», la secuencia empieza así:
0 1 0 0 0 0 0 0 0 1 0 0…
Cada número ocupa una casilla:
| Bit | Color |
|---|---|
| 0 | Blanco |
| 1 | Negro |
| 0 | Blanco |
| 0 | Blanco |
| 0 | Blanco |
| 0 | Blanco |
| 0 | Blanco |
| 0 | Blanco |
Sin embargo, hay casillas que no se pueden utilizar para los datos. Son las partes que sirven para que el teléfono reconozca el código:
- Los tres cuadrados grandes de las esquinas.
- Las líneas de sincronización.
- Las casillas que indican el nivel de corrección.
- Los posibles cuadrados pequeños de orientación.
Cuando el recorrido llega a una de esas zonas, simplemente se salta esa casilla y continúa con la siguiente que esté libre.
Por ejemplo, si el recorrido encuentra este patrón:
| X | |||
|---|---|---|---|
| X | |||
| X |
La X significa «casilla reservada». El bit no se coloca ahí, sino en la siguiente casilla disponible.
Aplicado a una cuadrícula real, el proceso sería:
- Dibujar primero los tres cuadrados grandes de las esquinas.
- Dibujar las líneas y zonas reservadas.
- Situarse en la esquina inferior derecha.
- Colocar el primer bit en la primera casilla libre.
- Colocar el siguiente bit en la casilla de al lado.
- Subir por esas dos columnas.
- Saltar las casillas reservadas.
- Al llegar arriba, desplazarse dos columnas hacia la izquierda.
- Bajar por esas dos columnas.
- Repetir el recorrido hasta colocar todos los bits.
Por ejemplo, si los bits fueran:
0 1 1 0 1 0
Se dibujarían así:
| Blanco | Negro |
|---|---|
| Negro | Blanco |
| Negro | Blanco |
Es decir:
- El 0 se pinta de blanco.
- El 1 se pinta de negro.
- Se sigue siempre el camino establecido.
- No se decide libremente dónde colocar cada cuadrado.
La parte importante es que el QR no lee los cuadrados siguiendo una línea normal de izquierda a derecha. El teléfono sabe de antemano que los datos están colocados siguiendo ese recorrido vertical en zigzag. Por eso puede reconstruir correctamente los ceros y los unos.
Aplicar la máscara
A continuación se aplica una máscara matemática. Esta máscara cambia algunos cuadrados negros por blancos y algunos blancos por negros para evitar que se formen patrones que puedan confundir a la cámara.
Comprobar el resultado
Cuando el dibujo esté terminado, hay que dejar un margen blanco alrededor y probarlo con varios teléfonos móviles.
Si el teléfono no lo reconoce, probablemente haya un error en alguno de estos elementos:
- La conversión de las letras.
- La colocación de los ceros y los unos.
- Los datos de corrección.
- Los cuadrados de las esquinas.
- La máscara.
- El tamaño o la separación entre los módulos.
Más allá del enlace: usos, riesgos y evolución
Aunque la aplicación más extendida en la vida diaria consiste en almacenar una dirección URL para dirigir al usuario a un sitio web, la flexibilidad del estándar permite empaquetar una amplia variedad de formatos de datos directamente legibles sin necesidad de conexión a internet. Es posible codificar vCards completas con nombres, teléfonos y correos electrónicos que se guardan automáticamente en la agenda del teléfono, credenciales de redes Wi-Fi que conectan el dispositivo de forma automática al escanearlas, coordenadas geográficas para sistemas de navegación o instrucciones de pago directo mediante pasarelas bancarias.
Dentro de este ecosistema operativo, conviene distinguir entre los códigos estáticos y los dinámicos. Los primeros contienen la información grabada de forma permanente en su matriz geométrica; si se desea cambiar la página web de destino, es necesario generar e imprimir un nuevo código físico. Los códigos dinámicos, en cambio, redirigen a una dirección intermedia gestionada por un servidor que puede modificar el destino final en cualquier momento sin alterar el diseño visual impreso, permitiendo además recopilar métricas detalladas sobre cuántas veces, cuándo y desde qué ubicaciones geográficas se ha realizado el escaneo.
Sin embargo, la popularización masiva de esta tecnología también ha traído consigo nuevos vectores de riesgo en materia de ciberseguridad. Al no incluir ningún cifrado interno ni mecanismos de autenticación nativos, cualquier persona puede generar un código que dirija a una dirección web maliciosa diseñada para robar datos personales o instalar software fraudulento. Esta práctica delictiva, conocida popularmente como quishing, aprovecha la confianza ciega que los usuarios suelen depositar en estos elementos visuales, haciendo que muchos escaneen sin verificar la URL de destino que muestran los navegadores móviles antes de cargar la página.
Paralelamente, la evolución tecnológica no se detiene en las clásicas matrices cuadradas en blanco y negro. En los últimos años han surgido variantes avanzadas como los microcódigos, diseñados para superficies muy reducidas donde el espacio es un bien escaso, o los diseños personalizados que integran elementos artísticos y corporativos complejos sin comprometer la legibilidad del sistema óptico. La investigación actual busca fusionar estas matrices con tecnologías de realidad aumentada y sistemas de identificación visual basados en inteligencia artificial, demostrando que un invento concebido hace treinta años para seguir piezas de automóviles sigue teniendo una capacidad de reinvención insólita.
¿Te habías detenido alguna vez a pensar en la compleja maquinaria matemática que se esconde detrás de un simple escaneo con tu teléfono móvil? ¿Has sufrido alguna vez las consecuencias de un código malicioso o utilizas estas matrices habitualmente en tu día a día profesional? ¡Comparte tus experiencias y opiniones en los comentarios!



