@@ -22,6 +22,7 @@ const SIG = new Uint8Array([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
2222export const PngParseEventType = {
2323 IHDR : 'image_header' ,
2424 gAMA : 'image_gamma' ,
25+ sBIT : 'significant_bits' ,
2526 PLTE : 'palette' ,
2627 IDAT : 'image_data' ,
2728} ;
@@ -70,6 +71,24 @@ export class PngImageGammaEvent extends Event {
7071 }
7172}
7273
74+ /**
75+ * @typedef PngSignificantBits
76+ * @property {number= } significant_greyscale Populated for color types 0, 4.
77+ * @property {number= } significant_red Populated for color types 2, 3, 6.
78+ * @property {number= } significant_green Populated for color types 2, 3, 6.
79+ * @property {number= } significant_blue Populated for color types 2, 3, 6.
80+ * @property {number= } significant_alpha Populated for color types 4, 6.
81+ */
82+
83+ export class PngSignificantBitsEvent extends Event {
84+ /** @param {PngSignificantBits } */
85+ constructor ( sigBits ) {
86+ super ( PngParseEventType . sBIT ) ;
87+ /** @type {PngSignificantBits } */
88+ this . sigBits = sigBits ;
89+ }
90+ }
91+
7392/**
7493 * @typedef PngColor
7594 * @property {number } red
@@ -153,6 +172,16 @@ export class PngParser extends EventTarget {
153172 return this ;
154173 }
155174
175+ /**
176+ * Type-safe way to bind a listener for a PngSignificantBitsEvent.
177+ * @param {function(PngSignificantBitsEvent): void } listener
178+ * @returns {PngParser } for chaining
179+ */
180+ onSignificantBits ( listener ) {
181+ super . addEventListener ( PngParseEventType . sBIT , listener ) ;
182+ return this ;
183+ }
184+
156185 /**
157186 * Type-safe way to bind a listener for a PngPaletteEvent.
158187 * @param {function(PngPaletteEvent): void } listener
@@ -231,6 +260,37 @@ export class PngParser extends EventTarget {
231260 this . dispatchEvent ( new PngImageGammaEvent ( chStream . readNumber ( 4 ) ) ) ;
232261 break ;
233262
263+ // https://www.w3.org/TR/2003/REC-PNG-20031110/#11sBIT
264+ case 'sBIT' :
265+ if ( this . colorType === undefined ) throw `sBIT before IHDR` ;
266+ /** @type {PngSignificantBits } */
267+ const sigBits = { } ;
268+
269+ const badLengthErr = `Weird sBIT length for color type ${ this . colorType } : ${ length } ` ;
270+ if ( this . colorType === PngColorType . GREYSCALE ) {
271+ if ( length !== 1 ) throw badLengthErr ;
272+ sigBits . significant_greyscale = chStream . readNumber ( 1 ) ;
273+ } else if ( this . colorType === PngColorType . TRUE_COLOR ||
274+ this . colorType === PngColorType . INDEXED_COLOR ) {
275+ if ( length !== 3 ) throw badLengthErr ;
276+ sigBits . significant_red = chStream . readNumber ( 1 ) ;
277+ sigBits . significant_green = chStream . readNumber ( 1 ) ;
278+ sigBits . significant_blue = chStream . readNumber ( 1 ) ;
279+ } else if ( this . colorType === PngColorType . GREYSCALE_WITH_ALPHA ) {
280+ if ( length !== 2 ) throw badLengthErr ;
281+ sigBits . significant_greyscale = chStream . readNumber ( 1 ) ;
282+ sigBits . significant_alpha = chStream . readNumber ( 1 ) ;
283+ } else if ( this . colorType === PngColorType . TRUE_COLOR_WITH_ALPHA ) {
284+ if ( length !== 4 ) throw badLengthErr ;
285+ sigBits . significant_red = chStream . readNumber ( 1 ) ;
286+ sigBits . significant_green = chStream . readNumber ( 1 ) ;
287+ sigBits . significant_blue = chStream . readNumber ( 1 ) ;
288+ sigBits . significant_alpha = chStream . readNumber ( 1 ) ;
289+ }
290+
291+ this . dispatchEvent ( new PngSignificantBitsEvent ( sigBits ) ) ;
292+ break ;
293+
234294 // https://www.w3.org/TR/2003/REC-PNG-20031110/#11PLTE
235295 case 'PLTE' :
236296 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
300360
301361async function main ( ) {
302362 for ( const fileName of FILES ) {
303- if ( ! fileName . includes ( '3p' ) ) continue ;
304-
305363 console . log ( `file: ${ fileName } ` ) ;
306364 const nodeBuf = fs . readFileSync ( fileName ) ;
307365 const ab = nodeBuf . buffer . slice ( nodeBuf . byteOffset , nodeBuf . byteOffset + nodeBuf . length ) ;
@@ -312,6 +370,9 @@ async function main() {
312370 parser . onGamma ( evt => {
313371 // console.dir(evt.imageGamma);
314372 } ) ;
373+ parser . onSignificantBits ( evt => {
374+ console . dir ( evt . sigBits ) ;
375+ } ) ;
315376 parser . onPalette ( evt => {
316377 // console.dir(evt.palette);
317378 } ) ;
0 commit comments