4
votes

In a first attempt to get some pixel manipulation done on a HTML5 canvas I've written a code to change a specific part of a background image. I'm using a mask image to mark the specific parts that need to be changed. And I'm drawing 2 vertical lines 1 pixel at a time. My code looks like:

var backgroundTemp=[0,0,false];

function generateBg(){
    var bgGenCanvas  = document.getElementById("backgroundGenerator");
    var bgGenCtx = bgGenCanvas.getContext("2d");

    var bgMaskCanvas  = document.getElementById("backgroundMask");
    var bgMaskCtx = bgMaskCanvas.getContext("2d");

    if(backgroundTemp[0]==0){
        var img = new Image();
        img.onload=function(){
            bgGenCtx.drawImage(this,0,0);
            backgroundTemp[0]++;
            generateBg();
        }
        backgroundTemp[0]++;
        img.src = 'images/ordnerGreen.png';
    }
    if(backgroundTemp[1]==0){
        var img = new Image();
        img.onload=function(){
            bgMaskCtx.drawImage(this,0,0);
            backgroundTemp[1]++;
            generateBg();
        }
        backgroundTemp[1]++;
        img.src = 'images/ordnerMask.png';
    }
    if(backgroundTemp[0]==2 && backgroundTemp[1]==2 && backgroundTemp[2]==false){
        backgroundTemp[2]=true;
        var newColor=hexToRgb(settings.ordnerColor);
        var genData = bgGenCtx.getImageData(0,0,bgGenCanvas.width,bgGenCanvas.height);
        var maskData = bgMaskCtx.getImageData(0,0,bgMaskCanvas.width,bgMaskCanvas.height);
        var darkenAt1=796*4;
        var darkenAt2=996*4;
        var widthPerLine=bgGenCanvas.width*4;
        for(var i=0;i<maskData.data.length;i+=4){
            var currentLine=Math.ceil(i/widthPerLine);

            var red=maskData.data[i];
            var green=maskData.data[i+1];
            var blue=maskData.data[i+2];

            if(red==255 && green==255 && blue==255){
                red=newColor.r;
                green=newColor.g;
                blue=newColor.b;
                if(darkenAt1==i || darkenAt2==i){
                    red-=Math.floor(red/4);
                    green-=Math.floor(green/4);
                    blue-=Math.floor(blue/4);
                    if(darkenAt1==i){
                        darkenAt1+=parseInt(widthPerLine);
                    }
                    if(darkenAt2==i){
                        darkenAt2+=parseInt(widthPerLine);
                    }
                }
                genData.data[i]=red;
                genData.data[i+1]=green;
                genData.data[i+2]=blue;
            }
        }
        bgGenCtx.putImageData(genData,0,0);
        document.getElementById('viewerBackground').style.backgroundImage="url('"+bgGenCanvas.toDataURL()+"')";
    }
}

$(window).load(function(){generateBg();});

At first it randomly did work or did not work. Sometimes the outcomes would be empty, sometimes the original image and sometimes the modified image. I figured the images might not have completed loading so i added a construction to ensure they would both be loaded. This worked for Firefox and Chrome. In IE however the problem is still there, every time i press F5 i get a random result.

Anyone knows how to fix this?

1
Can you please post a link to live demo so we could test it? We don't have the images.duri

1 Answers

2
votes

Depending on the images loading speed (and their availability in cache ) you may end up executing 3 times your pixel iteration instead of only once.

In the worst case scenario your onLoad listeners will be executed as soon as the src of the image is specified (if the image is available in cache)

To avoid this you should try to load your images sequentially (ie.loading backgroundTemp[1] image from backgroundTemp[0] onLoad function) and launch your pixel iteration stuff from the backgroundTemp[1] onLoad.