pngjs
pngjs copied to clipboard
BGRA/ARGB -> PNG
I have pixel data in BGRA and ARGB format as per https://github.com/electron/electron/blob/master/docs/api/web-contents.md#webcontentsbeginframesubscriptioncallback and am trying to convert it to a PNG but can't seem to figure out how. Here's what I have so far.
var data = Buffer.allocUnsafe(buffer.length);
var size = mainWindow.getSize(); // [w, h]
var format;
var pixel = 0; // total buffer offset that inc's by 1 for each pixel
var curr = 0; // 1-4 current R/G/B/A index
var offset = 0;
// These two if statements turn the BGRA or ARGB buffer into an RGBA buffer.
if (os.endianness() === "BE") {
format = "ARGB";
for (var argbValue of buffer.values()) {
curr++;
offset = pixel * 4;
switch (curr) {
case 1: { // A
offset += 3;
break;
}
case 2: { // R
offset += 0;
break;
}
case 3: { // G
offset += 1;
break;
}
default: { // B
offset += 2;
break;
}
}
data.fill(argbValue, offset, offset + 1);
if (curr === 4) {
pixel++;
curr = 0;
}
}
} else {
format = "BGRA";
for (var bgraValue of buffer.values()) {
curr++;
offset = pixel * 4;
switch (curr) {
case 1: { // B
offset += 2;
break;
}
case 2: { // G
offset += 1;
break;
}
case 3: { // R
offset += 0;
break;
}
default: { // A
bgraValue = 0;
offset += 3;
break;
}
}
data.fill(bgraValue, offset, offset + 1);
if (curr === 4) {
pixel++;
curr = 0;
}
}
}
// new PNG's don't emit `parsed` so here my thinking was i could create an empty PNG and then read that PNG
new PNG({ // creates empty PNG of correct size
width: size[0],
height: size[1],
inputHasAlpha: true
}).pack().pipe(new PNG({
// copies empty PNG so `parsed` will be called
}).on('parsed', function() {
// sets PNG data to the RGBA buffer we already have
this.data.fill(data)
// saves that to a file (this part saves a PNG that is 100% transparent) oddly, the file sizes for these entirely transparent PNGs are not always the same.
this.pack().pipe(fs.createWriteStream('imgs/' + (imgIndex++) + '-out.png'));
}))
Hi,
I'm low on time, but this looks suspiscous:
.pack().pipe(new PNG({
// copies empty PNG so `parsed` will be called
}).on('parsed', function() {
why not just create the new png and then fill data then pack.. like our example
https://github.com/lukeapage/pngjs/blob/master/examples/newfile.js#L4
@IsaiahJTurner Did you solve your problem ? getting a hard time to make it work.
@lukeapage i got unexpected output when trying to convert argb to png, the result here.
my code
const buffer: Buffer = prop.data;
if (buffer.length > 0) {
let width = buffer.readUInt32LE(0); // the first 4 bytes is the width
let height = buffer.readUInt32LE(4); // the second 4 bytes is the height
let png = new PNG({ width, height, inputHasAlpha: true });
let output = true;
for (var y = 0; y < height; ++y) {
for (var x = 0; x < width; ++x) {
var p = (4 * (y * width + x));
try {
png.data[p] = buffer.readUInt32LE((p + 1) + 8);
png.data[p + 1] = buffer.readUInt32LE((p + 2) + 8);
png.data[p + 2] = buffer.readUInt32LE((p + 3) + 8);
png.data[p + 3] = buffer.readUInt32LE(p + 8);
} catch (err) {
output = false;
continue;
}
}
}
if (output) png.pack().pipe(fs.createWriteStream(wid + '.png'));
}
any clue why the image like that ? i've tried using other image data but always have purple color on it.