La tecnología para leer códigos QR sin una computadora
(qr.blinry.org)- Se organiza el procedimiento paso a paso para descifrar un código QR a mano, desde la estructura de 21×21 módulos de la versión 1 hasta quitar la máscara y convertirlo a bytes
- Las áreas especiales como el patrón de búsqueda, el patrón de temporización, la información de formato y la quiet zone son necesarias para reconocerlo, pero deben omitirse al leer los datos reales
- Los datos se restauran verificando primero en la información de formato el patrón de máscara y el nivel de corrección de errores, y luego invirtiendo los módulos del QR en cada posición negra de la máscara
- Se lee en orden de zigzag de dos columnas, empezando desde la esquina inferior derecha; en modo Byte, después de los 8 bits de longitud, cada grupo de 8 bits corresponde a un byte de carácter
- No hace falta resolver a mano hasta el área de corrección de errores; en un QR simple, basta con leer la cantidad de bytes indicada por el campo de longitud y convertirlos usando la tabla ASCII para descifrarlo
Preparar un código QR para leerlo a mano
- El código QR de práctica se puede preparar de tres maneras
- Ingresar un texto cualquiera para actualizar el código QR que se explica abajo
- Escanear con la cámara un código QR existente para aprender cómo leerlo
- Practicar con una palabra aleatoria en inglés, que no se muestra y puede usarse como entrenamiento
- El código QR de ejemplo tiene un tamaño de 21×21 módulos
- La unidad equivalente a un píxel en un código QR se llama módulo (module)
- El tamaño del código QR se distingue por versión (version)
- La versión más pequeña es de 21×21 módulos
- A partir de ahí, cada versión aumenta 4 por lado
- Un código QR de 21×21 módulos es la versión 1
Áreas especiales que hay que omitir en un código QR
- El patrón de búsqueda (finder pattern) ayuda al escáner a identificar primero el código QR
- La línea vacía alrededor del patrón de búsqueda debe omitirse al leer el contenido
- El código QR de versión 1 no tiene patrón de alineación (alignment pattern)
- El patrón de alineación es un patrón adicional que ayuda al escáner a leer correctamente el código QR
- El patrón de temporización (timing pattern) son dos líneas donde los módulos blancos y negros siempre aparecen alternados, y ayudan al escáner a leer correctamente el código QR
- La información de formato determina el patrón de máscara y el nivel de corrección de errores
- Hay información de formato vertical y horizontal
- El patrón de temporización atraviesa e interrumpe ambas líneas
- La quiet zone es el borde blanco que rodea el código QR
- Ayuda al escáner a identificar el inicio y el fin del código QR
Quitar el patrón de máscara
- Los códigos QR usan una máscara (mask) para evitar grandes bloques negros o blancos
- En total hay 8 opciones de máscara
- En el ejemplo, se leen los módulos negros como 1 y los blancos como 0 para verificar los bits del patrón de máscara
- Los bits de ejemplo son
110en binario 110corresponde al 6 en decimal
- Los bits de ejemplo son
- Cada tipo de máscara tiene un patrón predefinido
- El patrón del código QR de ejemplo se ve como parte de un arcoíris en blanco y negro
- Después de repetir la máscara sobre el área de datos, se invierten los módulos del código QR en cada posición donde la máscara tiene un módulo negro
- Se proporciona un DIY zine con una chuleta de todos los tipos de máscara
- Para un ejemplo de cómo doblarlo como un pequeño folleto, se puede consultar esta imagen guía
Modo de codificación y orden de lectura
- El descifrado del contenido comienza verificando primero el modo de codificación
- La información de codificación siempre está en la esquina inferior derecha
- El modo de codificación también debe quitarse primero con la máscara aplicada
- En el ejemplo, se consulta la chuleta y se hace XOR entre las dos casillas
- Entre los modos de codificación están Numeric, Alphanumeric, Byte, ECI y Kanji
- El modo de codificación del código QR de ejemplo es Byte (4)
- El contenido comienza en la esquina inferior derecha
- Se lee subiendo en zigzag entre dos columnas
- Luego se baja en zigzag por las siguientes dos columnas de la izquierda
- Siempre se omiten todas las áreas especiales
Descifrar la longitud y los bytes
- Los primeros 4 bits son el modo de codificación
- En modo Byte, los siguientes 8 bits indican la longitud del contenido
- Después de eso, cada 8 bits corresponde a un byte de contenido
- La información de longitud también debe quitarse con la máscara aplicada
- En el ejemplo, la información de longitud sin máscara es
00001100- En decimal es
12 - Significa que la longitud total del contenido es de 12 bytes
- En decimal es
- El primer byte sin máscara es
01001000- En hexadecimal es
0x48 - El carácter ASCII correspondiente es
H
- En hexadecimal es
- El segundo byte sin máscara es
01100101- En hexadecimal es
0x65 - El carácter ASCII correspondiente es
e
- En hexadecimal es
- Los bytes restantes se dejan como práctica, y se puede detener la lectura al completar la cantidad de caracteres indicada por el campo de longitud leído antes
Tabla ASCII y corrección de errores
- Se puede usar una tabla ASCII para convertir valores hexadecimales en caracteres
- Las minúsculas empiezan con
aen0x61y terminan conzen0x7A- Los caracteres intermedios pueden encontrarse contándolos
- No toda el área restante es contenido
- Los códigos QR también incluyen corrección de errores (error correction)
- Esto permite leer el código QR aunque parte esté dañada, borrosa o ausente
- La corrección de errores se genera con matemáticas, pero no se aborda para el objetivo de leerlo a mano
- Después de aprender el procedimiento para descifrar a mano un código QR simple, se puede practicar con palabras cortas en inglés usando el botón de código aleatorio, o escanear un código QR real con el botón Scan code
- El código fuente está en Codeberg
- En particular, son muy bienvenidos los PR que expliquen el modo de codificación UTF-8
1 comentarios
Opiniones de Hacker News
A fines de los 90 o principios de los 2000 quería pasar el contenido de discos Atari de 8 bits a una PC.
Conocía el cable y software SIO2PC, que conectaba el puerto SIO de Atari con el puerto serial de la PC, pero en ese momento no tenía los conocimientos de electrónica para fabricarlo yo mismo.
Al final escribí un programa en Basic en el Atari para leer el disco sector por sector, dibujarlo en pantalla con los enormes píxeles de 4 colores del modo gráfico 3, conecté el Atari a la tarjeta de TV de la PC e hice que un programa en Delphi tomara capturas de pantalla continuamente para decodificar los datos.
Como los sectores vacíos desajustaban la corrección de posición de los píxeles, agregué un patrón de máscara, checksum e incluso la dirección del sector, y con ese método pude transferir todo el contenido de los discos a la PC.
Todavía considero esto mi mayor logro de ingeniería.
Unos 10 años después hice un programa SIO2PC llamado AspeQt, y RespeQt, un fork comunitario más reciente, sigue siendo la herramienta más usada en este campo; incluso tiene un subforo dedicado en AtariAge: https://forums.atariage.com/forum/184-respeqt-sio2pc-softwar...
Dicen que hicieron parpadear patrones de bits con la retroiluminación del LCD y leyeron esos datos con una cámara: https://mastodon.social/@bagder/111538350617290554
La explicación de “la corrección de errores es matemática compleja, así que no me ocupo de eso al leerlo a mano” debería tener un poco más de detalle.
Entiendo que la matemática sea difícil, pero me da curiosidad saber si los datos de corrección de errores van al final, después de cada byte o en medio.
También quisiera saber si, en un código QR no dañado, aun con corrección de errores se puede leer a mano simplemente saltándose la parte matemática.
% 10para obtener un valor entre 0 y 9.Por eso hay una probabilidad de 1/10 de que los datos estén mal pero el checksum coincida por casualidad, y de todos modos el último dígito no es importante para el ID de código de barras único del producto real.
Una vez, el código de barras de un artículo que estaba devolviendo en Home Depot estaba roto y el dígito del checksum se había desgastado; intenté desesperadamente calcularlo antes de que el empleado hiciera la búsqueda manual, pero al final él ganó, y no puedo olvidarlo.
https://www.gs1.org/services/how-calculate-check-digit-manua...
https://www.simplybarcodes.com/barcode_check_digit_calculato...
Luego, según el tamaño y el nivel de corrección de errores, el flujo de bits se divide en bloques, se calculan los datos de corrección de errores para cada bloque y después los bloques se intercalan.
Por eso este método falla, sin importar el nivel de corrección de errores, al superar la versión 5 de QR, y también falla en las versiones 3 a 5 si el nivel de corrección de errores es alto.
En la práctica se usan dos códigos algo distintos según el tipo de información: Reed-Solomon y BCH.
https://www.quaxio.com/an_artisanal_qr_code.html
Artículos relacionados:
Decoding small QR codes by hand (2012) - https://news.ycombinator.com/item?id=36173441 - junio de 2023, 69 comentarios
How a QR code works - https://news.ycombinator.com/item?id=32837565 - septiembre de 2022, 114 comentarios
Creating a QR Code step by step - https://news.ycombinator.com/item?id=24119124 - agosto de 2020, 41 comentarios
Creating a QR Code step by step - https://news.ycombinator.com/item?id=18360847 - noviembre de 2018, 34 comentarios
El artículo en sí es excelente, pero es aún más genial que genere dinámicamente todas las imágenes según los valores de entrada.
Me gustó la explicación de cómo leer códigos QR, y para un artículo sobre cómo decodificar códigos de barras unidimensionales comunes como UPC, este también está bien:
https://scanbot.io/blog/how-do-barcodes-work/
Hace unos 10 años intenté leer códigos QR a mano, pero me rendí por los patrones de máscara
Incluso antes de determinar el tipo de datos, hay que aplicar el patrón de máscara con XOR
Me da curiosidad cuánto ayudan realmente estos patrones de máscara en un lector de códigos QR real
El mes pasado estuve buscando la configuración óptima de corrección de errores, pero en casos sin daño, como una matriz completa mostrada en pantalla, la respuesta era “ninguna”, y no fue fácil llegar a esa conclusión
No encontré materiales que compararan varias configuraciones e implementaciones de escaneo en entornos reales, y probé por mi cuenta mostrando un QR pequeño en pantalla con distintos niveles de corrección de errores y sacudiendo la cámara para simular problemas de lectura, pero no vi diferencias significativas entre configuraciones
Si ya hay al menos cuatro marcadores de alineación, un margen amplio y hasta patrones de sincronización, me pregunto si de verdad hace tanta diferencia que se formen bloques blancos por no tener máscara
La segunda razón por la que dejé de intentar leer QR visualmente fue que casi siempre la URL estaba escrita debajo como texto alternativo; desde entonces sí he visto algunos casos sin texto alternativo, pero son muy raros
Si no la usas, el mensaje ocupa menos espacio y el QR se vuelve más pequeño
Si tienes que ajustarlo a un espacio fijo, como al imprimir stickers, puedes hacer que los píxeles sean físicamente más grandes, y para una lectura estable los píxeles más grandes ayudaron más que la corrección de errores
Según la longitud del mensaje, a veces puedes subir el nivel de corrección de errores sin cambiar el tamaño final del QR, y en ese caso obtienes ambas cosas
Es para quienes meten una URL completa llena de parámetros de seguimiento en un código versión 25, de 117x117, la ponen en un cartel grande y quieren que los datos sobrevivan aunque le caiga excremento de pájaro o alguien le pegue un sticker encima
El experimento buscaba ver qué tan pequeño podía imprimirse y seguir siendo detectable, y como dice el comentario de al lado, parece ser porque los píxeles individuales se vuelven más grandes
Un video de hace unos 10 años sobre cómo descifrar QR: https://www.youtube.com/watch?v=KA8hDldvfv0 (20 min)
También tengo una página web interactiva para crear un código QR paso a paso. Básicamente es el proceso inverso: https://www.nayuki.io/page/creating-a-qr-code-step-by-step
Me dio curiosidad la corrección de errores, y al parecer los códigos QR pueden diseñarse con distintas tasas recuperables, de 7% a 30%
Interesante: https://docs.beaconstac.com/en/articles/6018654-what-is-erro...
Shannon encontró los límites teóricos a mediados del siglo XX, pero nadie sabía cómo alcanzarlos
Cuando en los años 90 la patente de los códigos turbo se acercó de pronto a ese límite, la comunidad académica reaccionó con incredulidad
Por supuesto, gracias a tecnologías como esa son posibles las redes móviles rápidas y confiables
En uno de los acertijos derivados del Mystery Hunt 2023, había un problema en el que había que descifrar a mano un código QR tan dañado que ni siquiera la corrección de errores podía recuperarlo
Revisé todas las guías mencionadas en estos comentarios y, aunque fueron útiles, no eran excelentes
Así que me alegra que haya cada vez más artículos detallados como este, y este en particular definitivamente parece muy bien logrado
Si te da curiosidad, el acertijo está aquí, y la decodificación del QR aparece hacia la parte final: https://puzzles.mit.edu/2023/abcde.puzzlefactory.place/puzzl...
Según Wikipedia, el código QR fue inventado en 1994 por un fabricante japonés de autopartes para etiquetar piezas de automóviles
Me pregunto si, de haberse inventado hoy, podría haberse mejorado más
¿Se podría haber hecho más pequeño o más fácil de leer?
En 1994 los códigos de barras ya estaban por todas partes, pero eso no impidió que el código QR despegara
Tal vez no haya mucho margen de mejora. A menos que se cambie mucho el concepto y se pase a algo como NFC