111

I want to load a PNG image encoded in Base64 to canvas element. I have this code:

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

In Chrome 8 I get the error: Uncaught TypeError: Type error

And in Firefox's Firebug this: "The type of an object is incompatible with the expected type of the parameter associated to the object" code: "17"

In that base64 is 5x5px black PNG square that I have made in GIMP and turn it to base64 in GNU/Linux's program base64.

Jongware
  • 22,200
  • 8
  • 54
  • 100
Tomáš Nesrovnal
  • 1,422
  • 3
  • 13
  • 15

2 Answers2

213

By the looks of it you need to actually pass drawImage an image object like so

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>

I've tried it in chrome and it works fine.

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
Jerryf
  • 2,633
  • 1
  • 16
  • 10
  • 11
    Good answer, but are you sure this works every time? I found it buggy to draw an image immediately after setting the `src`, because you're supposed to use the `onload` callback to ensure the image has finished loading. 50% of my tests failed because the image hadn't finished loading. – Scott Rippey Sep 06 '12 at 23:05
  • Wow! Blast from the past :). You’re quite correct. If you’re calling drawImage just after you’ve set the src of the image you probably will run into problems and depending on your situation you will most likely want to use onload to make sure that the image is actually loaded before you attempt to render it to the canvas. The above code was just more of an example showing that drawImage actually requires an image object and how to pass that to it. – Jerryf Sep 07 '12 at 11:00
  • 8
    Just as a note, if you're looping over a number of canvasses, you may want to change it to `ctx.drawImage(this,0,0);` so that it ensures the image variable refers to the correct image. Great answer though! – Dormouse Nov 26 '12 at 18:30
  • 14
    The onload event should be set before the src. Sometimes the src can be loaded instantly and never fire the onload event – Totty.js Mar 06 '13 at 22:05
  • Im having problems with the onload event in IE9 any suggestions? This code block works consistently in chrome and FF. – Akin Okegbile Nov 13 '13 at 22:19
  • how would you know the size? – user151496 Mar 01 '16 at 10:26
  • 3
    But, if the `data:image/` length is large we will get `414 (Request-URI Too Long` – Sarath Jul 14 '16 at 14:52
  • @Angel Politis, How to i can draw base64 video on canvas ? – Abhay Sharma Jul 26 '17 at 11:18
  • @Totty.js Do you know why that is? I was under the impression events (so `onload`) are macrotasks and can only run after the stack is clean. – Moo Mar 18 '20 at 15:10
22

Jerryf's answer is fine, except for one flaw.

The onload event should be set before the src. Sometimes the src can be loaded instantly and never fire the onload event.

(Like Totty.js pointed out.)

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

....

Bill2022
  • 29
  • 9
John
  • 605
  • 9
  • 28
  • 4
    **"Sometimes the src can be loaded instantly and never fire the onload event."** I think the occurence of this is extremely rare to almost never, but there's no reason not to make it a habit to set `onload` before `src`...I make it a habit to do so. – markE Apr 25 '15 at 04:23
  • 5
    @markE It is not rare. It will happen all the time when the browser caches the image, for example on a browser reload. This happened in an IE engine in a c++ program. – Stefan Rein Dec 22 '18 at 14:00