pdfkit/lib/image/jpeg.js
Luiz Américo 5bbd9a18cb
Support Jpeg Exif Orientation (#1482)
Co-authored-by: Franklin Strube <fstrube@morevang.com>
Co-authored-by: Luiz Américo Pereira Câmara <blikblum@users.noreply.github.com>
2023-12-03 07:48:00 -03:00

97 lines
1.8 KiB
JavaScript

import exif from 'jpeg-exif';
const MARKERS = [
0xffc0,
0xffc1,
0xffc2,
0xffc3,
0xffc5,
0xffc6,
0xffc7,
0xffc8,
0xffc9,
0xffca,
0xffcb,
0xffcc,
0xffcd,
0xffce,
0xffcf
];
const COLOR_SPACE_MAP = {
1: 'DeviceGray',
3: 'DeviceRGB',
4: 'DeviceCMYK'
};
class JPEG {
constructor(data, label) {
let marker;
this.data = data;
this.label = label;
if (this.data.readUInt16BE(0) !== 0xffd8) {
throw 'SOI not found in JPEG';
}
// Parse the EXIF orientation
this.orientation = exif.fromBuffer(this.data).Orientation || 1;
let pos = 2;
while (pos < this.data.length) {
marker = this.data.readUInt16BE(pos);
pos += 2;
if (MARKERS.includes(marker)) {
break;
}
pos += this.data.readUInt16BE(pos);
}
if (!MARKERS.includes(marker)) {
throw 'Invalid JPEG.';
}
pos += 2;
this.bits = this.data[pos++];
this.height = this.data.readUInt16BE(pos);
pos += 2;
this.width = this.data.readUInt16BE(pos);
pos += 2;
const channels = this.data[pos++];
this.colorSpace = COLOR_SPACE_MAP[channels];
this.obj = null;
}
embed(document) {
if (this.obj) {
return;
}
this.obj = document.ref({
Type: 'XObject',
Subtype: 'Image',
BitsPerComponent: this.bits,
Width: this.width,
Height: this.height,
ColorSpace: this.colorSpace,
Filter: 'DCTDecode'
});
// add extra decode params for CMYK images. By swapping the
// min and max values from the default, we invert the colors. See
// section 4.8.4 of the spec.
if (this.colorSpace === 'DeviceCMYK') {
this.obj.data['Decode'] = [1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0];
}
this.obj.end(this.data);
// free memory
return (this.data = null);
}
}
export default JPEG;