From 79265ae1eeef611c88c4cd3ce7b4995237c15700 Mon Sep 17 00:00:00 2001 From: Diego Muracciole Date: Sat, 18 Apr 2026 15:37:04 +0200 Subject: [PATCH 1/3] refactor: remove Buffer dependency from EXIF orientation parser --- .prettierrc | 7 ++++--- lib/binary.js | 31 +++++++++++++++++++++++++++++++ lib/image/jpeg.js | 32 ++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 lib/binary.js diff --git a/.prettierrc b/.prettierrc index 0aa186e36..a20502b7f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ -{ - "singleQuote": true -} \ No newline at end of file +{ + "singleQuote": true, + "trailingComma": "all" +} diff --git a/lib/binary.js b/lib/binary.js new file mode 100644 index 000000000..f85e7d88f --- /dev/null +++ b/lib/binary.js @@ -0,0 +1,31 @@ +/* +Binary helpers — Uint8Array-native replacements for Node Buffer operations. +*/ + +export const toBinaryString = bytes => { + const chunkSize = 0x8000; + let out = ''; + for (let i = 0; i < bytes.length; i += chunkSize) { + const end = Math.min(i + chunkSize, bytes.length); + out += String.fromCharCode.apply(null, bytes.subarray(i, end)); + } + return out; +}; + +export const readUInt16BE = (bytes, offset = 0) => + ((bytes[offset] << 8) | bytes[offset + 1]) >>> 0; + +export const readUInt16LE = (bytes, offset = 0) => + ((bytes[offset + 1] << 8) | bytes[offset]) >>> 0; + +export const readUInt32BE = (bytes, offset = 0) => + (bytes[offset] * 0x1000000 + + ((bytes[offset + 1] << 16) | + (bytes[offset + 2] << 8) | + bytes[offset + 3])) >>> + 0; + +export const readUInt32LE = (bytes, offset = 0) => + ((bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16)) + + bytes[offset + 3] * 0x1000000) >>> + 0; diff --git a/lib/image/jpeg.js b/lib/image/jpeg.js index 8510df32c..793179a18 100644 --- a/lib/image/jpeg.js +++ b/lib/image/jpeg.js @@ -1,9 +1,17 @@ +import { + readUInt16BE, + readUInt16LE, + readUInt32BE, + readUInt32LE, + toBinaryString, +} from '../binary'; + /** * Parse EXIF orientation from JPEG buffer - * @param {Buffer} data - JPEG image data + * @param {Uint8Array} data - JPEG image data * @returns {number|null} Orientation value (1-8) or null if not found */ -const parseExifOrientation = (data) => { +const parseExifOrientation = data => { if (!data || data.length < 20) return null; let pos = 2; // Skip SOI marker @@ -13,7 +21,7 @@ const parseExifOrientation = (data) => { while (pos < data.length && data[pos] !== 0xff) pos++; if (pos >= data.length - 4) return null; - const marker = data.readUInt16BE(pos); + const marker = readUInt16BE(data, pos); pos += 2; // SOS marker - image data starts, stop searching @@ -23,28 +31,28 @@ const parseExifOrientation = (data) => { if ((marker >= 0xffd0 && marker <= 0xffd9) || marker === 0xff01) continue; if (pos + 2 > data.length) return null; - const segmentLength = data.readUInt16BE(pos); + const segmentLength = readUInt16BE(data, pos); // APP1 (EXIF) marker if (marker === 0xffe1 && pos + 8 <= data.length) { - const exifHeader = data.subarray(pos + 2, pos + 8).toString('binary'); + const exifHeader = toBinaryString(data.subarray(pos + 2, pos + 8)); if (exifHeader === 'Exif\x00\x00') { const tiffStart = pos + 8; if (tiffStart + 8 > data.length) return null; // Byte order - const byteOrder = data - .subarray(tiffStart, tiffStart + 2) - .toString('ascii'); + const byteOrder = toBinaryString( + data.subarray(tiffStart, tiffStart + 2), + ); const isLittleEndian = byteOrder === 'II'; if (!isLittleEndian && byteOrder !== 'MM') return null; const read16 = isLittleEndian - ? (o) => data.readUInt16LE(o) - : (o) => data.readUInt16BE(o); + ? o => readUInt16LE(data, o) + : o => readUInt16BE(data, o); const read32 = isLittleEndian - ? (o) => data.readUInt32LE(o) - : (o) => data.readUInt32BE(o); + ? o => readUInt32LE(data, o) + : o => readUInt32BE(data, o); // Verify TIFF magic number (42) if (read16(tiffStart + 2) !== 42) return null; From c68716054ab5912fb1402f4e31480920eab58ba7 Mon Sep 17 00:00:00 2001 From: Diego Muracciole Date: Sat, 18 Apr 2026 15:50:01 +0200 Subject: [PATCH 2/3] fix: lint --- lib/binary.js | 2 +- lib/image/jpeg.js | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/binary.js b/lib/binary.js index f85e7d88f..eaca49e3a 100644 --- a/lib/binary.js +++ b/lib/binary.js @@ -2,7 +2,7 @@ Binary helpers — Uint8Array-native replacements for Node Buffer operations. */ -export const toBinaryString = bytes => { +export const toBinaryString = (bytes) => { const chunkSize = 0x8000; let out = ''; for (let i = 0; i < bytes.length; i += chunkSize) { diff --git a/lib/image/jpeg.js b/lib/image/jpeg.js index 793179a18..7480f6329 100644 --- a/lib/image/jpeg.js +++ b/lib/image/jpeg.js @@ -11,7 +11,7 @@ import { * @param {Uint8Array} data - JPEG image data * @returns {number|null} Orientation value (1-8) or null if not found */ -const parseExifOrientation = data => { +const parseExifOrientation = (data) => { if (!data || data.length < 20) return null; let pos = 2; // Skip SOI marker @@ -48,11 +48,11 @@ const parseExifOrientation = data => { if (!isLittleEndian && byteOrder !== 'MM') return null; const read16 = isLittleEndian - ? o => readUInt16LE(data, o) - : o => readUInt16BE(data, o); + ? (o) => readUInt16LE(data, o) + : (o) => readUInt16BE(data, o); const read32 = isLittleEndian - ? o => readUInt32LE(data, o) - : o => readUInt32BE(data, o); + ? (o) => readUInt32LE(data, o) + : (o) => readUInt32BE(data, o); // Verify TIFF magic number (42) if (read16(tiffStart + 2) !== 42) return null; From f931c9fc59772923eeb6299fdbcdbd478a9a6291 Mon Sep 17 00:00:00 2001 From: Diego Muracciole Date: Wed, 22 Apr 2026 00:03:27 +0200 Subject: [PATCH 3/3] chore: update .prettierrc --- .prettierrc | 1 - 1 file changed, 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index a20502b7f..9e74d98a6 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,3 @@ { "singleQuote": true, - "trailingComma": "all" }