Search code examples
javascripthtmltextureswebglgetimagedata

Textures not loading in webgl. reading and manipulating from 2D canvas, storing in Array


I'm trying (newbie) to build an application in webgl. I've come to the point where I want to load an array of images, and do some pixel manipulations on it. I'm trying to get the first pixel-column of every picture in an array, and building a new picture with it. then pushing this newly generated picture in another array. (then taking the next column etc..)

I'm accomplishing this by drawing the images on an 2D canvas, and then reading back the pixels. After a couple of recursions I'm getting the desired image and write it using base64 encoding (and the PNGlib.js library) back to an array.

the problem is that the textures all stay black upon loading the page. This is so until I manually reload the page.

http://home.scarlet.be/~cornetp/ (only tested in firefox 4)

I want the images to show up immediately, if someone could have a look at it,

thanks,

    var crateTextures = Array();
    var crateArray = Array();
    var imageArray = Array();
    var crateImage
    var elem;
    var context;
    var r;
    var g;
    var b;

    function initTexture() {            
            cratefunction();
            for (var t=0; t < 3; t++) {
            var texture = gl.createTexture();
            texture.image = crateArray[t];
            crateTextures.push(texture);            
        }

        crateArray[0].onload = function () {
            handleLoadedTexture(crateTextures)
        }

    }
    function cratefunction(){
        initImages();
        toSagitaal();   
    }   
    function toSagitaal(){
        elem = document.getElementById('myCanvas');
        context = elem.getContext('2d');
        for(var z=0; z<3; z++){
            context.drawImage(imageArray[z], 0, 0);

            var p = new PNGlib(256, 256, 256); // construcor takes height, weight and color-depth
            var background = p.color(1, 1, 0, 1); // set the background transparent
            var canvasData = context.getImageData(0, 0, elem.width, elem.height);
            for (var i = 0; i < 256; i++) {
                    for (var j = 0; j < 256; j++) {
                            var idx = (j * canvasData.width + i) * 4;
                                r = canvasData.data[idx + 0];
                                g = canvasData.data[idx + 1];                           
                                b = canvasData.data[idx + 2];                           
                                p.buffer[p.index(255-i, j + 0)] = p.color(r, g, b);
                    }
            }
        crateImage = new Image();
        crateImage.src = "data:imagef/png;base64,"+p.getBase64();
        crateArray.push(crateImage);        
        }
    }   
    function initImages() {
                imageArray[0] = new Image();
        imageArray[0].src = "./data/data0000.png";
                imageArray[1] = new Image();
        imageArray[1].src = "./data/data0001.png";
                imageArray[2] = new Image();
        imageArray[2].src = "./data/data0002.png";
    }

Solution

  • Your problem is that, for example, the line

       imageArray[0].src = "./data/data0000.png";
    

    initiates an image load, but does not wait for it. So when you immediately call toSagitaal() the images are not yet loaded.

    Typically you have to specify a handler that does something when the image has loaded. To do this you assign a function to the onload property.

    If you refactor so that you have a function toSagitaal(i) that processes the ith image, then you might add a line like

       imageArray[0].onload = function(){toSagitaal(0);} ;
    

    after the imageArray[0].src assignment and similarly for the other two images.

    The reason that your present example works on reload is that the browser has by that time already loaded the images, so the fact that you aren't waiting doesn't matter.