pgjvzhk - Javascript: Renderiza PNG almacenado como Uint8Array en el elemento Canvas sin URI de datos
data uri to image (2)
Estoy tratando de renderizar una imagen PNG almacenada en un javascript Uint8Array
. El código que probé originalmente fue el siguiente:
var imgByteStr = String.fromCharCode.apply(null, this.imgBytes);
var pageImg = new Image();
pageImg.onload = function(e) {
// Draw onto the canvas
canvasContext.drawImage(pageImg, 0, 0);
};
// Attempt to generate the Data URI from the binary
// 3rd-party library adds toBase64() as a string function
pageImg.src="data:image/png;base64,"+encodeURIComponent(imgByteStr.toBase64());
Sin embargo, descubrí que, por alguna razón, la función de carga nunca se estaba ejecutando (tenía los puntos de interrupción configurados en Chrome y simplemente nunca los golpeaba). Descubrí que si configuraba el src en una URL en lugar de URI de datos, funcionaba correctamente. Sin embargo, debido a algunas limitaciones, no puedo referirme directamente a la URL de la imagen, es decir, debe cargarse desde UInt8Array
.
Además, para complicar un poco más las cosas, estas imágenes pueden tener un tamaño de megabytes. Según lo que he leído, existen problemas de compatibilidad con el intento de utilizar los URI de datos para imágenes muy grandes. Debido a esto, estoy muy indeciso para utilizarlos.
La pregunta, por lo tanto, es ¿cómo puedo renderizar esta matriz de bytes como PNG en un contexto canvas sin usar URI de datos o referirme directamente a la URL de la imagen?
También intenté usar algo como lo siguiente para manipular los datos de imagen directamente usando la función putImageData
. Tenga en cuenta que no entiendo al 100% cómo funciona esta función
var imgdata = canvasContext.createImageData(this.baseHeight, this.baseWidth);
var imgdatalen = imgdata.data.length;
for(var i=0; i<imgdatalen; i++) {
imgdata.data[i] = _this.imgBytes[i];
}
canvasContext.putImageData(imgdata, 0, 0);
Fue quitado de un blog cuya pestaña he cerrado desde entonces, así que le pido disculpas a la inspiración por no dar el crédito apropiado.
Además, mientras leje lentamente a esto, me encontré con un error en Chrome SECURITY_ERR: DOM Exception 18
. Resulta que, tan pronto como una imagen se carga en un lienzo usando drawImage, no se puede recuperar sin algunas soluciones adicionales. Una publicación de Chromium Blog sobre el tema fue especialmente útil
Si tiene los datos PNG en la memoria (que creo que es lo que está describiendo), puede crear una imagen a partir de él. En HTML, se vería así:
<img src="data:image/png;base64,KSjs9JdldhAlisflAkshf==" />
En JavaScript puedes hacer lo mismo:
var image = document.createElement(''img'');
image.src = ''data:image/png;base64,'' + base64Data;
Tenga en cuenta que puede cambiar el tipo MIME si no tiene datos PNG.
Luego puede dibujar la image
en su lienzo utilizando context.drawImage(image, 0, 0)
o similar.
Entonces, la parte restante del rompecabezas es codificar el contenido de su Uint8Array
en los datos de la Base 64.
var array = new Uint8Array(),
base64Data = btoa(String.fromCharCode.apply(null, array));
La función btoa
no es estándar, por lo que algunos navegadores pueden no ser compatibles. Sin embargo, parece que la mayoría lo hace . De lo contrario, es posible que encuentre útil algún código que utilizo .
¡No he probado nada de esto yo mismo!
Si ya tiene un UInt8Array, debería considerar usar Blob
y createObjectURL
; createObjectURL
asigna una URL especial que permite al navegador acceder a un blob de datos binarios creado internamente como si fuera un archivo cargado externamente.
Donde es compatible , createObjectURL
es una excelente alternativa a los enormes URI de datos. Es posible que aún deba recurrir al uso de URI de datos en Opera, IE <10 y todas, excepto las versiones más recientes de los navegadores móviles.
var myArray; //= your data in a UInt8Array
var blob = new Blob([myArray], {''type'': ''image/png''});
var URL = URL.createObjectURL(blob); //possibly `webkitURL` or another vendor prefix for old browsers.