Libreria (Node o PHP) para codificar imagen dentro de QR

Iniciado por [u]nsigned, 19 Abril 2020, 22:01 PM

0 Miembros y 1 Visitante están viendo este tema.

[u]nsigned

Hola, que queria preguntarles si saben de alguna libreria para NodeJs (o php) que permita guardar una imagen dentro de un codigo QR? He visto que es posible, pero no logro encontrar una libreria que haga eso. Estoy desarrollando una app y seria de gran utilidad poder meter ademas de un texto plano tambien una imagen dentro del QR.

He probado pasar la imagen a base64 y luego encodear todo al QR como si fuera texto plano, es pero muy ineficiente de esa forma. Y como acabo de ver que algunas librerias permiten trabajar directamente con datos binarios, queria saber si es posible meter la imagen mas algun texto de esa forma dentro de un QR.

Saludos y gracias por leer.  ::)

No hay atajo ante la duda, el misterio se hace aquí...
Se hace carne en cada uno, el misterio es existir!

@XSStringManolo

Miré la entrada de QR en Wikipedia y tiene aproximadamente unos 3kB de espacio. Que no es suficiente para una imagen normal.

Me imagino que no te sirve alojar una imagen online y poner la url de la imagen en el QR?

No veo una alternativa muy viable para solucionar el problema.
Usar base64 aún es peor porque te aumenta un 33% el tamaño de media.

https://www.npmjs.com/package/qr-image

engel lex

toma en cuenta que por muy comprimida que esté la imagen la misma tiene una cantidad de informacion por pixel que es de 3 veces 8 bits (de 0 a 255 por color, siendo 3 colores) el QR puede contener 1 bit por pixel, siendo los pixeles de tamaño lo suficientemente grandes para ser visibles, a eso sumale estructuras de control y redundancias de seguridad...

es decir tu resultado tendrá mas tamaño y complejidad que la imagen original
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

[u]nsigned

Muchas gracias a ambos, me han aclarado todas las dudas que tenia sobre QR.  Supongo que es inviable entonces, ya se me hacia demasiado bueno para ser verdad....

No hay atajo ante la duda, el misterio se hace aquí...
Se hace carne en cada uno, el misterio es existir!

EdePC

Saludos,

- Si te refieres a convertir una imagen tal cual en QR, pues no es dable más que nada porque el tamaño y complejidad del QR aumenta dependiendo a la cantidad de bytes de entrada.

- Por otro lado si que puedes abusar de la corrección de errores que trae QR para modificar la apariencia del QR de tal manera que se pueda incrustar una imagen visual en el, por ejemplo:



- Puedo resalta https://www.qrcode-monkey.com/es para generar QR OnLine

- En caso de PHP y Node he visto que se utilizan:
http://phpqrcode.sourceforge.net/
https://github.com/soldair/node-qrcode

[u]nsigned

Muchas gracias por el aporte!

Lo que yo necesitaba era meterla dentro del código qr como información, cosa que no se puede lamentablemente....

No hay atajo ante la duda, el misterio se hace aquí...
Se hace carne en cada uno, el misterio es existir!

engel lex

