From cbb74059b318fb227d6a26bedf033af9b7a6a218 Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Sun, 23 Mar 2025 23:44:21 -0500 Subject: [PATCH] Remove exifr dependency --- .vscode/settings.json | 1 - package.json | 1 - pnpm-lock.yaml | 8 -------- src/components/ImageInput.tsx | 6 ++---- src/utility/exif.ts | 37 +++++++++++++++++++++++++++++++++++ 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5ef0cd4d..ea94cecd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,7 +17,6 @@ "depluralizes", "Eterna", "exif", - "exifr", "exiftool", "favicons", "favs", diff --git a/package.json b/package.json index d9d875be..289cc815 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "cmdk": "^1.1.1", "date-fns": "^4.1.0", "date-fns-tz": "^3.2.0", - "exifr": "^7.1.3", "fast-deep-equal": "^3.1.3", "framer-motion": "^12.5.0", "nanoid": "^5.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32b9bdc4..fb7ca279 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -59,9 +59,6 @@ importers: date-fns-tz: specifier: ^3.2.0 version: 3.2.0(date-fns@4.1.0) - exifr: - specifier: ^7.1.3 - version: 7.1.3 fast-deep-equal: specifier: ^3.1.3 version: 3.1.3 @@ -2469,9 +2466,6 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - exifr@7.1.3: - resolution: {integrity: sha512-g/aje2noHivrRSLbAUtBPWFbxKdKhgj/xr1vATDdUXPOFYJlQ62Ft0oy+72V6XLIpDJfHs6gXLbBLAolqOXYRw==} - exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} @@ -7229,8 +7223,6 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - exifr@7.1.3: {} - exit@0.1.2: {} expect@29.7.0: diff --git a/src/components/ImageInput.tsx b/src/components/ImageInput.tsx index d9e4702b..44c50d22 100644 --- a/src/components/ImageInput.tsx +++ b/src/components/ImageInput.tsx @@ -2,8 +2,7 @@ import { blobToImage } from '@/utility/blob'; import { useRef, RefObject } from 'react'; -import { CopyExif } from '@/utility/exif'; -import exifr from 'exifr'; +import { CopyExif, getOrientation } from '@/utility/exif'; import { clsx } from 'clsx/lite'; import { ACCEPTED_PHOTO_FILE_TYPES } from '@/photo'; import { FiUploadCloud } from 'react-icons/fi'; @@ -131,8 +130,7 @@ export default function ImageInput({ ctx.save(); - let orientation = await exifr - .orientation(file) + let orientation = await getOrientation(file) .catch(() => 1) ?? 1; // Preserve EXIF data for PNGs diff --git a/src/utility/exif.ts b/src/utility/exif.ts index f732f53e..9eb7c65e 100644 --- a/src/utility/exif.ts +++ b/src/utility/exif.ts @@ -124,3 +124,40 @@ export const CopyExif = async ( return new Blob([dest.slice(0, 2), exif, dest.slice(2)], { type }); }; +export const getOrientation = (file: File): Promise => + file.arrayBuffer().then(buffer => { + const view = new DataView(buffer); + + if (view.getUint16(0, false) !== 0xFFD8) { + return -2; + } else { + const length = view.byteLength; + let offset = 2; + while (offset < length) { + if (view.getUint16(offset + 2, false) <= 8) return -1; + const marker = view.getUint16(offset, false); + offset += 2; + if (marker === 0xFFE1) { + if (view.getUint32(offset += 2, false) !== 0x45786966) { + return -1; + } else { + const little = view.getUint16(offset += 6, false) === 0x4949; + offset += view.getUint32(offset + 4, little); + const tags = view.getUint16(offset, little); + offset += 2; + for (let i = 0; i < tags; i++) { + if (view.getUint16(offset + (i * 12), little) === 0x0112) { + return view.getUint16(offset + (i * 12) + 8, little); + } + } + } + } else if ((marker & 0xFF00) !== 0xFF00) { + break; + } else { + offset += view.getUint16(offset, false); + } + } + + return -1; + }; + });