MrZ MrZ - 1 month ago 15
Node.js Question

node.js swf extraction definebitslossless2 incorrect pixels

I made an library to extract images and binary (

.bin
) data from an SWF File.


But for
DefineBitsLossless2
tag (
PNG
images with alpha), I have a problem: some pixels aren't at their right place, but the others are OK.

Here's my current code (written in
Typescript
) using Jimp library for image manipulation (I also tried
node-canvas
, same thing)

private async DefineBitsLossless2(buff: SWFBuffer, tag: any, tagHeader: any, Callback: Function) {
var id = buff.readUIntLE(16);
var format = buff.readUInt8();
var width = buff.readUIntLE(16);
var height = buff.readUIntLE(16);

var data = buff.buffer.slice(buff.pointer, (buff.pointer + tagHeader.length) - 7);
buff.addPointer(tagHeader.length - 7);

if(format != 5) {
throw new Error(`Unsupported DefineBitsLossless2 image format. Only format 5 is supported, got format ${format}`);
}

var GZBuffer = this.concatSWFHeader(zlib.unzipSync(data), data);
var image = await new Jimp(width, height);
var position = 0;

for(var y = 0; y < height; y++) {
for(var x = 0; x < width; x++) {
var alpha = GZBuffer.readUInt8(position++);
var red = GZBuffer.readUInt8(position++);
var green = GZBuffer.readUInt8(position++);
var blue = GZBuffer.readUInt8(position++);

image.setPixelColor(Jimp.rgbaToInt(red, green, blue, alpha), x, y);
}
}

image.getBuffer(Jimp.MIME_PNG, function(err, buffer) {
tag.id = id;
tag.format = format;
tag.width = width;
tag.height = height;
tag.data = buffer;
Callback(null);
});
}



private concatSWFHeader(buff: Buffer, swf: Buffer) {
return Buffer.concat([swf.slice(0, 8), buff]);
}


Here's the result of this SWF that I used for test pruposes:

Using my library:

#1

Using FFDec (Free Flash Decompiler in Java)

#2

I followed this Adobe guide to make my library (see the page
144
for
DefineBitsLossless2
tag)

What's wrong with my code?

Answer

I believe this:

var GZBuffer = this.concatSWFHeader(zlib.unzipSync(data), data);

should instead be:

var GZBuffer = zlib.unzipSync(data);

Not sure what you were going for with concatSWFHeader, but that would rather be part of the ZLIB header you're adding, and it should account for whole image being offset by 2 pixels.