mirror of
https://github.com/codedread/bitjs
synced 2025-10-03 17:49:16 +02:00
PngParser: Add support for hIST chunk
This commit is contained in:
parent
aeb5bb2f10
commit
7b1906a91b
3 changed files with 44 additions and 3 deletions
|
@ -2,5 +2,5 @@ General-purpose, event-based parsers for digital images.
|
||||||
|
|
||||||
Currently supports GIF, JPEG, and PNG.
|
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
|
https://github.com/MikeKovarik/exifr/tree/master/src/file-parsers
|
|
@ -17,7 +17,7 @@ import { getExifProfile } from './exif.js';
|
||||||
// https://www.w3.org/TR/png-3/
|
// https://www.w3.org/TR/png-3/
|
||||||
// https://en.wikipedia.org/wiki/PNG#File_format
|
// https://en.wikipedia.org/wiki/PNG#File_format
|
||||||
|
|
||||||
// TODO: Ancillary chunks: hIST, sPLT.
|
// TODO: Ancillary chunks: sPLT.
|
||||||
|
|
||||||
// let DEBUG = true;
|
// let DEBUG = true;
|
||||||
let DEBUG = false;
|
let DEBUG = false;
|
||||||
|
@ -35,6 +35,7 @@ export const PngParseEventType = {
|
||||||
cHRM: 'chromaticities_white_point',
|
cHRM: 'chromaticities_white_point',
|
||||||
eXIf: 'exif_profile',
|
eXIf: 'exif_profile',
|
||||||
gAMA: 'image_gamma',
|
gAMA: 'image_gamma',
|
||||||
|
hIST: 'histogram',
|
||||||
iTXt: 'intl_text_data',
|
iTXt: 'intl_text_data',
|
||||||
pHYs: 'physical_pixel_dims',
|
pHYs: 'physical_pixel_dims',
|
||||||
sBIT: 'significant_bits',
|
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.
|
* @typedef PngChunk Internal use only.
|
||||||
* @property {number} length
|
* @property {number} length
|
||||||
|
@ -326,7 +341,6 @@ export class PngParser extends EventTarget {
|
||||||
*/
|
*/
|
||||||
palette;
|
palette;
|
||||||
|
|
||||||
|
|
||||||
/** @param {ArrayBuffer} ab */
|
/** @param {ArrayBuffer} ab */
|
||||||
constructor(ab) {
|
constructor(ab) {
|
||||||
super();
|
super();
|
||||||
|
@ -384,6 +398,16 @@ export class PngParser extends EventTarget {
|
||||||
return this;
|
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.
|
* Type-safe way to bind a listener for a PngImageDataEvent.
|
||||||
* @param {function(PngImageDataEvent): void} listener
|
* @param {function(PngImageDataEvent): void} listener
|
||||||
|
@ -746,6 +770,20 @@ export class PngParser extends EventTarget {
|
||||||
this.dispatchEvent(new PngExifProfileEvent(exifValueMap));
|
this.dispatchEvent(new PngExifProfileEvent(exifValueMap));
|
||||||
break;
|
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
|
// https://www.w3.org/TR/png-3/#11IDAT
|
||||||
case 'IDAT':
|
case 'IDAT':
|
||||||
/** @type {PngImageData} */
|
/** @type {PngImageData} */
|
||||||
|
@ -836,6 +874,9 @@ async function main() {
|
||||||
parser.onExifProfile(evt => {
|
parser.onExifProfile(evt => {
|
||||||
// console.dir(evt.exifProfile);
|
// console.dir(evt.exifProfile);
|
||||||
});
|
});
|
||||||
|
parser.onHistogram(evt => {
|
||||||
|
// console.dir(evt.histogram);
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await parser.start();
|
await parser.start();
|
||||||
|
|
BIN
tests/image-testfiles/ch1n3p04.png
Normal file
BIN
tests/image-testfiles/ch1n3p04.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 258 B |
Loading…
Add table
Add a link
Reference in a new issue