Leer un código QR con FileMaker en una imagen de un campo contenedor

En esta entrada vamos a ver cómo leer el código QR de una imagen en JPG de un campo contenedor de FileMaker 19, pasando el resultado a un campo de texto.

Aquí estamos otra vez con más FileMaker y más JavaScript: ¡Más Melocotones!

Vaya por delante lo que ya he comentado en alguna ocasión, que no soy ningún experto. Ni soy experto en FileMaker ni lo soy en JavaScript. Aviso esto porque esta entrada, aunque funciona, me sigue quedando la impresión de que se podría hacer lo mismo pero mejor y de una forma más directa… o no, luego me explico… o no.

Bueno, al tajo. Resulta que en la entrada “Generar códigos QR con FileMaker”, Marcos planteó la siguiente cuestión:

¿Es posible realizar el proceso inverso? me explico:
La idea es (hablando de Filemaker) leer o escanear el código siendo este una imagen insertada en un campo contenedor y obtener el resultado en un campo de texto.

Y me picó la curiosidad.

Comencé a buscar en el bendito GitHub algún desarrollo en JavaScript para leer códigos QR. Hay unos cuantos y al final me decanté por este porque está bastante actualizado y muy bien currado:

https://github.com/mebjas/html5-qrcode

Que además también tiene una entrada en su blog:

https://blog.minhazav.dev/HTML5-QR-Code-scanning-support-for-local-file-and-default-camera/

Estuve haciendo unas cuantas pruebas intentando leer el código directamente de la imagen, y aunque con los ejemplos en HTML funcionaba, usando un input, si intentaba prescindir de ese input y/o hacer eso mismo en FileMaker, cargar la imagen directamente a una función, no conseguía ningún resultado positivo. Algo no estaba haciendo correctamente, pero no sabía el qué.

El caso es que me cansé de probar y decidí cambiar de estrategia: ¿Y si pasaba la imagen a base64 e intentaba leer el QR así? Era dar un rodeo, pero si funcionaba…

Obviamente eso suponía buscar otra librería, así que me lancé a ello, pero mira tú por dónde, encuentro esta página que dice que hace eso con la misma que estoy usando, aunque modificándola ligeramente:

https://sandi-fajariadi.medium.com/detect-qr-code-from-an-image-using-javascript-ba30b0aa7d59

¡Y funciona, vaya si funciona!

Sandi Fajariadi muestra en su página un código que nosotros vamos también a modificar otro poquito. Para empezar, él extrae el tipo de fichero de la cadena en base64 y luego elimina la cabecera. Nosotros, en FileMaker, generamos la cadena en base64 sin la cabecera y vamos a asumir que usamos siempre ficheros en JPG. Teniendo esto, si queremos usar otro tipo de ficheros sería fácil adaptar el código si es que hiciera falta.

Al lío.

Lo primero que haremos será descargarnos el script en JS. Si vamos al apartado “minified”:

https://github.com/mebjas/html5-qrcode/tree/master/minified

Encontramos esta advertencia:

If you are not using any loader, you can get the latest UMD javascript code in production from https://unpkg.com/html5-qrcode

Así que nos lo bajamos del mencionado enlace.

A continuación, vamos a realizarle la modificación indicada por Sandi Fajariadi:

Tan simple como con un editor de texto buscar la cadena de arriba y sustituirla por la de abajo. Y con esto ya tenemos el script listo para nuestros propósitos.

Vamos a probar: Crearemos en FileMaker un fichero sencillo con los siguientes campos:

    • qrcode: que contendrá el script que acabamos de bajar y preparar. Será un campo de texto con almacenamiento global
    • imagen: un campo contenedor donde meteremos los QR
    • base64: un campo de cálculo con resultado texto que codificará en Base64 la imagen del contenedor
    • resuelve: un campo de cálculo, con resultado texto, que será el que genere la web que procesará el visualizador.
    • resultado: un campo de texto donde pegaremos el resultado de “leer” el QR

También crearemos un guion para pasar el valor de la variable al campo de texto que bautizaremos como «resultprint«.

Y así, sabiendo todos estos datos, podemos ir preparando el cálculo para el campo “resuelve”, que quedará así:

