@@ -14,7 +14,7 @@ import { ByteStream } from '../../io/bytestream.js';
1414// https://www.w3.org/TR/png-3/
1515// https://en.wikipedia.org/wiki/PNG#File_format
1616
17- // TODO: Ancillary chunks bKGD, eXIf, hIST, pHYs, sPLT, tIME.
17+ // TODO: Ancillary chunks eXIf, hIST, pHYs, sPLT, tIME.
1818
1919// let DEBUG = true;
2020let DEBUG = false ;
@@ -28,6 +28,7 @@ export const PngParseEventType = {
2828 PLTE : 'palette' ,
2929
3030 // Ancillary chunks.
31+ bKGD : 'background_color' ,
3132 cHRM : 'chromaticities_white_point' ,
3233 gAMA : 'image_gamma' ,
3334 iTXt : 'intl_text_data' ,
@@ -223,6 +224,24 @@ export class PngIntlTextualDataEvent extends Event {
223224 }
224225}
225226
227+ /**
228+ * @typedef PngBackgroundColor
229+ * @property {number= } greyscale Only for color types 0 and 4.
230+ * @property {number= } red Only for color types 2 and 6.
231+ * @property {number= } green Only for color types 2 and 6.
232+ * @property {number= } blue Only for color types 2 and 6.
233+ * @property {number= } paletteIndex Only for color type 3.
234+ */
235+
236+ export class PngBackgroundColorEvent extends Event {
237+ /** @param {PngBackgroundColor } backgroundColor */
238+ constructor ( backgroundColor ) {
239+ super ( PngParseEventType . bKGD ) ;
240+ /** @type {PngBackgroundColor } */
241+ this . backgroundColor = backgroundColor ;
242+ }
243+ }
244+
226245/**
227246 * @typedef PngChunk Internal use only.
228247 * @property {number } length
@@ -258,6 +277,16 @@ export class PngParser extends EventTarget {
258277 this . bstream . setBigEndian ( ) ;
259278 }
260279
280+ /**
281+ * Type-safe way to bind a listener for a PngBackgroundColorEvent.
282+ * @param {function(PngBackgroundColorEvent): void } listener
283+ * @returns {PngParser } for chaining
284+ */
285+ onBackgroundColor ( listener ) {
286+ super . addEventListener ( PngParseEventType . bKGD , listener ) ;
287+ return this ;
288+ }
289+
261290 /**
262291 * Type-safe way to bind a listener for a PngChromaticiesEvent.
263292 * @param {function(PngChromaticiesEvent): void } listener
@@ -416,6 +445,28 @@ export class PngParser extends EventTarget {
416445 this . dispatchEvent ( new PngImageGammaEvent ( chStream . readNumber ( 4 ) ) ) ;
417446 break ;
418447
448+ // https://www.w3.org/TR/png-3/#11bKGD
449+ case 'bKGD' :
450+ if ( this . colorType === undefined ) throw `bKGD before IHDR` ;
451+ if ( this . colorType === PngColorType . INDEXED_COLOR && ! this . palette ) throw `bKGD before PLTE` ;
452+ /** @type {PngBackgroundColor } */
453+ const bkgdColor = { } ;
454+
455+ if ( this . colorType === PngColorType . GREYSCALE ||
456+ this . colorType === PngColorType . GREYSCALE_WITH_ALPHA ) {
457+ bkgdColor . greyscale = chStream . readNumber ( 2 ) ;
458+ } else if ( this . colorType === PngColorType . TRUE_COLOR ||
459+ this . colorType === PngColorType . TRUE_COLOR_WITH_ALPHA ) {
460+ bkgdColor . red = chStream . readNumber ( 2 ) ;
461+ bkgdColor . green = chStream . readNumber ( 2 ) ;
462+ bkgdColor . blue = chStream . readNumber ( 2 ) ;
463+ } else if ( this . colorType === PngColorType . INDEXED_COLOR ) {
464+ bkgdColor . paletteIndex = chStream . readNumber ( 1 ) ;
465+ }
466+
467+ this . dispatchEvent ( new PngBackgroundColorEvent ( bkgdColor ) ) ;
468+ break ;
469+
419470 // https://www.w3.org/TR/png-3/#11sBIT
420471 case 'sBIT' :
421472 if ( this . colorType === undefined ) throw `sBIT before IHDR` ;
@@ -651,6 +702,9 @@ async function main() {
651702 parser . onIntlTextualData ( evt => {
652703 // console.dir(evt.intlTextualdata);
653704 } ) ;
705+ parser . onBackgroundColor ( evt => {
706+ // console.dir(evt.backgroundColor);
707+ } )
654708
655709 try {
656710 await parser . start ( ) ;
0 commit comments