1010
1111import * as fs from 'node:fs' ; // TODO: Remove.
1212import { ByteStream } from '../../io/bytestream.js' ;
13+ import { getExifProfile } from './exif.js' ;
14+
15+ /** @typedef {import('./exif.js').ExifValue } ExifValue */
1316
1417// https://www.w3.org/TR/png-3/
1518// https://en.wikipedia.org/wiki/PNG#File_format
1619
17- // TODO: Ancillary chunks eXIf, hIST, sPLT.
20+ // TODO: Ancillary chunks: hIST, sPLT.
1821
1922// let DEBUG = true;
2023let DEBUG = false ;
@@ -30,6 +33,7 @@ export const PngParseEventType = {
3033 // Ancillary chunks.
3134 bKGD : 'background_color' ,
3235 cHRM : 'chromaticities_white_point' ,
36+ eXIf : 'exif_profile' ,
3337 gAMA : 'image_gamma' ,
3438 iTXt : 'intl_text_data' ,
3539 pHYs : 'physical_pixel_dims' ,
@@ -284,6 +288,17 @@ export class PngPhysicalPixelDimensionsEvent extends Event {
284288 }
285289}
286290
291+ /** @typedef {Map<number, ExifValue> } PngExifProfile */
292+
293+ export class PngExifProfileEvent extends Event {
294+ /** @param {PngExifProfile } exifProfile */
295+ constructor ( exifProfile ) {
296+ super ( PngParseEventType . eXIf ) ;
297+ /** @type {PngExifProfile } */
298+ this . exifProfile = exifProfile ;
299+ }
300+ }
301+
287302/**
288303 * @typedef PngChunk Internal use only.
289304 * @property {number } length
@@ -349,6 +364,16 @@ export class PngParser extends EventTarget {
349364 return this ;
350365 }
351366
367+ /**
368+ * Type-safe way to bind a listener for a PngExifProfileEvent.
369+ * @param {function(PngExifProfileEvent): void } listener
370+ * @returns {PngParser } for chaining
371+ */
372+ onExifProfile ( listener ) {
373+ super . addEventListener ( PngParseEventType . eXIf , listener ) ;
374+ return this ;
375+ }
376+
352377 /**
353378 * Type-safe way to bind a listener for a PngImageGammaEvent.
354379 * @param {function(PngImageGammaEvent): void } listener
@@ -715,6 +740,12 @@ export class PngParser extends EventTarget {
715740 this . dispatchEvent ( new PngIntlTextualDataEvent ( intlTextData ) ) ;
716741 break ;
717742
743+ // https://www.w3.org/TR/png-3/#eXIf
744+ case 'eXIf' :
745+ const exifValueMap = getExifProfile ( chStream ) ;
746+ this . dispatchEvent ( new PngExifProfileEvent ( exifValueMap ) ) ;
747+ break ;
748+
718749 // https://www.w3.org/TR/png-3/#11IDAT
719750 case 'IDAT' :
720751 /** @type {PngImageData } */
@@ -802,6 +833,9 @@ async function main() {
802833 parser . onPhysicalPixelDimensions ( evt => {
803834 // console.dir(evt.physicalPixelDimensions);
804835 } ) ;
836+ parser . onExifProfile ( evt => {
837+ // console.dir(evt.exifProfile);
838+ } ) ;
805839
806840 try {
807841 await parser . start ( ) ;
0 commit comments