@@ -22,6 +22,7 @@ const SIG = new Uint8Array([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
22
22
export const PngParseEventType = {
23
23
IHDR : 'image_header' ,
24
24
gAMA : 'image_gamma' ,
25
+ sBIT : 'significant_bits' ,
25
26
PLTE : 'palette' ,
26
27
IDAT : 'image_data' ,
27
28
} ;
@@ -70,6 +71,24 @@ export class PngImageGammaEvent extends Event {
70
71
}
71
72
}
72
73
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
+
73
92
/**
74
93
* @typedef PngColor
75
94
* @property {number } red
@@ -153,6 +172,16 @@ export class PngParser extends EventTarget {
153
172
return this ;
154
173
}
155
174
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
+
156
185
/**
157
186
* Type-safe way to bind a listener for a PngPaletteEvent.
158
187
* @param {function(PngPaletteEvent): void } listener
@@ -231,6 +260,37 @@ export class PngParser extends EventTarget {
231
260
this . dispatchEvent ( new PngImageGammaEvent ( chStream . readNumber ( 4 ) ) ) ;
232
261
break ;
233
262
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
+
234
294
// https://www.w3.org/TR/2003/REC-PNG-20031110/#11PLTE
235
295
case 'PLTE' :
236
296
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
300
360
301
361
async function main ( ) {
302
362
for ( const fileName of FILES ) {
303
- if ( ! fileName . includes ( '3p' ) ) continue ;
304
-
305
363
console . log ( `file: ${ fileName } ` ) ;
306
364
const nodeBuf = fs . readFileSync ( fileName ) ;
307
365
const ab = nodeBuf . buffer . slice ( nodeBuf . byteOffset , nodeBuf . byteOffset + nodeBuf . length ) ;
@@ -312,6 +370,9 @@ async function main() {
312
370
parser . onGamma ( evt => {
313
371
// console.dir(evt.imageGamma);
314
372
} ) ;
373
+ parser . onSignificantBits ( evt => {
374
+ console . dir ( evt . sigBits ) ;
375
+ } ) ;
315
376
parser . onPalette ( evt => {
316
377
// console.dir(evt.palette);
317
378
} ) ;
0 commit comments