Revisado: Códigos QR con Filemaker. Parte I: Nitidez

Hay dos problemas que nos podemos encontrar en FileMaker a la hora de generar códigos QR: la nitidez y el tamaño. En esta primera entrada vamos a tratar el tema de la nitidez, cómo conseguir unos QR perfectamente definidos con FileMaker.

Hace ya algún tiempo publiqué la siguiente entrada:

Generar códigos QR con FileMaker

El problema de la nitidez se puede solventar con algún ajuste sobre lo explicado en ella, no obstante, hay otra librería que ayuda bastante en este sentido: kjua

https://larsjung.de/kjua/

El mencionado link es el de su página y autor, Lars Jung, el mismo de la librería que utilizamos en la entrada inicial de los QR. Librería y código fuente se pueden encontrar aquí:

https://github.com/lrsjng/kjua

¿Qué tiene de especial esta librería? Pues, para empezar, que cuenta con una opción, “crisp”, que si la establecemos en “true” mostrará siempre códigos QR nítidos “casi” al tamaño que queramos. Y digo “casi” porque esto tiene truco. Pongo un ejemplo y luego nos metemos en harina.

Si le pedimos a la librería que nos genere un QR de versión 6 (luego hablamos de esto de las versiones) y con un tamaño de 200 px, se nos generará un cuadrado de 200×200 que contendrá un QR perfecto… pero cuyas medidas de QR, de negro a negro, para entendernos, serán de 164×164, dejando un margen blanco de 18 px por cada lado para acabar formado el cuadrado de 200×200 solicitado.

Sí, ya, ya… Que suena a chino, pues vamos con un ejemplo que lo vamos a ver mejor.

Para realizar el ejemplo lo hacemos con este sencillo html, en el que, por cierto y a diferencia de la anterior entrada, vamos a prescindir de JQuery. Para quien quiera probarlo, sólo hay que meter la librería kjua.min.js en el mismo directorio que el siguiente archivo en html que podemos nombrar como queramos.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='Content-Type' content='text/html; charset=Utf-8'>
    <script type='text/javascript' src='kjua.min.js'></script>
  </head>
  <body>
    <script>
      var imagenqr = kjua({
      render: 'image',
      crisp: true,
      minVersion: 6,
      size: 200,
      ratio: null,
      ecLevel: 'M',
      quiet:0,
      text: 'https://wampirius.com'
      });
      document.querySelector('body').appendChild(imagenqr);
    </script>
</body>
</html>

Explicamos el funcionamiento porque es muy fácil. Siguiendo las instrucciones que el autor tiene en su web:

var el = kjua({text: 'hello!'});
document.querySelector('body').appendChild(el);

Establecemos una variable, en nuestro caso «imagenqr», llamamos a la función y le pasamos las opciones con los valores que necesitamos según los ejemplos de la web:

{
    // render method: 'canvas', 'image' or 'svg'
    render: 'image',

    // render pixel-perfect lines
    crisp: true,

    // minimum version: 1..40
    minVersion: 1,

    // error correction level: 'L', 'M', 'Q' or 'H'
    ecLevel: 'L',

    // size in pixel
    size: 200,

    // pixel-ratio, null for devicePixelRatio
    ratio: null,

    // code color
    fill: '#333',

    // background color
    back: '#fff',

    // content
    text: 'no text',

    // roundend corners in pc: 0..100
    rounded: 0,

    // quiet zone in modules
    quiet: 0,

    // modes: 'plain', 'label' or 'image'
    mode: 'plain',

    // label/image size and pos in pc: 0..100
    mSize: 30,
    mPosX: 50,
    mPosY: 50,

    // label
    label: 'no label',
    fontname: 'sans',
    fontcolor: '#333',

    // image element
    image: null
}

En el navegador obtendremos esto:

Nos descargamos la imagen obtenida y la pasamos por el GIMP a ver qué nos muestra:

