1
0
Fork 0
mirror of https://github.com/codedread/bitjs synced 2025-10-03 01:29:17 +02:00

PngParser: Add support for hIST chunk

This commit is contained in:
Jeff Schiller 2024-01-18 21:39:35 -08:00
parent aeb5bb2f10
commit 7b1906a91b
3 changed files with 44 additions and 3 deletions

View file

@ -2,5 +2,5 @@ General-purpose, event-based parsers for digital images.
Currently supports GIF, JPEG, and PNG.
Some nice implementations of Exif parsing for PNG, HEIF, TIFF here:
Some nice implementations of Exif parsing for HEIF, TIFF here:
https://github.com/MikeKovarik/exifr/tree/master/src/file-parsers

View file

@ -17,7 +17,7 @@ import { getExifProfile } from './exif.js';
// https://www.w3.org/TR/png-3/
// https://en.wikipedia.org/wiki/PNG#File_format
// TODO: Ancillary chunks: hIST, sPLT.
// TODO: Ancillary chunks: sPLT.
// let DEBUG = true;
let DEBUG = false;
@ -35,6 +35,7 @@ export const PngParseEventType = {
cHRM: 'chromaticities_white_point',
eXIf: 'exif_profile',
gAMA: 'image_gamma',
hIST: 'histogram',
iTXt: 'intl_text_data',
pHYs: 'physical_pixel_dims',
sBIT: 'significant_bits',
@ -299,6 +300,20 @@ export class PngExifProfileEvent extends Event {
}
}
/**
* @typedef PngHistogram
* @property {number[]} frequencies The # of frequencies matches the # of palette entries.
*/
export class PngHistogramEvent extends Event {
/** @param {PngHistogram} histogram */
constructor(histogram) {
super(PngParseEventType.hIST);
/** @type {PngHistogram} */
this.histogram = histogram;
}
}
/**
* @typedef PngChunk Internal use only.
* @property {number} length
@ -326,7 +341,6 @@ export class PngParser extends EventTarget {
*/
palette;
/** @param {ArrayBuffer} ab */
constructor(ab) {
super();
@ -384,6 +398,16 @@ export class PngParser extends EventTarget {
return this;
}
/**
* Type-safe way to bind a listener for a PngHistogramEvent.
* @param {function(PngHistogramEvent): void} listener
* @returns {PngParser} for chaining
*/
onHistogram(listener) {
super.addEventListener(PngParseEventType.hIST, listener);
return this;
}
/**
* Type-safe way to bind a listener for a PngImageDataEvent.
* @param {function(PngImageDataEvent): void} listener
@ -746,6 +770,20 @@ export class PngParser extends EventTarget {
this.dispatchEvent(new PngExifProfileEvent(exifValueMap));
break;
// https://www.w3.org/TR/png-3/#11hIST
case 'hIST':
if (!this.palette) throw `hIST before PLTE`;
if (length !== this.palette.entries.length * 2) throw `Bad # of hIST frequencies: ${length / 2}`;
/** @type {PngHistogram} */
const hist = { frequencies: [] };
for (let f = 0; f < this.palette.entries.length; ++f) {
hist.frequencies.push(chStream.readNumber(2));
}
this.dispatchEvent(new PngHistogramEvent(hist));
break;
// https://www.w3.org/TR/png-3/#11IDAT
case 'IDAT':
/** @type {PngImageData} */
@ -836,6 +874,9 @@ async function main() {
parser.onExifProfile(evt => {
// console.dir(evt.exifProfile);
});
parser.onHistogram(evt => {
// console.dir(evt.histogram);
});
try {
await parser.start();

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B