Dados PNG Base64 para tela HTML5

90

Quero carregar uma imagem PNG codificada em Base64 para o elemento canvas. Eu tenho este código:

<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>

No Chrome 8, recebo o erro: Uncaught TypeError: Type error

E no Firebug do Firefox isto: "O tipo de um objeto é incompatível com o tipo esperado do parâmetro associado ao objeto" código: "17"

Nessa base64 está um quadrado PNG preto de 5x5px que fiz no GIMP e transformo-o em base64 no programa base64 do GNU / Linux.

Tomáš Nesrovnal
fonte

Respostas:

172

Pelo que parece, você precisa realmente passar a drawImage um objeto de imagem como

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>

Eu tentei em cromo e funciona bem.

Jerryf
fonte
8
Boa resposta, mas tem certeza de que isso funciona sempre? Descobri que é complicado desenhar uma imagem imediatamente após definir o src, porque você deve usar o onloadretorno de chamada para garantir que a imagem tenha terminado de carregar. 50% dos meus testes falharam porque a imagem não terminou de carregar.
Scott Rippey
Uau! Explosão do passado :). Você está certo. Se você estiver chamando drawImage logo depois de definir o src da imagem, provavelmente terá problemas e, dependendo da sua situação, provavelmente desejará usar onload para ter certeza de que a imagem está realmente carregada antes de tentar renderizar para a tela. O código acima foi apenas mais um exemplo mostrando que drawImage realmente requer um objeto de imagem e como passá-lo para ele.
Jerryf
8
Apenas como uma observação, se você estiver percorrendo várias telas, pode querer alterá-lo para de ctx.drawImage(this,0,0);modo que garanta que a variável de imagem se refere à imagem correta. Ótima resposta!
Dormouse
13
O evento onload deve ser definido antes do src. Às vezes, o src pode ser carregado instantaneamente e nunca disparar o evento onload
Totty.js
3
Mas, se o data:image/comprimento for grande, teremos414 (Request-URI Too Long
Sarath
17

A resposta de Jerryf é boa, exceto por uma falha.

O evento onload deve ser definido antes do src. Às vezes, o src pode ser carregado instantaneamente e nunca disparar o evento onload.

(Como Totty.js apontou.)

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";
John
fonte
2
A propósito: editei a resposta de Jerryf, mas alguém a rejeitou. Não pode ter sido Jerryf, pois seu perfil diz que ele foi registrado pela última vez em 2014.
John,
3
"Às vezes, o src pode ser carregado instantaneamente e nunca disparar o evento onload." Acho que a ocorrência disso é extremamente rara a quase nunca, mas não há razão para não criar o hábito de definir onloadantes src... Tenho o hábito de fazê-lo.
marco de
2
@markE Não é raro. Isso acontecerá o tempo todo quando o navegador armazenar a imagem em cache, por exemplo, em uma atualização do navegador. Isso aconteceu em um mecanismo do IE em um programa c ++.
Stefan Rein