[quote author=nsigned link=topic=504120.msg2219831#msg2219831 date=1587417556]
Muchas gracias por el aporte!

Lo que yo necesitaba era meterla dentro del código qr como información, cosa que no se puede lamentablemente....
[/quote]


Imagina que lo que tu estás pidiendo es tomar el texto de una hora y en una hoja identica escribir ese texto con unos y ceros como binario... necesitarías 8 hojas para completar el mismo texto... el problema es que el requisito del QR es que el limite es meter eso en lo que cabe un twitt, ya originalmente la tarea no era posible y al hacerla 8 veces mas larga, tus posibilidades eran mucho menores...
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

@XSStringManolo

#7
Lo que podrías hacer es quizás un código más pequeño que genere una imagen de más mala calidad y abusar del navegador para ejecutarlo. Realmente nunca lo probé pero quizás se pueda.Me refiero a en lugar de poner:
https://google.com/favicon.ico


poner:
javascript:pintarHorizontalLineas("0-98", "azul");pintsrHorizontalLineas(99, "verde", "23-84"); ...


O quizás con un data:
data:text/html,<script>pintarHorizontalLineas("0-98", "azul");pintsrHorizontalLineas(99, "verde", "23-84"); ...</script>


Hay más formas, igual alguna te funciona.
Quizás puedas mezclar varias cosas: Simplificar las imágenes, reducirle el tamaño utilizando algoritmos de compresión para expandirla luego con código. Utilizar codificaciones óptimas como trabajar con caracteres ascii en lugar de su homólogo en bytes... Convertir colores muy similares en el mismo para mejorar la compresión a costa de calidad. Convertir imágenes a jpg de alta compresión y baja resolución...
También hay algoritmos para apartir de imágenes de baja calidad ampliarlas y mejorarlas.


Desde luego no es algo nimio, pero no es imposible hacer algo decente con mucho curro creo yo. Quizás incluso te podría rentar más aprovecharte de como leen los lectores de QR para juguetear con ello y que procese más info de la que hay.



Te dejo un script sencillo que hice para que no me copien imágnes. Le pones la url de una imagen, te extrae los píxeles y te la recrea con tags. A ti la parte que te interesa es la de extraer la imagen, meterla en el canvas y obtener los colores de los píxeles. A partir de ahí es cosa tuya representar la misma info con menos espacio.
Código (javascript) [Seleccionar]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OCR</title>
<script>
/* SHORTCUTJS lib by StringManolo.
Use of the global Scope to code faster, reduce file sizes, reduce memory usage and make some code more readable/compact. Readable Version */
(function (){
DEFINE=function(constant, value) {
if(window[constant]===undefined) {
window[constant] = value
} else {
throw new ReferenceError(constant + " is already a property of the global/window Object.\nRedefinition not allowed.");
}
}


wrapQS=function(selector) {
return d.querySelector(selector)
}


wrapQSA=function(selector) {
return d.querySelectorAll(selector)
}


wrapAEL=function(elemnt, event, value) {
elemnt.addEventListener(event, value);
}


wrapDCE=function(element) {
return d.createElement(element);
}


wrapUCOU=function(url) {
return URL.createObjectURL(url)
}




DEFINE("d", window.document);
DEFINE("w", window);
DEFINE("$", wrapQS);
DEFINE("$$", wrapQSA);
DEFINE("dw", d.write);
DEFINE("_", window.alert);
DEFINE("ael", wrapAEL);
DEFINE("dce", wrapDCE);
DEFINE("ucou", URL.createObjectURL);


})();
</script>
</head>
<body>
<canvas id="canv" width="300" height="300"></canvas>
<div id="output"></div>
<!-- <a href="" id="a">click here to download your file</a> -->
<style>
canvas {
background-color: blue;
}


body {
background-color: #000;
font-size: 2px;
}


span {
padding: 0;
letter-spacing: -1;
}


</style>
<script>
/* DOWNLOAD IMAGE CROSSORIGEN: (to avoid tainted canvas) */
const request = fetch("https://cors-anywhere.herokuapp.com/" + prompt("Introduce URL de imagen. Ej: google.com/favicon.ico"));
request.then(function(resp) {
return resp.blob();
}).then(function(blob) {
let img = dce("img");
const blobURL = ucou(blob);
img.src = blobURL;
img.id = "imagen";
d.body.append(img);
_("Imagen añadida");
}).then(function(){
ael($("#imagen"), "load", function(){LIIC()});
}).catch(function(error) {
_("Error: " + error);
})




/* LOAD IMAGE INTO CANVAS */
function LIIC() {
let canvas = $("#canv");


let contexto = canvas.getContext("2d");
let imagen = $("#imagen");
canvas.width = imagen.width;
canvas.height = imagen.height;
contexto.drawImage(imagen,0,0);


SacarPixeles();


/* GET PIXELS IMAGE COLOR AND DRAW A IMAGE */
function SacarPixeles(){
let dataImagen = contexto.getImageData(0,0, canvas.width, canvas.height);
_("Tamaño imagen data: " + dataImagen.data.length);


let pixR =[], pixG =[], pixB =[], pixA =[];




let k = "";
for(var i =0, j =0; i < dataImagen.data.length; i +=4, ++j) {
k += "Colores pixel" +(j+1)+ ": Rojo=" +dataImagen.data[i]+" \nVerde=" +dataImagen.data[i+1]+" \nAzul=" +dataImagen.data[i+2]+" \nAlfa=" +dataImagen.data[i+3]+"\n\n\n";
pixR[j] = dataImagen.data[i].toString(16);
pixG[j] = dataImagen.data[1+i].toString(16);
pixB[j] = dataImagen.data[2+i].toString(16);
pixA[j] = dataImagen.data[3+i].toString(16);
}


performance = d.createDocumentFragment();
for(var i=0; i < pixR.length; ++i) {
var tdiv=dce("b");
var tbr=dce("br");
if(i % canvas.width == 0) {
performance.appendChild(tbr);
}
/*
░▒▓█
*/
tdiv.innerHTML = "▓";
tdiv.style.color = "#"+pixR[i]+""+pixG[i]+""+pixB[i]+""+pixA[i]+"";
performance.appendChild(tdiv);
}
_("Escribiendo...");
$("#output").appendChild(performance);


_("Imagen percorrida");
_(k);
k = "";
}




}


</script>
</body>
</html>