var {
uint32,
uint8,
enumeration,
binary,
crc32,
binString,
selector,
magic,
loop,
parse
} = require("bin-grammar");
// header
const ihdrGrammar = [
uint32('width'),
uint32('height'),
uint8('bitDepth'),
enumeration('colorType', { choices: {
greyscale: 0,
trueColor: 2,
indexedColor: 3,
grayscaleWithAlpha: 4,
trueColorWithAlpha: 6
} }),
enumeration('compressionMethod', { choices: { deflate: 0 } }),
enumeration('filterMethod', { choices: { adaptive: 0 } }),
enumeration('interlaceMethod', { choices: { none: 0, adam7: 1 } }),
]
// binary image data
const idatGrammar = [binary('data')];
// no content
const iendGrammar = [];
// definition of a chunk
const chunkGrammar = [
uint32('length'),
crc32('crc', [
binString('name', { size: 4 }),
selector('data', {
sizeField: 'length',
field: 'name',
flatten: true,
select: [
{ match: 'IHDR', struct: ihdrGrammar },
{ match: 'IDAT', struct: idatGrammar },
{ match: 'IEND', struct: iendGrammar },
],
}),
]),
];
// png "shell", in principle just a magic number and a list of chunks
const pngGrammar = [
magic('magic', { data: Buffer.from('89504e470d0a1a0a', 'hex') }),
loop('chunks', { struct: chunkGrammar })
];
// smallest possible 1x1 px transparent png
const buffer = Buffer.from(
'89504E470D0A1A0A0000000D494844520000000100000001' +
'0100000000376EF9240000001049444154789C6260010000' +
'00FFFF03000006000557BFABD40000000049454E44AE426082',
'hex'
);
// parse the png
const result = parse(pngGrammar, buffer);
// show result
JSON.stringify(result, null, ' ');