7

Although it seems that this question has been asked before, people rely on canvas for that conversion. The problem is going from a base64 url like this: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAFElEQVQIW2NkYGD4D8RYAeOQkgQAERQHAbuZaGoAAAAASUVORK5CYII=

to a pixel array with color intensities like this var array = [ [0x00,0x00,0x00], ... 49 times ]; for a 7px by 7px image (black in that case), we have to use code like this:

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);
}

which becomes asynchronous because of the onload and very painful to work with (although it works).

Then we would use code like this to get the RGBA colors from canvas

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;
}

Is there a way to just convert from the Base64 png image string to an array like the above without canvas? I have tried PNG.js which it says that the png is corrupt or incomplete (and I tried with or without the data:image/png;base64,. I have tried most of base64.js and I take bytes that don't make any sense. I tried atob/btoa calls with no relevant results either.

The answer for this question (Is is possible to read pixel data from base64 images?) should have been working but I get (just for the new PNG(data) ):

Uncaught Error: Incomplete or corrupt PNG file 

with my example:

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=");

or the example in that question. I am using this PNG.js: [ I am not using this anymore] https://github.com/devongovett/png.js/blob/master/png.js

EDIT The two packages are not the same - let's see!

EDIT 2 it almost worked using this http://jsfiddle.net/6VqwC/8/ from the other question BUT if you go you will see my black tile is becoming stripes of blue,green, red - is that a bug of the package :/ ?

EDIT 3 so it seems that the package is working with compressed pngs - and my pngs are not compressed - is there a way to use the PNG.js with non compressed files?

EDIT 4 So if I make a function (like in the answer that was deleted):

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);
        }
    }

and have multiple different functions like these:

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();
    });
}

then when I am doing that

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

what happens is that the initial tile is being manipulated so the effects do not accumulate. If you can help me with that then I have an answer that will use canvas. The call queue of doSomethingWithTile is not predefined/static and can be arbitrary

I am really baffled and I would really appreciate your help :) Thanks in advance!

Community
  • 1
  • 1
Michail Michailidis
  • 11,792
  • 6
  • 63
  • 106
  • the right starting point for what you ask is to use an XMLHTTPRequest to retrieve the raw data, then decode the file by yourself. – GameAlchemist Nov 18 '13 at 14:20
  • Thanks. The decoding was way difficult to implement because of various levels of compression etc... So I just did my code asynchronous but with guaranteed order of executions. I haven't touched the code ever since. I've been working on something else.. – Michail Michailidis Nov 21 '13 at 06:47
  • Does this answer your question? [Is is possible to read pixel data from base64 images?](https://stackoverflow.com/questions/11813162/is-is-possible-to-read-pixel-data-from-base64-images) – Brad Johnson Dec 01 '20 at 22:45

0 Answers0