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!