Vemos que, como hemos dicho antes, la imagen mide, en efecto, 200×200 pero cuenta con un margen al rededor del QR. Vamos a cortarlo y a medir de nuevo:

Y, como podemos ver, el tamaño real del QR es de 164×164. Pero… ¿Por qué es esto así?

Bien, pues esto tiene que ver con la versión del QR, e información al respecto la podemos encontrar en diversos sitios, por ejemplo aquí:

https://www.qrcode.com/en/about/version.html

o aquí:

http://hm2.heubach-media.de/projektis/hmReports/6_0/Documentation/CONTENT/EN00002273.HTM

En el primer enlace tenemos abundante información sobre los tipos de QR y el porqué de cada uno. En el segundo tenemos una útil tabla:

La versión del QR tiene que ver con la cantidad de contenido que queramos almacenar, esto viene bastante bien explicado en el primer enlace. Entonces, según sea su versión se generará una matriz de un tamaño determinado de píxeles. Para el ejemplo que nos ocupa, una versión 6, pues según la tabla será de 41×41 pixeles.

Si omitimos el parámetro «minVersion«, o si lo fijamos a 1, el script kjua seleccionará la versión más adecuada para generar el QR correspondiente, es decir, lo que hace es generar un QR de la versión más baja necesaria. No obstante, nosotros podemos «forzar» una versión mínima, de ahí que https://wampirius.com lo hayamos podido meter en una versión 6 cuando en realidad con una 2 sería suficiente. Esto de este ejemplo es como matar moscas a cañonazos, pero por poderse, vemos que se puede. No obstante, ojo: «minVersion» es eso, la versión mínima. Si ponemos 4 y la cadena a codificar requiere una versión mayor, el QR lo generará en la versión necesaria.

Vale, pero ¿qué tiene esto que ver con el margen blanco y demás mandangas? Pues que para conseguir un QR nítido, kjua lo que hace es, si tenemos la opción crisp en true, calcular cuántos grupos “enteros” de la matriz según la versión caben en la medida indicada y el resto rellenar con blanco. Así, si le hemos pedido 200px de tamaño, pues calcula 200/41 obteniendo un resultado de 4, y el resto lo rellena de blanco alrededor. Es decir, siempre dibujará un múltiplo exacto de la matriz necesaria y así, cada cuadradito del QR ocupará un pixel, cuatro (2×2), nueve (3×3)… los que sean, pero todos medirán exactamente lo mismos píxeles y la nitidez en pantalla será perfecta. El tema de la impresión lo dejamos para la siguiente entrada.

Vamos a ver qué pasa poniendo la opción crisp en false: En este caso, el QR se generará exactamente al tamaño deseado, pero tendrá que intercalar píxeles y el resultado no saldrá tan nítido:

Seguro que estás pensando que “pues yo lo veo igual” o “pues no está tan mal”, y tienes razón, aquí en pantalla no se ve del todo mal, pero en FileMaker cuando imprimimos, las cosas cambian y bastante. Así que vámonos p’allá.

FileMaker 19

Vamos a crear un FM sencillito: un campo de texto con lo que queremos que contenga el QR y el visualizador para el QR, y por supuesto los campos necesarios para albergar el script kjua y el campo de cálculo que produzca el código html para el visualizador. Es fácil, pero si alguien tiene algún problema el proceso es muy similar al de la anterior entrada, donde está todo muy detallado y así no repetimos, aquí, simplemente, vamos a hacer el script del campo de cálculo un poquito diferente y, como ya hemos dicho, prescindiendo de JQuery.

Como está todo explicado en la otra entrada, vamos a poner aquí un somero resumen del contenido de los campos:

Campo contenido: de texto. Pondremos lo que queramos que salga en el QR. En los ejemplos lo haremos con https://wampirius.com pero podéis poner lo que mejor os parezca.

