Datos PNG Base64 a lienzo HTML5

89

Quiero cargar una imagen PNG codificada en Base64 al elemento canvas. Tengo este codigo:

<html>
<head>
</head>
<body>
<canvas id="c"></canvas>
<script type="text/javascript">

var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");

data =  "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMCRUiMrIBQVkAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12NgoC4AAABQAAEiE+h1AAAAAElFTkSuQmCC";

ctx.drawImage(data, 0, 0);

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

En Chrome 8 aparece el error: Uncaught TypeError: Type error

Y en Firebug de Firefox esto: "El tipo de un objeto es incompatible con el tipo esperado del parámetro asociado al objeto" código: "17"

En esa base64 hay un cuadrado PNG negro de 5x5px que hice en GIMP y lo cambié a base64 en el programa base64 de GNU / Linux.

Tomáš Nesrovnal
fuente

Respuestas:

170

Por lo que parece, debe pasar a drawImage un objeto de imagen como ese

var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");

var image = new Image();
image.onload = function() {
  ctx.drawImage(image, 0, 0);
};
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMCRUiMrIBQVkAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12NgoC4AAABQAAEiE+h1AAAAAElFTkSuQmCC";
<canvas id="c"></canvas>

Lo probé en Chrome y funciona bien.

Jerryf
fuente
8
Buena respuesta, pero ¿estás seguro de que esto funciona siempre? Me pareció complicado dibujar una imagen inmediatamente después de configurar src, porque se supone que debes usar la onloaddevolución de llamada para asegurarte de que la imagen haya terminado de cargarse. El 50% de mis pruebas fallaron porque la imagen no se había terminado de cargar.
Scott Rippey
¡Guauu! Explosión del pasado :). Tienes toda la razón. Si está llamando a drawImage justo después de haber configurado el src de la imagen, probablemente tendrá problemas y, dependiendo de su situación, probablemente querrá usar onload para asegurarse de que la imagen esté realmente cargada antes de intentar renderizar. al lienzo. El código anterior era más bien un ejemplo que muestra que drawImage realmente requiere un objeto de imagen y cómo pasarlo.
Jerryf
8
Solo como una nota, si está recorriendo varios lienzos, es posible que desee cambiarlo para ctx.drawImage(this,0,0);garantizar que la variable de imagen se refiera a la imagen correcta. ¡Sin embargo, gran respuesta!
Lirón
13
El evento onload debe establecerse antes que src. A veces, el src se puede cargar instantáneamente y nunca disparar el evento onload
Totty.js
3
Pero, si la data:image/longitud es grande, obtendremos414 (Request-URI Too Long
Sarath
17

La respuesta de Jerryf está bien, excepto por un defecto.

El evento onload debe establecerse antes que src. A veces, el src se puede cargar instantáneamente y nunca disparar el evento onload.

(Como señaló Totty.js).

var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");

var image = new Image();
image.onload = function() {
    ctx.drawImage(image, 0, 0);
};
image.src = "data:image/  png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMCRUiMrIBQVkAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12NgoC4AAABQAAEiE+h1AAAAAElFTkSuQmCC";
Juan
fuente
2
Por cierto: edité la respuesta de Jerryf, pero alguien la rechazó. No puede haber sido Jerryf, ya que su perfil dice que inició sesión por última vez en 2014.
John
2
"A veces, el src se puede cargar instantáneamente y nunca disparar el evento onload". Creo que la ocurrencia de esto es extremadamente rara o casi nunca, pero no hay razón para no convertirlo en un hábito de establecer onloadantes src... Yo lo hago por hábito.
MarkE
2
@markE No es raro. Ocurrirá todo el tiempo cuando el navegador almacena en caché la imagen, por ejemplo, en una recarga del navegador. Esto sucedió en un motor IE en un programa c ++.
Stefan Rein