'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var assert = require('node:assert'); var node_buffer = require('node:buffer'); var node_util = require('node:util'); const RST0 = 0xD0; const SOI = 0xD8; const EOI = 0xD9; const SOS = 0xDA; const COM = 0xFE; const FF = 0xFF; function indexOfNextMarker(buffer, offset = 0) { if (buffer == null) throw new TypeError('not a buffer') let idx = buffer.indexOf(FF, offset); if (idx === -1) return -1 // Swallow optional FF padding while (idx < buffer.length && buffer[idx + 1] === FF) ++idx; // There should be at least one marker byte left if (idx === buffer.length - 1) return -1 else return idx + 1 } /** * Parses a JPEG segment at the given offset in the buffer. * Returns the segment's marker, as well as the payload's * size and offset in the buffer. */ function parse(buffer, offset = 0) { let size = 0; let marker = buffer.readUInt8(offset); offset += 1; // SOI, EOI, and RSTn have no payload! if (!(marker >= RST0 && marker <= EOI)) { assert(offset + 2 <= buffer.length, 'bad marker size: 16-bit uint expected'); size = buffer.readUInt16BE(offset); offset += 2; assert(size >= 2, 'bad marker size: >= 2 expected'); size -= 2; assert(offset + size <= buffer.length, 'premature end of segment'); } return { marker, offset, size } } /** * Scans the buffer, returning an iterator of all JPEG segments. */ function* scan(buffer, offset = 0) { offset = indexOfNextMarker(buffer, offset); while (offset !== -1) { let segment = parse(buffer, offset); yield segment; if (segment.marker === SOS) break if (segment.marker === EOI) break offset = indexOfNextMarker(buffer, segment.offset + segment.size); } } const check = (...args) => compare(...args) === 0; const compare = (buffer, bytes, offset = 0) => buffer .subarray(offset, offset + bytes.length) .compare(node_buffer.Buffer.from(bytes)); /** * Returns an array of all textual comments in a JPEG file. * If `options.encoding` is set to `null` the returned * array will contain all COM segments with corresponding * raw `payload` Buffers. * * @param [Buffer] buffer the JPEG file data * @param [object] options */ function rdjpgcom(buffer, { encoding = 'utf-8' } = {}) { assert(check(buffer, [FF, SOI]), 'no JPEG data'); let td = (encoding == null) ? null : new node_util.TextDecoder(encoding, { fatal: true }); let comments = []; let segments = scan(buffer, 2); for (let { marker, offset, size } of segments) { try { if (marker === COM) { let payload = buffer.subarray(offset, offset + size); if (encoding == null) comments.push({ marker, offset, payload }); else comments.push(td.decode(payload)); } } catch (e) { // Ignore text decoding errors if (!(e instanceof TypeError)) throw e } } return comments } exports.default = rdjpgcom; exports.rdjpgcom = rdjpgcom;