Campo kjuamin: de texto y global que tiene que albergar el contenido del script generador del código QR, en este caso kjua y que podemos descargar de aquí:

https://github.com/lrsjng/kjua

Descargamos el código y en la carpeta dist tenemos el archivo kjua.min.js el contenido de dicho archivo es el que colocaremos en el campo kjuamin

Campo codigoqr: de cálculo y generará el html que ha de leer el visualizador web.

Ahora, si nos acordamos de cómo habíamos hecho el campo de cálculo de la otra entrada, pues procedemos igual con este, pero cambiamos un par de cosillas en el script. Si en aquel generábamos el QR en un div, aquí al prescindir de JQuery lo hacemos un pelín diferente, así:

"<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='Content-Type' content='text/html; charset=Utf-8'>
    <script>" & kjuamin & "</script>
  </head>
  <body>
  <script>
      var imagenqr = kjua({
      render: 'image',
      crisp: true,
      minVersion: 6,
      size: 200,
      ratio: null,
      ecLevel: 'M',
      quiet:0,
      text: '" & contenido & "'
      });
      document.querySelector('body').appendChild(imagenqr);
  </script>
</body>
</html>"

De momento dejamos las mismas opciones que nos han generado el último QR, donde la imagen tenía 200×200 en una versión 6. Luego jugaremos un poco con estos valores. Esto lo hacemos con la única idea de seguir con el mismo ejemplo y poder comparar y, para ello, en el campo contenido introduciremos https://wampirius.com para que los QR del ejemplo anterior hecho con el navegador y este nos salgan exactamente iguales. El resultado es este:

El visualizador web lo hemos definido en la presentación con unas dimensiones de 300×300 para que albergue sin problemas al QR sin barras de desplazamiento ni nada por el estilo.

Vamos a cambiar crisp a false. De esta forma el QR medirá nuestros 200×200 pero a costa de perder nitidez:

Ya sé lo que estás pensando: “Joer, Wampi, yo lo sigo viendo bien”. Pues sí, “mal del todo” no se ve, la verdad, pero si imprimimos en un PDF y ampliamos:

Vemos que «nítido, nítido» no es. Y aunque con este ejemplo pudiera resultar en una imagen aceptable, en otras ocasiones el problema se magnifica.

Los ejemplos que hemos usado hasta ahora para codificar https://wampirius.com han sido con un QR de tipo 6, que es como matar moscas a cañonazos porque sobran puntos como para tres partidos de baloncesto, pero era sólo un ejemplo para ver que podemos generar QR de un tipo superior al que necesitamos y jugar un poco con las dimensiones.

Vamos a ver qué pasa poniendo el minVersion: 1 y el size a 60 (recordamos que con minVersion kjua selecciona la versión mínima necesaria para generar el QR a partir del número que le pongamos, en este caso ya os puedo decir que para la dirección de este blog es necesaria una versión 2, que produce una matriz de 25×25)

Que si lo imprimimos en un pdf y ampliamos a un 300%

Podemos ver que está a años luz de estar bien

Pero con el crisp en true, el resultado impreso es este:

Está también ampliado al 300% y vemos que el resultado es perfecto, un poco más pequeño, porque la matriz tiene 25×25 y habrá generado un QR de 50×50 con un margen de 5 px en blanco alrededor para obtener los 60×60 solicitados.

Vale, ya sabemos cómo mostrarlos por pantalla e imprimirlos perfectamente nítidos, ahora nos queda el tamaño en papel. Pero antes de meternos con el tamaño impreso, que tiene su miga aunque es muy interesante, vamos con un “truco” para tener unos QR perfectamente nítidos al tamaño que nos de la gana, peeeero… sólo en pantalla.

QR vectoriales

No sé muy bien qué utilidad puede tener esto en FileMaker, pero es muy sencillo y puede ser útil en alguna app.

Este script, kjua, nos ofrece la posibilidad de generar imágenes SVG, esto es, gráficos vectoriales.

