phnjcmlwdd pgjvzhk pgh0bww pc9odg1spg pc9ib2r5pjwvahrtbd4 data convert javascript html5-canvas

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.