¿Cómo convertir una cadena png base64 a una matriz de píxeles sin utilizar canvas getImageData?

Aunque parece que esta pregunta se ha hecho antes, la gente confía en el lienzo para esa conversión. El problema va desde una url base64 como esta:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAFElEQVQIW2NkYGD4D8RYAeOQkgQAERQHAbuZaGoAAAAASUVORK5CYII=

a una matriz de píxeles con intensidades de color como estevar array = [ [0x00,0x00,0x00], ... 49 times ]; para una imagen de 7px por 7px (negro en ese caso), tenemos que usar un código como este:

var mCanvas = document.createElement('canvas');
var base64DataUrl = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAFElEQVQIW2NkYGD4D8RYAeOQkgQAERQHAbuZaGoAAAAASUVORK5CYII=";
mCanvas.width = 7;
mCanvas.height = 7;
var mContext = mCanvas.getContext('2d');
var myImage = new Image();
myImage.setAttribute("src", base64DataUrl);
myImage.onload = function() { 
    var mContext = mCanvas.getContext('2d');
    var mImgData = mContext.getImageData(0,0,mCanvas.width,mCanvas.height);
}

que se convierte en asíncrono debido a laonload y muy doloroso trabajar con él (aunque funciona).

Luego usaríamos un código como este para obtener los colores RGBA del lienzo

function convertCanvasToPixelsArray(mCanvas){
    var mContext = mCanvas.getContext('2d');
    console.log(mCanvas.width);
    var mImgData = mContext.getImageData(0,0,mCanvas.width,mCanvas.height);

    var srcIndex=0, dstIndex=0, curPixelNum=0;
    var pixelsArray = new Array(mCanvas.width*mCanvas.height);
    for (curPixelNum=0; curPixelNum<mCanvas.width*mCanvas.height;  curPixelNum++)
    {
        pixelsArray[dstIndex] = new Array(3);
        pixelsArray[dstIndex][0] = mImgData.data[srcIndex]; // r
        pixelsArray[dstIndex][1] = mImgData.data[srcIndex+1];   // g
        pixelsArray[dstIndex][2] = mImgData.data[srcIndex+2];   // b

        dstIndex += 1;
        srcIndex += 4;
    }
    return pixelsArray;
}

¿Hay una manera de convertir simplemente de la cadena de imagen png Base64 a una matriz como la anterior sin lienzo? He probado PNG.js, que dice que el png está corrupto o incompleto (y lo intenté con o sin eldata:image/png;base64,. He probado la mayoría de base64.js y tomo bytes que no tienen ningún sentido. Intenté llamadas atob / btoa sin resultados relevantes tampoco.

La respuesta a esta pregunta (¿Es posible leer datos de píxeles de imágenes base64?) debería haber estado trabajando pero recibo (solo para el nuevo PNG (datos)):

Uncaught Error: Incomplete or corrupt PNG file 

con mi ejemplo:

function show(data){
        var png = new PNG(data);
        var img = document.getElementById('image'), limg = document.getElementById('largeimage');
        document.getElementById('nativeimage').src = 'data:image/png;base64,' + data;
        img.innerHTML = '';
        limg.innerHTML = '';
        img.style.width = png.width + 'px';
        img.style.height = png.height + 'px';
        limg.style.width = (png.width * 3) + 'px';
        limg.style.width = (png.height * 3) + 'px';
        var line;
        while(line = png.readLine())
        {
            for (var x = 0; x < line.length; x++){
                var px = document.createElement('div'), px2 = document.createElement('div');
                px.className = px2.className = 'pixel';
                px.style.backgroundColor = px2.style.backgroundColor = '#' + line[x].toString(16).padRight('0', 6);
                img.appendChild(px);
                limg.appendChild(px2);
            }
        }
    }


    show("iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAFElEQVQIW2NkYGD4D8RYAeOQkgQAERQHAbuZaGoAAAAASUVORK5CYII=");

o el ejemplo en esa pregunta. Estoy usando este PNG.js: [No lo estoy usando más]https://github.com/devongovett/png.js/blob/master/png.js

EDITAR Los dos paquetes no son lo mismo - ¡veamos!

Editar 2 casi funcionó usando estohttp://jsfiddle.net/6VqwC/8/ de la otra preguntaPERO Si vas verás que mi baldosa negra se está convirtiendo en franjas deazul, verde, rojo - ¿Es eso un error del paquete: /?

EDITAR 3 así que parece que el paquete funciona con pngs comprimidos, y mis pngs no están comprimidos, ¿hay alguna forma de usar PNG.js con archivos no comprimidos?

EDITAR 4 Así que si hago una función (como en la respuesta que fue eliminada):

function convertBase64ToPixelsArray(tile,whatToDoNext){
        var base64DataUrl = tile.base64DataUrl;
        var mCanvas = newEl("canvas");
        var ctx = mCanvas.getContext("2d");
        var pixelsArray = [];

        var img = newEl("img");
        img.onload = getRGB;
        img.src = base64DataUrl;

        function getRGB(){
            mCanvas.width = img.width;
            mCanvas.height = img.height;
            ctx.drawImage(img,0,0);
            var data = ctx.getImageData(0,0,mCanvas.width, mCanvas.height).data;
            for (var i=0; i<data.length; i+=4){
                pixelsArray.push([data[i],data[i+1],data[i+2]]);
            }
            whatToDoNext(pixelsArray);
        }
    }

y tienen múltiples funciones diferentes como estas:

function doSomethingWithTile(tile,params){
   convertBase64ToPixelsArray(tile,function(pixelsArray){
    //manipulate the pixels 
    //convert them back to base64 and store it in the tile
    tile.base64UrlData = convertPixelsArrayToCanvas(pixelsArray,tile.width,tile.height).convertToBase64();
    });
}

entonces cuando estoy haciendo eso

var tile = initialize_tile();
doSomethingWithTile(tile,params1);
doSomethingWithTile2(tile,params2);
doSomethingWithTile(tile,params1);
...

lo que sucede es que la pieza inicial se está manipulando para que los efectos no se acumulen. Si puedes ayudarme con eso, entonces tengo una respuesta que usará lienzo. La cola de llamadas de doSomethingWithTile no está predefinida / estática y puede ser arbitraria

Estoy realmente desconcertado y realmente agradecería su ayuda :) ¡Gracias de antemano!

Respuestas a la pregunta(0)

Su respuesta a la pregunta