Al usar gráficos vectoriales no tendremos ningún problema en conseguir unos gráficos nítidos al tamaño que queramos, podéis probar poniendo la opción render: ‘svg’ y distintos tamaños. Pero aún hay otra opción muy interesante con estos gráficos: hacer que se adapten al 100% del tamaño del visualizador web sin tener que hacer cábalas respecto al tamaño. Para ello, sólo tenemos que saber qué tipo de QR necesitamos generar, su tamaño necesario según la tabla y hacer unas pequeñas modificaciones en el campo de cálculo, que quedaría así:

"<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='Content-Type' content='text/html; charset=Utf-8'>
    <script>" & kjuamin & "</script>
  </head>
  <body>
  <svg viewBox='0 0 25 25' >
  <script>
      var imagenqr = kjua({
      render: 'svg',
      crisp: true,
      minVersion: 1,
      size: 25,
      ratio: null,
      ecLevel: 'M',
      quiet:0,
      text: '" & contenido & "'
      });
      document.querySelector('svg').appendChild(imagenqr);
  </script>
</svg>
</body>
</html>"

La magia la va a hacer viewBox=’0 0 X X’ sin más parámetros, donde X y X son las medidas de nuestro QR, en este ejemplo 25×25

Después de <body> colocamos la etiqueta svg: <svg viewBox=’0 0 25 25′ > donde los dos últimos números son la resolución que hemos pedido que genere. El tipo, render, lo ponemos en svg y finalmente, en document.querySelector ponemos svg en lugar de body. Tras cerrar el script ponemos la etiqueta de cierre de svg y listo. Esto generará un QR que ocupará toda el área del visualizador web:

Si en la presentación definimos el área del visualizador web en 60×60:

Obtenemos:

Y si cambiamos las medidas del visualizador a cualquier otra medida, por ejemplo 317×317:

Obtenemos:

Perfectamente nítido, adaptado y sin tocar absolutamente nada más.

Y seguro que estás pensando…. “Pues si sale así de bien, ponemos un tamaño de 60×60 y a imprimir”. Vamos a probar imprimiendo el que hemos hecho primero:

Pues no. Lamentablemente, esto sólo vale para pantalla. Impresos los QR sólo saldrán nítidos si las dimensiones son múltiplo de la matriz que se tenga que generar, y controlar así el tamaño es muy difícil. Podremos imprimir algo muy aproximado, pero no exacto.

Pero hay solución, y pasa por definir los dpi en el archivo de imagen que se genere, de esta forma, la imagen impresa saldrá exactamente al tamaño que queramos y perfectamente nítida. Pero eso lo veremos en la siguiente entrada.

No obstante, antes de seguir adelante, dejo aquí un par de links para aprender más sobre los SVG porque tienen un montón de posibilidades:

https://webdesign.tutsplus.com/es/tutorials/svg-viewport-and-viewbox-for-beginners–cms-30844

How to Scale SVG

En esta entrada hemos visto un poco el funcionamiento del script kjua y sus posibilidades, bien usando image o svg y cómo sacar códigos perfectamente nítidos tanto en pantalla como impresos. También hemos visto cómo sacarlos nítidos y a cualquier tamaño en pantalla. Ya sólo nos queda poder imprimirlos al tamaño exacto que queramos, y eso lo vamos a solucionar en nada.

Nos vemos en la próxima entrada.

Nota al pie: Por cierto, la imagen de cabecera es una adaptación de una libre de derechos y original de Roland Steinmann, «Rollstein», en Pixabay: https://pixabay.com/es/users/rollstein-13853955/

Deja una respuesta

No está permitida la inserción de ningún dato de carácter personal (mail, tef...). Cualquier comentario que los contenga será editado o eliminado.

Por favor, si dejas un comentario pon cualquier nombre para poderme dirigir a ti pero que no te identifique

El comentario es totalmente anónimo. No se almacena la IP