Skip to content

Commit

Permalink
PngParser: Add support for eXIf chunk
Browse files Browse the repository at this point in the history
  • Loading branch information
codedread committed Jan 19, 2024
1 parent 29ca69e commit aeb5bb2
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
36 changes: 35 additions & 1 deletion image/parsers/png.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@

import * as fs from 'node:fs'; // TODO: Remove.
import { ByteStream } from '../../io/bytestream.js';
import { getExifProfile } from './exif.js';

/** @typedef {import('./exif.js').ExifValue} ExifValue */

// https://www.w3.org/TR/png-3/
// https://en.wikipedia.org/wiki/PNG#File_format

// TODO: Ancillary chunks eXIf, hIST, sPLT.
// TODO: Ancillary chunks: hIST, sPLT.

// let DEBUG = true;
let DEBUG = false;
Expand All @@ -30,6 +33,7 @@ export const PngParseEventType = {
// Ancillary chunks.
bKGD: 'background_color',
cHRM: 'chromaticities_white_point',
eXIf: 'exif_profile',
gAMA: 'image_gamma',
iTXt: 'intl_text_data',
pHYs: 'physical_pixel_dims',
Expand Down Expand Up @@ -284,6 +288,17 @@ export class PngPhysicalPixelDimensionsEvent extends Event {
}
}

/** @typedef {Map<number, ExifValue>} PngExifProfile */

export class PngExifProfileEvent extends Event {
/** @param {PngExifProfile} exifProfile */
constructor(exifProfile) {
super(PngParseEventType.eXIf);
/** @type {PngExifProfile} */
this.exifProfile = exifProfile;
}
}

/**
* @typedef PngChunk Internal use only.
* @property {number} length
Expand Down Expand Up @@ -349,6 +364,16 @@ export class PngParser extends EventTarget {
return this;
}

/**
* Type-safe way to bind a listener for a PngExifProfileEvent.
* @param {function(PngExifProfileEvent): void} listener
* @returns {PngParser} for chaining
*/
onExifProfile(listener) {
super.addEventListener(PngParseEventType.eXIf, listener);
return this;
}

/**
* Type-safe way to bind a listener for a PngImageGammaEvent.
* @param {function(PngImageGammaEvent): void} listener
Expand Down Expand Up @@ -715,6 +740,12 @@ export class PngParser extends EventTarget {
this.dispatchEvent(new PngIntlTextualDataEvent(intlTextData));
break;

// https://www.w3.org/TR/png-3/#eXIf
case 'eXIf':
const exifValueMap = getExifProfile(chStream);
this.dispatchEvent(new PngExifProfileEvent(exifValueMap));
break;

// https://www.w3.org/TR/png-3/#11IDAT
case 'IDAT':
/** @type {PngImageData} */
Expand Down Expand Up @@ -802,6 +833,9 @@ async function main() {
parser.onPhysicalPixelDimensions(evt => {
// console.dir(evt.physicalPixelDimensions);
});
parser.onExifProfile(evt => {
// console.dir(evt.exifProfile);
});

try {
await parser.start();
Expand Down
15 changes: 15 additions & 0 deletions tests/image-parsers-png.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import * as fs from 'node:fs';
import 'mocha';
import { expect } from 'chai';
import { PngColorType, PngInterlaceMethod, PngUnitSpecifier, PngParser } from '../image/parsers/png.js';
import { ExifDataFormat, ExifTagNumber } from '../image/parsers/exif.js';

/** @typedef {import('../image/parsers/exif.js').ExifValue} ExifValue */

/** @typedef {import('../image/parsers/png.js').PngBackgroundColor} PngBackgroundColor */
/** @typedef {import('../image/parsers/png.js').PngChromaticies} PngChromaticies */
Expand Down Expand Up @@ -260,4 +263,16 @@ describe('bitjs.image.parsers.PngParser', () => {
expect(pixelDims.pixelPerUnitY).equals(1000);
expect(pixelDims.unitSpecifier).equals(PngUnitSpecifier.METRE);
});

it('extracts eXIf', async () => {
/** @type {PngPhysicalPixelDimensions} */
let exif;
await getPngParser('tests/image-testfiles/exif2c08.png')
.onExifProfile(evt => { exif = evt.exifProfile })
.start();

const descVal = exif.get(ExifTagNumber.COPYRIGHT);
expect(descVal.dataFormat).equals(ExifDataFormat.ASCII_STRING);
expect(descVal.stringValue).equals('2017 Willem van Schaik');
});
});
Binary file added tests/image-testfiles/exif2c08.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit aeb5bb2

Please sign in to comment.