harristyle harristyle - 3 months ago 5
Javascript Question

canvas context getImageData() function won't execute, probably because it's executed before the image is loaded

what I'm trying to do is draw an image to an html canvas using only javascript, and by using the getImageData() function, I'm trying to get the image's bits and then manipulate them in multiple ways.

however, because i'm loading the image using javascript, my suspicion is that the image can't load in time before the call to getImageData(), so the program just stops working when that call is made, as you can see the _log(3) statement isn't being called.

this happens even though I've called getImageData() function inside the images onload() event.

i've already seen a few suggestions in some other stackoverflow threads regarding this issue, but none of them seem to work for me.

any help in the right direction would be really appreciated.

here's the jsfiddle: https://jsfiddle.net/houqdfx9/2/

this is the html:

<p id="log"></p>


this is the javascript:

function _log(string){
document.getElementById("log").innerHTML += string;
}

function _createCanvas(){
var canvas = document.createElement("canvas");
canvas.setAttribute("id", "canvas");
document.body.appendChild(canvas);
return canvas;
}

function _drawAndProcessImage(img, ctx){
ctx.drawImage(img, 0, 0);
_log(img.width + " " + img.height + " ");
var img_data = ctx.getImageData(0,0,img.width,img.height);
_log(3);

/* DO THINGS WITH THE IMG_DATA HERE */
}

function setCanvasAndLoadImage(url, canvas, callback) {
var img = new Image;
var ctx = canvas.getContext("2d");
img.onload = function(){callback(img, ctx);};
img.src = url;
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
};

var canvas = _createCanvas();

setCanvasAndLoadImage("https://pixabay.com/static/uploads/photo/2014/02/01/17/30/apple-256267_960_720.jpg", canvas, _drawAndProcessImage);

Answer

Please try this. This works. But, there is a cross domain violation because of the different domains. You would need to proxy this through a server maybe. See this for a solution.

function _log(string){
    document.getElementById("log").innerHTML += string; 
}

function _createCanvas(){
  var canvas = document.createElement("canvas");
  canvas.setAttribute("id", "canvas");
  document.body.appendChild(canvas);
  return canvas;
}

function _drawAndProcessImage(img, ctx){
    ctx.drawImage(img, 0, 0);
    _log(img.width + " " + img.height + " ");
    var img_data = ctx.getImageData(0,0,img.width,img.height);
    _log(3);

    /* DO THINGS WITH THE IMG_DATA HERE */
}

function setCanvasAndLoadImage(url, canvas, callback) {
   var img = new Image;
   var ctx = canvas.getContext("2d"); 
   img.onload = function() {
     canvas.width = img.naturalWidth;
     canvas.height = img.naturalHeight;

     callback(img, ctx);
   };
   img.src = url;
};

var canvas = _createCanvas();

setCanvasAndLoadImage("https://pixabay.com/static/uploads/photo/2014/02/01/17/30/apple-256267_960_720.jpg", canvas, _drawAndProcessImage);
<p id="log"></p>