4 puntos por GN⁺ 2024-01-23 | 1 comentarios | Compartir por WhatsApp
  • 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 110 en binario
    • 110 corresponde al 6 en decimal
  • 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
  • El primer byte sin máscara es 01001000
    • En hexadecimal es 0x48
    • El carácter ASCII correspondiente es H
  • El segundo byte sin máscara es 01100101
    • En hexadecimal es 0x65
    • El carácter ASCII correspondiente es e
  • 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 a en 0x61 y terminan con z en 0x7A
    • 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

 
GN⁺ 2024-01-23
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...

    • Me recuerda la forma en que se hizo ingeniería inversa del firmware y las claves del iPod de primera generación.
      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
    • A medida que los sistemas bloqueados se vuelven más comunes, este tipo de exfiltración de datos basada en pantalla claramente parece tener futuro.
  • 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.

    • Los códigos de barras usan el último dígito como checksum, suman y multiplican los números y luego hacen un cálculo tipo % 10 para 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...
    • Los datos dentro de un código QR se codifican como un flujo de bits en uno de varios alfabetos, y bytes es solo uno de ellos.
      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.
    • An Artisanal QR Code muestra cómo calcular a mano un checksum con una aritmética parecida a la división larga.
      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

    • La corrección de errores es curiosa
      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
    • La corrección de errores no es para quienes se preguntan “qué debo hacer para hacer más pequeño el mensaje y mejorar la legibilidad del código QR”
      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 año pasado hice un experimento parecido y, al menos en códigos QR impresos en 3D, lo mejor fue no tener corrección de errores
      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...

    • La corrección de errores es un tema realmente interesante
      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?

    • No hay nada que impida un nuevo diseño bastante mejor
      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
    • Si se hubiera inventado hoy, probablemente habría sido hexagonal