Wie konvertiere ich eine PNG Base64-Zeichenfolge in ein Pixelarray ohne Verwendung von Canvas getImageData?
Obwohl diese Frage anscheinend schon einmal gestellt wurde, verlassen sich die Leute bei dieser Konvertierung auf Canvas. Das Problem geht von einer Base64-URL wie folgt aus:data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAFElEQVQIW2NkYGD4D8RYAeOQkgQAERQHAbuZaGoAAAAASUVORK5CYII=
zu einem Pixel-Array mit solchen Farbintensitätenvar array = [ [0x00,0x00,0x00], ... 49 times ];
Für ein 7 x 7 Pixel großes Bild (in diesem Fall schwarz) müssen wir folgenden Code verwenden:
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);
}
die wegen der asynchron wirdonload und sehr schmerzhaft zu arbeiten (obwohl es funktioniert).
Dann würden wir Code wie diesen verwenden, um die RGBA-Farben von der Leinwand zu erhalten
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;
}
Gibt es eine Möglichkeit, nur von der Base64-PNG-Bildzeichenfolge in ein Array wie das oben genannte ohne Zeichenfläche zu konvertieren? Ich habe PNG.js ausprobiert, das besagt, dass das PNG beschädigt oder unvollständig ist (und ich habe es mit oder ohne versuchtdata:image/png;base64,
. Ich habe die meisten base64.js ausprobiert und ich nehme Bytes, die keinen Sinn ergeben. Ich habe versucht, atob / btoa-Anrufe ohne relevante Ergebnisse.
Die Antwort auf diese Frage (Ist es möglich, Pixeldaten von base64-Bildern zu lesen?) hätte funktionieren sollen aber ich bekomme (nur für das neue PNG (Daten)):
Uncaught Error: Incomplete or corrupt PNG file
mit meinem beispiel:
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=");
oder das Beispiel in dieser Frage. Ich benutze diese PNG.js: [Ich benutze diese nicht mehr]https://github.com/devongovett/png.js/blob/master/png.js
BEARBEITEN Die beiden Pakete sind nicht gleich - mal sehen!
BEARBEITEN 2 Damit hätte es fast geklappthttp://jsfiddle.net/6VqwC/8/ von der anderen FrageABER Wenn du gehst, wirst du sehen, dass meine schwarzen Kacheln zu Streifen werdenblau, grün, rot - Ist das ein Fehler des Pakets: /?
EDIT 3 Es scheint also, dass das Paket mit komprimierten PNGs arbeitet - und meine PNGs sind nicht komprimiert - gibt es eine Möglichkeit, die PNG.js mit nicht komprimierten Dateien zu verwenden?
EDIT 4 Also, wenn ich eine Funktion mache (wie in der Antwort, die gelöscht wurde):
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);
}
}
und haben mehrere verschiedene Funktionen wie diese:
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();
});
}
dann, wenn ich das tue
var tile = initialize_tile();
doSomethingWithTile(tile,params1);
doSomethingWithTile2(tile,params2);
doSomethingWithTile(tile,params1);
...
Was passiert ist, dass das ursprüngliche Plättchen manipuliert wird, so dass sich die Effekte nicht ansammeln. Wenn Sie mir dabei helfen können, habe ich eine Antwort, die Leinwand verwendet. Die Aufrufwarteschlange von doSomethingWithTile ist nicht vordefiniert / statisch und kann beliebig sein
Ich bin wirklich verblüfft und würde mich sehr über Ihre Hilfe freuen :) Vielen Dank im Voraus!