¡Que no cunda el pánico! Más adelante, cuando hagamos la prueba con el FileMaker lo ponemos para copiar y pegar. De momento es sólo para echarle un vistazo.

Las únicas diferencias con el código de Fajariadi es que prescindimos de leer y eliminar la cabecera, de mostrar los errores (si los hubiera) por consola, ya que eso no nos es útil en FM, y que el resultado lo metemos en la última función en una variable que es la que pasaremos  al guion con PerformScripWithOption

Código de la web de Sandi Fajariadi mostrando las zonas donde hemos realizado los cambios.

Preparando el FileMaker

Como hemos comentado antes, vamos a crear un ficherito sencillo con los mencionados campos:

Poca complicación, como puede verse. Lo único el contenido de los campos de cálculo. Para el «base64» la fórmula será la siguiente:

Base64EncodeRFC ( 4648 ; imagen)

Más información:

https://help.claris.com/es/pro-help/content/base64encoderfc.html

El contenido del campo de cálculo «resuelve«, listo para copiar y pegar, es este:

"<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=Utf-8'>
<script>" & qrcode & "</script>
</head>
<body>
<div id='reader'></div>
<script>
var base64image = '" & base64 & "';
var resultado;
function base64ImageToBlob(str) {
var type = 'jpg';
var b64 = str;
var imageContent = atob(b64);
var buffer = new ArrayBuffer(imageContent.length);
var view = new Uint8Array(buffer);
for(var n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
var blob = new Blob([buffer], { type: type });
return blob;
}
function getQRCode(imageBase64) { 
var imageBlob = base64ImageToBlob(imageBase64);
const html5QrCode = new Html5Qrcode('reader');
html5QrCode.scanFile(imageBlob, false)
.then(qrCodeMessage => {
setQRCode(qrCodeMessage);
}); 
}
function setQRCode(QRCode) {
resultado = QRCode;
FileMaker.PerformScriptWithOption ( 'resultprint', resultado, '0' );
}
getQRCode(base64image);
</script>
</body>
</html>"

Una pequeña actualización:

He estado haciendo unas pruebas y fruto de ellas ha sido someter a dieta al campo anterior, eliminando casi todas las funciones y simplificándolo, el resultado es el siguiente, que hace exactamente lo mismo pero con menos líneas:

"<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=Utf-8'>
<script>" & qrcode & "</script>
</head>
<body>
<div id='reader'></div>
<script>
var b64 = '" & base64 & "';
var type = 'jpg';
var imageContent = atob(b64);
var buffer = new ArrayBuffer(imageContent.length);
var view = new Uint8Array(buffer);
for(var n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
var imageBlob = new Blob([buffer], { type: type });
const html5QrCode = new Html5Qrcode('reader');
html5QrCode.scanFile(imageBlob, false).then(function(qrCodeMessage){
var resultado = qrCodeMessage;
FileMaker.PerformScriptWithOption ( 'resultprint', resultado, '0' );
});
</script>
</body>
</html>"

Y falta el script de JS que habrá que incluir en el campo qrcode en el que, además de la modificación de Fajariadi hemos eliminado la primera línea con el comentario relativo a la licencia, que me fastidia, pero en ocasiones he tenido problemas con JavaScript en FileMaker si llevaba comentarios, espacios, etc. No obstante, la primera línea eliminada es esta:

/*! For license information please see html5-qrcode.min.js.LICENSE.txt */

Y el script lo paso a este archivo de texto para poder descargarlo, abrir con cualquier editor de texto y directamente copiar y pegar en el campo de texto:

html5-qrcode.min-MODIFICADO.txt

Por supuesto, ahora tenemos que ir a «presentación» y crear un visualizador web para que procese todo:

Ampliamos las opciones, para refrescar la memoria, ya que en alguna entrada anterior las hemos colocado igual:

Aquí el visualizador web es enorme, pero no lo necesitamos ver para nada, aunque tiene que estar. Recordad que una opción, cutre pero efectiva, es darle una dimensión de un pixel y colocarlo donde no moleste.

Vamos ahora, por último, con el guion que necesitamos para que tome el valor de la variable de JavaScript y lo coloque en el campo de texto, obteniendo en claro el contenido del QR que es lo que hemos venido a buscar:

Como ya vimos en entradas anteriores, un par de líneas: En la primera establecemos una variable, le decimos que tome el valor de ScriptParameter y en la segunda establecemos un campo, el de texto, y que coloque el valor de la variable.

Probando

Y llega el momento de saber si todo esto funciona (Atención, spoiler: ¡Funciona! 😀 )

Apañamos un poco la presentación, ponemos el visualizador a la derecha, ordenamos un poquito los campos y a ver qué pasa. No hace falta tampoco tener los campos visibles, esto es sólo para probar.

Vamos a una de las entradas que tenemos por melocotones y hacemos una captura de un QR y lo guardamos como JPG, por ejemplo este:

El contenido del mismo es «Lo que quieras poner»

Ahora, creamos nuestro primer registro y arrastramos el fichero hasta el campo contenedor, a ver qué pasa:

Y ahí lo tenemos.

Vamos a probar con otro y se lo vamos a complicar algo. Capturamos el QR que tenemos aquí: https://www.wampirius.com/revisado-codigos-qr-con-filemaker-parte-ii-tamano-de-impresion/ y no nos molestamos ni en quitar las flechas y, ojo a esto, la captura es en png y se la colocamos tal cual en ese formato:

¡Fantástico! el desarrollo de Minhaz es una auténtica joya. Ha leído el QR sin importarle la «basurilla» añadida. Además, lo curioso ha sido que lo que hemos arrastrado a FileMaker ha sido un archivo en PNG, y al script le estamos diciendo que es un JPG (ver línea 13). Teóricamente esto «no» debería haber funcionado, pero lo ha hecho, y ahora mismo no sé si es por cómo está programada la librería o por cómo almacena FileMaker las imágenes. En cualquier caso esto ha sido una prueba y no conviene fiarse de que vaya a funcionar sea cual sea el formato. En caso de querer usar más de un formato, lo suyo sería averiguar el tipo de formato y meterlo en la variable.

Una vuelta de tuerca más y acabamos ¿Y si lo giramos un poco, no 90 o 180 grados, sólo un poco…?

Me reafirmo en lo dicho: esta librería es una auténtica joya. Tengo que probar el resto de formatos que soporta, pero es extraordinaria.

Edito: Como me han pedido el archivo fmp12 por mail, dejo aquí una versión del mismo, un pelín diferente a la de los ejemplos anteriores, que muestra también el contenido del QR en el campo contenedor. Es una sobre la que he estado haciendo pruebas para una entrada posterior. Funciona perfectamente en versiones de FileMaker 19.3.1 y posteriores:

leerqr_FM19

Gracias a Minhaz por este pedazo de trabajo y gracias también a Sandi Fajariadi por su aportación sobre Base64 y su ajuste sobre el script de Minhaz. Gracias a estos dos genios ha sido posible el desarrollo de esta entrada. Es todo el mérito suyo, un servidor no ha hecho sino juntar las piezas.

¡Hasta la próxima fruta (u hortaliza, u lo que sea…)!

Nota: La imagen de cabecera está sacada de Pixabay y su autor es Xavier Turpain (xat-ch) 

 

2 respuestas a «Leer un código QR con FileMaker en una imagen de un campo contenedor»

  1. muchas gracias por tu aportacion me ha ayudado muchisimo solo que no puedo hacer funcionar el script de resultprint, no veo en donde este la falla

    1. Hola.
      Perdona el retraso en contestar. Me alegra saber que la entrada te ha sido de ayuda. En cuanto a por qué no funciona el guion… no sabría decirte con seguridad. Una de las causas puede ser la versión de FileMaker, que tiene que se igual o superior a la 19.3.1, que es cuando se introducen cambios importantes en el motor del visualizador web. Pero si no es ese el caso, pues ya no sabría decirte.
      Puedes bajarte el archivo de esta entrada, que lo tienes un poco más arriba para descargar (leerqr_FM19). Está justo encima, al final de la entrada. Hasta hace unos días daba error a la hora de descargar porque una actualización había roto todos los links de descarga, pero ya está solucionado. Ese archivo te garantizo que funciona, lo volví a probar ayer en otro equipo para asegurarme. A ver si viéndole las entrañas consigues solucionar el problema.
      Suerte y un cordial saludo.

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