I am trying to load multiple images in a loop but no idea why it ain't working.
LoadCharactersImages2:function(Layer,roomObject)
{
var imgs = Array(5);
var ImgBanners = Array(5);
var sources = Array(5);
var locationX = 100; //x coordinate location of image
var self = this;
self.ImgloadCount = 0;
sources[0] = "images/pacman/pacman_right.png";
sources[1] = "images/pacman/pinkdown.png";
sources[2] = "images/pacman/redleft.png";
sources[3] = "images/pacman/yellowup.png";
sources[4] = "images/pacman/blueright.png";
for(var i = 0 ; i < 5;i++)
{
imgs[i] = new Image();
imgs[i].src = sources[i];
imgs[i].onload = function() {
ImgBanners[i] = new Kinetic.Image({
x: locationX,
y: 100,
image: imgs[i],
});
Layer.add(ImgBanners[i]);
self.ImgloadCount++;
self.AddtoStage(Layer,self);
self.LoadUsersImages(self,roomObject,Layer);
}
locationX = locationX + 100;
}
},
AddtoStage:function(layer,self)
{
if(self.ImgloadCount == 5)
self.stage.add(layer);
},
AddtoStage will add layer to stage when all the images are loaded. Now why it is not showing images on the canvas whats the problem ?
EDIT:
Now i edited the code to work it with closures as #zeta suggested but still no success.Here's the edited code.
imgs[i].onload = (function(index){
return function() {
ImgBanners[index] = new Kinetic.Image({
x: locationX,
y: 100,
image: imgs[index],
});
Layer.add(ImgBanners[index]);
self.ImgloadCount++;
self.AddtoStage(Layer,self);
self.LoadUsersImages(self,roomObject,Layer);
Layer.draw();
}
})(i);
You need a closure:
imgs[i].onload = (function(index){
return function() {
ImgBanners[index] = new Kinetic.Image({
x: locationX,
y: 100,
image: imgs[index],
});
})(i);
See also:
How do JavaScript closures work?
Please have a look at that link. Loads images in a loop of coffeescript
https://gist.github.com/4589644
I solved the problem by removing return function from the statement.
Related
I have a very strange behaviour of my script: only from time to time (seldom 3-4 times at one time right after each other, but more likely every 7th to 150th trial) the skript loads, but I only see a white canvas and get the error message:
Uncaught TypeError: Cannot read property 'getParent' of
undefinedKonva.Util.addMethods.add # konva.min.js:44draw #
floorplansurvey.php:950(anonymous function) #
floorplansurvey.php:985images.(anonymous function).onload #
floorplansurvey.php:390
On reload it often works again...
I just have no idea at all what is happening here, the bug can't be forced/reproduced, I thank you so much, if you have anything you can help me with. Even a strategy for a clearer analysis would be helpful, sorry for being that unspecific and the long code
edit: I've made a jsfiddle under:
https://jsfiddle.net/17548hmv/1/
run it several times, until the error occures
these are the code snippets at:
# floorplansurvey.php:390:
function loadImages(sources, draw) {
//window.location.reload(true);
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
draw(images);
}
};
images[src].src = sources[src];
}
delete (loadedImages);
delete (numImages);
};
# floorplansurvey.php:985images.(anonymous function).onload:
loadImages(sources, function(images) {
draw(images);
});
# floorplansurvey.php:950(anonymous function):
bglayer.add(plan);
# konva.min.js:44draw:
I dont understand this one myself
add:function(t)
{if(arguments.length>1)
{for(var e=0;e<arguments.length;e++)
this.add(arguments[e]);
return this}if(t.getParent())return t.moveTo(this),this;
var n=this.children;
return
Var sources is defined like:
var sources = {
Cd: './graphics/Cd.png',
Cu: './graphics/Cu.png',
Ca: './graphics/Ca.png',
Cs: './graphics/Cs.png',
Cc: './graphics/Cc.png',
Ed: './graphics/Ed.png',
Eu: './graphics/Eu.png',
Ea: './graphics/Ea.png',
Es: './graphics/Es.png',
Ec: './graphics/Ec.png',
Hd: './graphics/Hd.png',
Hu: './graphics/Hu.png',
...and so on
and this is the function draw:
function draw(images) {
for (i=0, len=showdatax.length; i<=len-1; i++)
{
//window.location.reload(true);
var gridcell = new Konva.Rect({
x: parseInt((imagesizeX - showdatax[i])*scalar-(gridcellsize/2)),
y: parseInt((imagesizeY - showdatay[i])*scalar-(gridcellsize/2)),
offset: [0, 0],
width: gridcellsize,
height: gridcellsize,
//fill: 'white',
//stroke: 'grey',
//strokeWidth: 2,
draggable: false,
id: showdatav[i]
});
gridlayer.add(gridcell);
}
//defaultsettiongs
var init = new Array();
init['x'] = new Array();
init['y'] = new Array();
init['x']['c'] = 0*scalar;
init['y']['c'] = 170*scalar;
init['x']['e'] = 0*scalar;
init['y']['e'] = 320*scalar;
init['x']['h'] = 0*scalar;
init['y']['h'] = 470*scalar;
init['x']['l'] = 0*scalar;
init['y']['l'] = 620*scalar;
init['x']['s'] = 0*scalar;
init['y']['s'] = 770*scalar;
init['x']['w'] = 0*scalar;
init['y']['w'] = 920*scalar; var step = 0;
var count = new Array (
'c','e','h','l','s','w');
count['c'] = 0;
count['e'] = 0;
count['h'] = 0;
count['l'] = 0;
count['s'] = 0;
count['w'] = 0;
var starttime = new Date();
var loghistory = '';
//drag event functions
function mouseoverbox (box,active)
{
writeMessage('Click and hold the left mouse button and pull this activity icon to the floorplan.');
box.setFillPatternImage(active);
box.shadowColor('blue');
box.moveTo(templayer);
badgelayer.draw();
templayer.draw();
}
function dragstarttouchstartbox (box,pos,kind)
{
//count[kind]++;
writeMessage('dragstart' + count[kind]);
var boxx = box.x;
box.x(pos.x-1.5*gridcellsize);
var boxy = box.y;
box.y(pos.y-1.5*gridcellsize);
var boxrshadowoffsetx = box.shadowOffset();
box.shadowOffset({x:0.25*gridcellsize,y:0.25*gridcellsize});
box.moveTo(templayer);
badgelayer.draw();
templayer.draw();
}
function dragmovebox (box,pos,kind,success,active,caution)
{
writeMessage('Your outside of the floorplan. Dropping the activity icon will reset it to its initial position.');
box.moveTo(templayer);
var boxx = box.x;
box.x(pos.x-1.5*gridcellsize);
var boxy = box.y;
box.y(pos.y-1.5*gridcellsize);
var shape = gridlayer.getIntersection(pos);
if (shape)
{
if (!badgelayer.getIntersection(pos))
{
writeMessage('Release the mouse button to place this activity icon on position (' + shape.x() + '|' + shape.y() + ')');
box.x(shape.x()-gridcellsize);
box.y(shape.y()-gridcellsize);
box.setFillPatternImage(success);
box.shadowColor('green');
badgelayer.draw();
}
else
{
writeMessage('Position (' + shape.x() + '|' + shape.y() + ') is in use!!! Can\'t allocate second activiy icon here.');
var boxx = box.x;
box.x(pos.x-1.5*gridcellsize);
var boxy = box.y;
box.y(pos.y-1.5*gridcellsize);
box.setFillPatternImage(caution);
box.shadowColor('red');
badgelayer.draw();
}
}
else
{
box.setFillPatternImage(active);
box.shadowColor('blue');
templayer.draw();
badgelayer.draw();
}
}
function dragendtouchendbox (box,pos,kind,caution,defaultimage)
{
var shape = gridlayer.getIntersection(pos);
box.moveTo(badgelayer);
templayer.draw();
if (shape && !(badgelayer.getIntersection(pos)))
{
writeMessage('Activity icon successfully placed at position (' + shape.x() + '|' + shape.y() + ').');
box.shadowOffset({x:0,y:0});
box.shadowColor('green');
}
else
{
box.shadowColor('red');
box.setFillPatternImage(caution);
badgelayer.draw();
var fromouttween = new Konva.Tween
({
node: box,
x: init['x'][kind]+imagesizeX*scalar+ gridcellsize,
y: init['y'][kind],
easing: Konva.Easings['EaseOut'],
duration: 0.3
});
if (!shape)
{
writeMessage('Please drop the activity icons inside the floorplan.');
}
else if (badgelayer.getIntersection(pos))
{
writeMessage('Please don\'t drop the activity icons onto a used place.');
}
fromouttween.play();
box.shadowColor('black');
box.setFillPatternImage(defaultimage);
box.shadowOffset({x:0,y:0});
badgelayer.draw();
pos.x=-100;
pos.y=-100;
}
count['kind']++;
step++;
writeResultToForm(pos,count,kind,step,loghistory,starttime);
badgelayer.draw();
templayer.draw();
//writeMessage('dragend');
}
function mouseoutbox (box,defaultimage)
{
box.setFillPatternImage(defaultimage);
box.moveTo(badgelayer);
box.shadowColor('black');
if (!validateForm(false))
{
writeMessage('There are still activity icons left to place.');
}
else
{
writeMessage('All activity icons are placed successfully. You can click "continue" now or change your placements.');
}
badgelayer.draw();
templayer.draw();
}
function alertbox (box,caution)
{
box.setFillPatternImage(caution);
box.shadowcolor('red');
badgelayer.draw;
}
//cbox and text
var textc = new Konva.Text({
x: init['x']['c']+imagesizeX*scalar+gridcellsize*5,
y: init['y']['c']+gridcellsize,
text: 'Cooking',
align: 'left',
width: badgetextwidth
});
var boxc = new Konva.Rect({
x: init['x']['c']+imagesizeX*scalar+gridcellsize,
y: init['y']['c'],
offset: [0, 0],
width: 3*gridcellsize,
height: 3*gridcellsize,
fillPatternImage: images.Cd,
fillPatternScaleX: scalar,
fillPatternScaleY: scalar,
stroke: 'black',
strokeWidth: 4,
draggable: true,
cornerRadius: gridcellsize/2,
shadowColor: 'black',
shadowBlur: 10,
shadowOffset: {x : 0, y : 0},
shadowOpacity: 0.5
});
var boxcd = new Konva.Rect({
x: init['x']['c']+imagesizeX*scalar+gridcellsize,
y: init['y']['c'],
offset: [0, 0],
width: 3*gridcellsize,
height: 3*gridcellsize,
fillPatternImage: images.Cu,
fillPatternScaleX: scalar,
fillPatternScaleY: scalar,
stroke: 'grey',
strokeWidth: 2,
draggable: false,
cornerRadius: gridcellsize/2,
});
boxc.on('mouseover ', function() {
mouseoverbox (this,images.Ca);
});
boxc.on('dragstart', function() {
var pos = stage.getPointerPosition();
dragstarttouchstartbox (this,pos,'c');
});
boxc.on('dragmove', function () {
var pos = stage.getPointerPosition();
dragmovebox(this,pos,'c',images.Cs,images.Ca,images.Cc);
});
boxc.on('dragend', function() {
var pos = stage.getPointerPosition();
dragendtouchendbox (this,pos,'c',images.Cc,images.Cd);
});
boxc.on('mouseout ', function() {
mouseoutbox (this,images.Cd)
});
boxc.on('foo', function() {
alertbox (this,images.Cd)
});
//ebox and text
var texte = new Konva.Text({
x: init['x']['e']+imagesizeX*scalar+gridcellsize*5,
...and so on for all the boxes addes here (5 times as long):
defaultlayer.add(boxcd);
badgelayer.add(boxc);
defaultlayer.add(textc);
defaultlayer.add(boxed);
badgelayer.add(boxe);
defaultlayer.add(texte);
defaultlayer.add(boxhd);
badgelayer.add(boxh);
defaultlayer.add(texth);
defaultlayer.add(boxld);
badgelayer.add(boxl);
defaultlayer.add(textl);
defaultlayer.add(boxsd);
badgelayer.add(boxs);
defaultlayer.add(texts);
defaultlayer.add(boxwd);
badgelayer.add(boxw);
defaultlayer.add(textw);
stage.add(bglayer);
stage.add(gridlayer);
stage.add(defaultlayer);
stage.add(badgelayer);
stage.add(templayer);
}
OK, sorry that it took me so long:
the solution wasn't that easy to find. I found that the script was loaded asynchronously and the png wasn't yet available by using chromes timeline analysis. so i went to my code and had to distinguish between the things, that really should be in the draw function and which not. i added the plan to the array of images (sources) that is loaded (src= ...) before executing draw() and then added
sources.onload= loadImages(sources, function(images) {
draw(images);
});
at the end of my file... no it works without any problem. konva.js had nothing to do with it and is up to now (I'm almost ready) like designed for my project
thanks for the tip #lavrton, it took me on the right way
and you can just put like this:
var imageObj = new Image();
imageObj.src = 'http://localhost:8000/plugins/kamiyar/logo.png';
imageObj.onload = function() {
var img = new Konva.Image({
image: imageObj,
x: stage.getWidth() / 2 - 200 / 2,
y: stage.getHeight() / 2 - 137 / 2,
width: 200,
height: 137,
draggable: true,
stroke: 'blue',
strokeWidth: 1,
dash: [1,5],
strokeEnabled: false
});
layer.add(img);
layer.draw();
};
sorry for my bad English ;)
Before your read this, my first account was blocked because i asked bad questions.. So please dont vote negative but say what i am doing wrong
Sooo I have this script:
var img1 = new Image()
img1.src="image1.jpg"
var img2 = new Image()
img2.src="image2.jpg"
var img3 = new Image()
img3.src="image3.jpg"
function Canvas() {
var ctx = document.getElementById('slider').getContext('2d');
var pic=1
function slider() {
this.draw = function() {
if(pic<4){pic++}
else{
pic=1
}
var img = "img"+pic
ctx.drawImage(img,0,0,ctx.canvas.width,ctx.canvas.height)
}
}
var slider = new slider();
function draw() {
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
ctx.save();
//draw
slider.draw();
//draw
ctx.restore();
}
var animateInterval = setInterval(draw,100)
}
window.addEventListener('load', function(event) {
Canvas();
});
I am trying to draw the image 1 or 2 or 3 on my canvas. But I also have the var pic wich has the number. So i tried ctx.drawimage(img+pic,0,0) or var img = "img"+pic and draw it then. But it doesnt work for me.
I hope you accept my question and can answer it, THNX
Use an array instead
var img = [];
/* you should use a for loop here */
for (var i = 0; i < 3; i++) {
img[i] = new Image();
img[i].src = "image" + (i+1) ".jpg";
}
and later you refer the right image with img[pic]. Be only sure to use an index between 0 and img.length - 1
Don't use separate variables, use an array.
var images = [ new Image(), new Image(), new Image() ];
for (var i = 0; i < images.length; i++) {
images[i].src = "image" + (i+1) + ".jpg";
}
Then refer to the array in the Slider() function:
var pic = 0;
function slider() {
this.draw = function() {
pic = (pic + 1) % images.length;
var img = images[pic];
ctx.drawImage(img,0,0,ctx.canvas.width,ctx.canvas.height)
}
}
The error seems to be that you refer to the string "img1" and not the object img1. Try use an array instead.
Set the following:
...
var pic=0;
var img=[img1,img2,img3];
function slider() {
this.draw = function() {
if(pic<3){pic++}
else{
pic=0;
}
ctx.drawImage(img[pic],0,0,ctx.canvas.width,ctx.canvas.height)
}
}
...
I have a canvas animation that has been created with createjs. The entire animation script including init() function is loaded via jquery: $.getScript() on page load.
The init() and handlecomplete() function included below is then run which attaches the animation to a html canvas element on the page.
var canvas, stage, exportRoot, audio;
var tweens = [];
function init() {
canvas = document.getElementById("canvas");
images = images||{};
if (stage) {
stage.enableDOMEvents(false);
stage.removeAllChildren();
createjs.Ticker.removeAllEventListeners()
stage.enableDOMEvents(true);
}
if (audio ) {
audio.stop();
}
removeTweens();
exportRoot = null;
audio = null;
stage = null;
var loader = new createjs.LoadQueue(false);
loader.installPlugin(createjs.Sound);
loader.addEventListener("fileload", handleFileLoad);
loader.addEventListener("complete", handleComplete);
loader.loadManifest(lib.properties.manifest);
}
function handleComplete() {
exportRoot = new lib.animation2();
stage = new createjs.Stage(canvas);
stage.addChild(exportRoot);
stage.update();
stage.canvas.width = 1280;
stage.canvas.height = 720;
resizeToFit();
stage.update();
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", stage);
createjs.Ticker.addEventListener("tick", updateTimer);
if (lib.properties.audiovolume) {
audio = createjs.Sound.play("audio", createjs.Sound.INTERRUPT_EARLY, 0, 0, -1, lib.properties.audiovolume);
}
exportRoot.gotoAndPlay(startFrame );
}
My issue is when the user makes a change, we load the script a second time using the same jquery method which returns the updated script. The init() function then executes properly and the new animation plays correctly, but our animated text (using the animateText below) does not appear on the canvas. This function is also loaded dynamically with other functions.
Checking the tween arrays, they are being created and removed as required, but they are not visible.
They are either layered behind the new animation, or not being attached to the new canvas or something else?
Simply refreshing the page will then load the new script and text properly. So clearly something in the dynamic loading of the script?
var animateText = function(localString, startX, startY, letterClip, endObject, font, color) {
var waitAmount = 0;
var offSetAmount = 20;
for(var i = 0; i < localString.length; i++){
var fl_MyInstance = new letterClip();
fl_MyInstance.localName.text = localString[i];
if(font != null){
fl_MyInstance.localName.font = font;
}
if(color != null){
fl_MyInstance.localName.color = color;
}
var localX = startX;
var localY = startY;
fl_MyInstance.x = startX + offSetAmount;
var beginX = startX + offSetAmount
offSetAmount = offSetAmount - 4
fl_MyInstance.y = startY;
fl_MyInstance.alpha = 0;
fl_MyInstance.scaleX = 0.1;
fl_MyInstance.scaleY = 0.1;
var bounds = fl_MyInstance.getBounds();
startX += bounds.width + 0;
var target = fl_MyInstance;
var tween = createjs.Tween.get(target, {
loop: false
}).wait(waitAmount)
.to({
x: localX,
y: localY,
alpha: 1,
scaleX: 1,
scaleY: 1
}, 400, createjs.Ease.circOut);
tween.waitAmount = waitAmount;
if(endObject == null){
tween.endObject = {
x: localX,
y: localY,
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}
} else {
tween.endObject = {
x: localX - endObject.x,
y: localY - endObject.y,
alpha: endObject.alpha,
scaleX: endObject.scaleX,
scaleY: endObject.scaleY
}
}
tween.targetClip = fl_MyInstance;
tween.arrayIndex = tweens.length;
tweens.push(tween);
waitAmount += 20;
stage.addChild(fl_MyInstance);
}
}
var removeTweens = function(){
for(var i = 0; i<tweens.length; i++){
if(tweens[i] != null){
var tween = tweens[i];
stage.removeChild(tween.targetClip);
tweens[tween.arrayIndex] = null;
}
}
}
var closeTweens = function(){
for(var i = 0; i<tweens.length; i++){
if(tweens[i] != null){
var tween = tweens[i];
createjs.Tween.get(tween.targetClip, {
loop: false
}).wait(tween.waitAmount).to(tween.endObject, 400, createjs.Ease.circOut).call(function(){
stage.removeChild(tween.targetClip);
tweens[tween.arrayIndex] = null;
});
}
}
}
var finalTweens = function(){
for(var i = 0; i<tweens.length; i++){
if(tweens[i] != null){
var tween = tweens[i];
createjs.Tween.get(tween.targetClip, {
loop: false
}).to(tween.endObject, 400, createjs.Ease.circOut);
}
}
}
Since the rest of the animation works perfectly using this method of dynamic loading, I don't think it is something in the loading. But there must be something missing in animateText and reloading functions that causes the issue.
I'm starting to use Jasmine to run tests on my code. Most of the tests so far have been fairly primitive but I'm now facing a problem when checking to see if an array has been populated.
the test is:
describe("create grid of layers", function() {
var result = new Array(4);
it("returns an array of objects as a grid", function() {
result = randomQuadrants();
expect( result).toBeDefined();
});
});
I've also tried:
describe("create grid of layers", function() {
var result = new Array(4);
it("returns an array of objects as a grid", function() {
expect(result = randomQuadrants()).toBeDefined();
});
});
as well but am receiving an error of ReferenceError: fabric is not defined at this line var obj = new fabric.GeologicalObject({ in the following code.
function randomQuadrants() {
var posX, posY;
posY = 175;
for (var i=0; i<10; i++){
//declaring random num here makes each layer the same but random.
grid[i] = new Array(6);
posX = 100;
for(j=0; j<10; j++) {
//random num here makes each square a random layer
var randomNum = random_num(layerDetails.length);
var obj = new fabric.GeologicalObject({
strength: layerDetails[randomNum].strength,
minSpeed: layerDetails[randomNum].minSpeed ,
maxSpeed: layerDetails[randomNum].maxSpeed,
width: 200,
height: 75,
left: posX,
top: posY,
fill: 'red'
});
posX = parseInt(posX) + 200;
loadPattern(obj, layerDetails[randomNum].pattern);
grid[i][j] = obj;
}
posY+=75;
}
return grid;
}
Thanks for any help!
I have been trying to make a script that compares two images in HTML5 and Javascript. But for some odd reason, it always returns that the images are completely the same.
And when looking at what the problem could be, I found out that every data value of every pixel returned, for some odd reason, "0".
So, any idea of what I have done wrong? :)
For some reason I feel like it's something very simple, but I just learned about the canvas element, so yeah.
This is my code:
function compareImg() {
var c1 = document.getElementById("c");
var ctx1 = c1.getContext("2d");
var c2 = document.getElementById("c2");
var ctx2 = c2.getContext("2d");
var match = 0;
var img1 = new Image();
img1.src = "cat.jpg";
img1.onload = function() {
ctx1.drawImage(img1, 0, 0);
}
var img2 = new Image();
img2.src = "bird.jpg";
img2.onload = function() {
ctx2.drawImage(img2, 0, 0);
}
for(var x = 0; x<c1.width; x++) { // For each x value
for(var y = 0; y<c1.height; y++) { // For each y value
var data1 = ctx1.getImageData(x, y, 1, 1);
var data2 = ctx2.getImageData(x, y, 1, 1);
if (data1.data[0] == data2.data[0] && data1.data[1] == data2.data[1] && data1.data[2] == data2.data[2]) {
match++;
}
}
}
var pixels = c1.width*c1.height;
match = match/pixels*100;
document.getElementById("match").innerHTML = match + "%";
}
You are not waiting until your images have loaded and drawn before performing your comparison. Try this:
var img = new Image;
img.onload = function(){
ctx1.drawImage(img,0,0);
var img = new Image;
img.onload = function(){
ctx2.drawImage(img,0,0);
// diff them here
};
img.src = 'cat.jpg';
};
img.src = 'cat.jpg';
As shown above, you should always set your src after your onload.
I suspect that the problem is that your image data is probably not ready at the point you try to use it for the canvas. If you defer that code to the onload handlers, that will (probably) help:
var img1 = new Image(), count = 2;
img1.src = "cat.jpg";
img1.onload = function() {
ctx1.drawImage(img1, 0, 0);
checkReadiness();
}
var img2 = new Image();
img2.src = "bird.jpg";
img2.onload = function() {
ctx2.drawImage(img2, 0, 0);
checkReadiness();
}
function checkReadiness() {
if (--count !== 0) return;
for(var x = 0; x<c1.width; x++) { // For each x value
for(var y = 0; y<c1.height; y++) { // For each y value
var data1 = ctx1.getImageData(x, y, 1, 1);
var data2 = ctx2.getImageData(x, y, 1, 1);
if (data1.data[0] == data2.data[0] && data1.data[1] == data2.data[1] && data1.data[2] == data2.data[2]) {
match++;
}
}
}
var pixels = c1.width*c1.height;
match = match/pixels*100;
document.getElementById("match").innerHTML = match + "%";
}
All I did was add a function wrapper around your code. That function checks the image count variable I added, and only when it's zero (i.e., only after both images have loaded) will it do the work.
(This may be superstition, but I always assign the "onload" handler before I set the "src" attribute. I have this idea that, perhaps only in the past, browsers might fail to run the handler if the image is already in the cache.)
Now another thing: you probably should just get the image data once, and then iterate over the returned data. Calling "getImageData()" for every single pixel is going to be a lot of work for the browser to do.