mirror of
https://github.com/codedread/bitjs
synced 2025-10-03 17:49:16 +02:00
PngParser: Handle sBIT chunk.
This commit is contained in:
parent
1d0abcaee8
commit
6ff93337fd
3 changed files with 78 additions and 3 deletions
|
@ -22,6 +22,7 @@ const SIG = new Uint8Array([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
|
||||||
export const PngParseEventType = {
|
export const PngParseEventType = {
|
||||||
IHDR: 'image_header',
|
IHDR: 'image_header',
|
||||||
gAMA: 'image_gamma',
|
gAMA: 'image_gamma',
|
||||||
|
sBIT: 'significant_bits',
|
||||||
PLTE: 'palette',
|
PLTE: 'palette',
|
||||||
IDAT: 'image_data',
|
IDAT: 'image_data',
|
||||||
};
|
};
|
||||||
|
@ -70,6 +71,24 @@ export class PngImageGammaEvent extends Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef PngSignificantBits
|
||||||
|
* @property {number=} significant_greyscale Populated for color types 0, 4.
|
||||||
|
* @property {number=} significant_red Populated for color types 2, 3, 6.
|
||||||
|
* @property {number=} significant_green Populated for color types 2, 3, 6.
|
||||||
|
* @property {number=} significant_blue Populated for color types 2, 3, 6.
|
||||||
|
* @property {number=} significant_alpha Populated for color types 4, 6.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class PngSignificantBitsEvent extends Event {
|
||||||
|
/** @param {PngSignificantBits} */
|
||||||
|
constructor(sigBits) {
|
||||||
|
super(PngParseEventType.sBIT);
|
||||||
|
/** @type {PngSignificantBits} */
|
||||||
|
this.sigBits = sigBits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef PngColor
|
* @typedef PngColor
|
||||||
* @property {number} red
|
* @property {number} red
|
||||||
|
@ -153,6 +172,16 @@ export class PngParser extends EventTarget {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type-safe way to bind a listener for a PngSignificantBitsEvent.
|
||||||
|
* @param {function(PngSignificantBitsEvent): void} listener
|
||||||
|
* @returns {PngParser} for chaining
|
||||||
|
*/
|
||||||
|
onSignificantBits(listener) {
|
||||||
|
super.addEventListener(PngParseEventType.sBIT, listener);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type-safe way to bind a listener for a PngPaletteEvent.
|
* Type-safe way to bind a listener for a PngPaletteEvent.
|
||||||
* @param {function(PngPaletteEvent): void} listener
|
* @param {function(PngPaletteEvent): void} listener
|
||||||
|
@ -231,6 +260,37 @@ export class PngParser extends EventTarget {
|
||||||
this.dispatchEvent(new PngImageGammaEvent(chStream.readNumber(4)));
|
this.dispatchEvent(new PngImageGammaEvent(chStream.readNumber(4)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// https://www.w3.org/TR/2003/REC-PNG-20031110/#11sBIT
|
||||||
|
case 'sBIT':
|
||||||
|
if (this.colorType === undefined) throw `sBIT before IHDR`;
|
||||||
|
/** @type {PngSignificantBits} */
|
||||||
|
const sigBits = {};
|
||||||
|
|
||||||
|
const badLengthErr = `Weird sBIT length for color type ${this.colorType}: ${length}`;
|
||||||
|
if (this.colorType === PngColorType.GREYSCALE) {
|
||||||
|
if (length !== 1) throw badLengthErr;
|
||||||
|
sigBits.significant_greyscale = chStream.readNumber(1);
|
||||||
|
} else if (this.colorType === PngColorType.TRUE_COLOR ||
|
||||||
|
this.colorType === PngColorType.INDEXED_COLOR) {
|
||||||
|
if (length !== 3) throw badLengthErr;
|
||||||
|
sigBits.significant_red = chStream.readNumber(1);
|
||||||
|
sigBits.significant_green = chStream.readNumber(1);
|
||||||
|
sigBits.significant_blue = chStream.readNumber(1);
|
||||||
|
} else if (this.colorType === PngColorType.GREYSCALE_WITH_ALPHA) {
|
||||||
|
if (length !== 2) throw badLengthErr;
|
||||||
|
sigBits.significant_greyscale = chStream.readNumber(1);
|
||||||
|
sigBits.significant_alpha = chStream.readNumber(1);
|
||||||
|
} else if (this.colorType === PngColorType.TRUE_COLOR_WITH_ALPHA) {
|
||||||
|
if (length !== 4) throw badLengthErr;
|
||||||
|
sigBits.significant_red = chStream.readNumber(1);
|
||||||
|
sigBits.significant_green = chStream.readNumber(1);
|
||||||
|
sigBits.significant_blue = chStream.readNumber(1);
|
||||||
|
sigBits.significant_alpha = chStream.readNumber(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dispatchEvent(new PngSignificantBitsEvent(sigBits));
|
||||||
|
break;
|
||||||
|
|
||||||
// https://www.w3.org/TR/2003/REC-PNG-20031110/#11PLTE
|
// https://www.w3.org/TR/2003/REC-PNG-20031110/#11PLTE
|
||||||
case 'PLTE':
|
case 'PLTE':
|
||||||
if (this.colorType === undefined) throw `PLTE before IHDR`;
|
if (this.colorType === undefined) throw `PLTE before IHDR`;
|
||||||
|
@ -300,8 +360,6 @@ basn0g02.png bgbn4a08.png cs5n3p08.png f03n0g08.png g10n2c08.png ps2n2c16.png s0
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
for (const fileName of FILES) {
|
for (const fileName of FILES) {
|
||||||
if (!fileName.includes('3p')) continue;
|
|
||||||
|
|
||||||
console.log(`file: ${fileName}`);
|
console.log(`file: ${fileName}`);
|
||||||
const nodeBuf = fs.readFileSync(fileName);
|
const nodeBuf = fs.readFileSync(fileName);
|
||||||
const ab = nodeBuf.buffer.slice(nodeBuf.byteOffset, nodeBuf.byteOffset + nodeBuf.length);
|
const ab = nodeBuf.buffer.slice(nodeBuf.byteOffset, nodeBuf.byteOffset + nodeBuf.length);
|
||||||
|
@ -312,6 +370,9 @@ async function main() {
|
||||||
parser.onGamma(evt => {
|
parser.onGamma(evt => {
|
||||||
// console.dir(evt.imageGamma);
|
// console.dir(evt.imageGamma);
|
||||||
});
|
});
|
||||||
|
parser.onSignificantBits(evt => {
|
||||||
|
console.dir(evt.sigBits);
|
||||||
|
});
|
||||||
parser.onPalette(evt => {
|
parser.onPalette(evt => {
|
||||||
// console.dir(evt.palette);
|
// console.dir(evt.palette);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,10 +3,11 @@ import 'mocha';
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import { PngColorType, PngInterlaceMethod, PngParser } from '../image/parsers/png.js';
|
import { PngColorType, PngInterlaceMethod, PngParser } from '../image/parsers/png.js';
|
||||||
|
|
||||||
/** @typedef {import('../image/parsers/png.js').PngImageHeader} PngImageHeader */
|
|
||||||
/** @typedef {import('../image/parsers/png.js').PngImageData} PngImageData */
|
/** @typedef {import('../image/parsers/png.js').PngImageData} PngImageData */
|
||||||
/** @typedef {import('../image/parsers/png.js').PngImageGamma} PngImageGamma */
|
/** @typedef {import('../image/parsers/png.js').PngImageGamma} PngImageGamma */
|
||||||
|
/** @typedef {import('../image/parsers/png.js').PngImageHeader} PngImageHeader */
|
||||||
/** @typedef {import('../image/parsers/png.js').PngPalette} PngPalette */
|
/** @typedef {import('../image/parsers/png.js').PngPalette} PngPalette */
|
||||||
|
/** @typedef {import('../image/parsers/png.js').PngSignificantBits} PngSignificantBits */
|
||||||
|
|
||||||
function getPngParser(fileName) {
|
function getPngParser(fileName) {
|
||||||
const nodeBuf = fs.readFileSync(fileName);
|
const nodeBuf = fs.readFileSync(fileName);
|
||||||
|
@ -57,6 +58,19 @@ describe('bitjs.image.parsers.PngParser', () => {
|
||||||
expect(gamma).equals(55000);
|
expect(gamma).equals(55000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('extracts sBIT', async () => {
|
||||||
|
/** @type {PngSignificantBits} */
|
||||||
|
let sBits;
|
||||||
|
await getPngParser('tests/image-testfiles/cs3n2c16.png')
|
||||||
|
.onSignificantBits(evt => sBits = evt.sigBits)
|
||||||
|
.start();
|
||||||
|
expect(sBits.significant_red).equals(13);
|
||||||
|
expect(sBits.significant_green).equals(13);
|
||||||
|
expect(sBits.significant_blue).equals(13);
|
||||||
|
expect(sBits.significant_greyscale).equals(undefined);
|
||||||
|
expect(sBits.significant_alpha).equals(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
it('extracts PLTE', async () => {
|
it('extracts PLTE', async () => {
|
||||||
/** @type {PngPalette} */
|
/** @type {PngPalette} */
|
||||||
let palette;
|
let palette;
|
||||||
|
|
BIN
tests/image-testfiles/cs3n2c16.png
Normal file
BIN
tests/image-testfiles/cs3n2c16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 214 B |
Loading…
Add table
Add a link
Reference in a new issue