UNPKG

image-in-browser

Version:

Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)

164 lines 5.52 kB
import { InputBuffer } from '../../common/input-buffer.js'; import { OutputBuffer } from '../../common/output-buffer.js'; import { ExifData } from '../../exif/exif-data.js'; import { JpegMarker } from './jpeg-marker.js'; export class JpegUtils { readExifData(block) { if (block === undefined) { return undefined; } const signature = block.readUint32(); if (signature !== JpegUtils._exifSignature) { return undefined; } if (block.readUint16() !== 0) { return undefined; } return ExifData.fromInputBuffer(block); } writeAPP1(out, exif) { if (exif.isEmpty) { return; } const exifData = new OutputBuffer(); exif.write(exifData); const exifBytes = exifData.getBytes(); out.writeUint16(exifBytes.length + 8); out.writeUint32(JpegUtils._exifSignature); out.writeUint16(0); out.writeBytes(exifBytes); } readBlock(input) { const length = input.readUint16(); if (length < 2) { return undefined; } return input.readRange(length - 2); } skipBlock(input, output) { const length = input.readUint16(); output === null || output === void 0 ? void 0 : output.writeUint16(length); if (length < 2) { return false; } if (output !== undefined) { output.writeBuffer(input.readRange(length - 2)); } else { input.skip(length - 2); } return true; } nextMarker(input, output) { let c = 0; if (input.isEOS) { return c; } do { do { c = input.read(); output === null || output === void 0 ? void 0 : output.writeByte(c); } while (c !== 0xff && !input.isEOS); if (input.isEOS) { return c; } do { c = input.read(); output === null || output === void 0 ? void 0 : output.writeByte(c); } while (c === 0xff && !input.isEOS); } while (c === 0 && !input.isEOS); return c; } decodeExif(data) { const input = new InputBuffer({ buffer: data, bigEndian: true, }); const soiCheck = input.peek(2); if (soiCheck.get(0) !== 0xff || soiCheck.get(1) !== 0xd8) { return undefined; } let marker = this.nextMarker(input); if (marker !== JpegMarker.soi) { return undefined; } let exif = undefined; marker = this.nextMarker(input); while (marker !== JpegMarker.eoi && !input.isEOS) { switch (marker) { case JpegMarker.app1: exif = this.readExifData(this.readBlock(input)); if (exif !== undefined) { return exif; } break; default: this.skipBlock(input); break; } marker = this.nextMarker(input); } return undefined; } injectExif(exif, data) { const input = new InputBuffer({ buffer: data, bigEndian: true, }); const soiCheck = input.peek(2); if (soiCheck.get(0) !== 0xff || soiCheck.get(1) !== 0xd8) { return undefined; } const output = new OutputBuffer({ size: data.length, bigEndian: true, }); let marker = this.nextMarker(input, output); if (marker !== JpegMarker.soi) { return undefined; } let hasExifBlock = false; const startOffset = input.offset; marker = this.nextMarker(input); while (!hasExifBlock && marker !== JpegMarker.eoi && !input.isEOS) { if (marker === JpegMarker.app1) { const block = this.readBlock(input); const signature = block === null || block === void 0 ? void 0 : block.readUint32(); if (signature === JpegUtils._exifSignature) { hasExifBlock = true; break; } } else { this.skipBlock(input); } marker = this.nextMarker(input); } input.offset = startOffset; if (!hasExifBlock) { this.writeAPP1(output, exif); output.writeBuffer(input.readRange(input.length)); return output.getBytes(); } marker = this.nextMarker(input, output); while (marker !== JpegMarker.eoi && !input.isEOS) { if (marker === JpegMarker.app1) { const saveOffset = input.offset; input.skip(2); const signature = input.readUint32(); input.offset = saveOffset; if (signature === JpegUtils._exifSignature) { this.skipBlock(input); this.writeAPP1(output, exif); output.writeBuffer(input.readRange(input.length)); return output.getBytes(); } } this.skipBlock(input, output); marker = this.nextMarker(input, output); } return output.getBytes(); } } JpegUtils._exifSignature = 0x45786966; //# sourceMappingURL=jpeg-utils.js.map