UNPKG

exiv2-wasm

Version:

Exiv2 in the browser via WebAssembly (read/write EXIF/IPTC/XMP).

211 lines (166 loc) 5.63 kB
# exiv2-wasm > 🇰🇷 Read this in Korean: **[README.ko.md](README.ko.md)** Use [Exiv2](https://exiv2.org/) in the browser via **WebAssembly**. A tiny C++ wrapper (embind) exposes simple functions to **read/write EXIF / IPTC / XMP**. Minimal deps are built for wasm (**expat, brotli dec/common, inih**); zlib comes from the Emscripten port. --- ## Online Demo - [한국어 버전](https://daissue.app/exif-editor) - [English version](https://daissue.app/en/exif-editor) --- ## Project structure ``` exiv2-wasm/ ├─ exiv2/ # submodule (Exiv2) ├─ libexpat/ # submodule (expat) ├─ brotli/ # submodule (google/brotli) ├─ inih/ # submodule (benhoyt/inih) ├─ scripts/ ├─ build.ps1 # Windows PowerShell build └─ build.bash # Linux/macOS bash build ├─ wrapper.cpp # embind wrapper (read/write metadata) ├─ index.html # demo UI page ├─ dist/ # build outputs: exiv2.js / exiv2.wasm └─ (build/, deps/) # build cache / installed deps (git-ignored) ``` Clone with submodules: ```bash git clone --recurse-submodules https://github.com/gerosyab/exiv2-wasm.git ``` --- ## Prerequisites ### Tools - **CMake**, **Ninja** - **Emscripten SDK** (emcmake / emcc / em++ / emar) **Windows (PowerShell)** ```powershell winget install Kitware.CMake winget install Ninja-build.Ninja ``` **Linux (Debian/Ubuntu)** ```bash sudo apt update sudo apt install -y cmake ninja-build python3 ``` **Emscripten SDK (all OS)** ```bash # anywhere you like git clone https://github.com/emscripten-core/emsdk.git cd emsdk ./emsdk install latest ./emsdk activate latest # new shell(s): source ./emsdk_env.sh # Linux/macOS # or on Windows PowerShell: # .\emsdk_env.ps1 ``` > Re-run `emsdk_env.sh` / `emsdk_env.ps1` in each new shell. --- ## Build **Windows (PowerShell)** ```powershell cd exiv2-wasm # one-session policy (optional) Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass # clean build .\scripts\build.ps1 -Clean # incremental build .\scripts\build.ps1 ``` **Linux/macOS (bash/zsh)** ```bash cd exiv2-wasm chmod +x scripts/build.bash # clean build ./scripts/build.bash -c # incremental build ./scripts/build.bash ``` **Outputs:** `dist/exiv2.js` and `dist/exiv2.wasm` --- ## Run the demo ```bash # from project root python -m http.server 8080 # open: # http://localhost:8080/index.html ``` --- ## JavaScript usage **Wrapper API:** - `read(u8: Uint8Array) -> { exif: Object, iptc: Object, xmp: Object }` - `readTagText(u8, key: string) -> string | null` - `readTagBytes(u8, key: string) -> Uint8Array | null` - `writeString(u8, key: string, value: string) -> Uint8Array` (returns new buffer) - `writeBytes(u8, key: string, data: Uint8Array) -> Uint8Array` **Browser (CDN + `<script>` global function)** ```html <script src="https://unpkg.com/exiv2-wasm"></script> <script> (async () => { const exiv2 = await createExiv2Module(); async function fileToU8(file) { const buf = await file.arrayBuffer(); return new Uint8Array(buf); } document.querySelector('#file').addEventListener('change', async (e) => { const u8 = await fileToU8(e.target.files[0]); const meta = exiv2.read(u8); console.log('Camera Model:', meta.exif['Exif.Image.Model']); }); })(); </script> <input id="file" type="file" accept="image/*"> ``` **Browser (CDN + ESM import)** ```js <script type="module"> import { createExiv2Module } from 'https://cdn.jsdelivr.net/npm/exiv2-wasm/+esm'; const exiv2 = await createExiv2Module(); const input = document.querySelector('#file'); input.addEventListener('change', async (e) => { const file = e.target.files[0]; const buf = new Uint8Array(await file.arrayBuffer()); const meta = exiv2.read(buf); console.log('Camera Model:', meta.exif['Exif.Image.Model']); }); </script> <input id="file" type="file" accept="image/*"> ``` **ESM (Node.js / Vite / webpack / Rollup)** ``` import { createExiv2Module } from 'exiv2-wasm'; const exiv2 = await createExiv2Module(); const fs = await import('fs/promises'); const u8 = new Uint8Array(await fs.readFile('image.jpg')); const meta = exiv2.read(u8); console.log('Model:', meta.exif['Exif.Image.Model']); ``` **CommonJS** ```js const { createExiv2Module } = require('exiv2-wasm'); const fs = require('fs'); function fileToU8(path) { return new Uint8Array(fs.readFileSync(path)); } createExiv2Module().then((exiv2) => { const u8 = fileToU8('image.jpg'); const meta = exiv2.read(u8); console.log('Model:', meta.exif['Exif.Image.Model']); }); ``` **Common keys (examples)** - Camera: `Exif.Image.Make`, `Exif.Image.Model` - Exposure: `Exif.Photo.ExposureTime`, `Exif.Photo.ShutterSpeedValue` - Aperture: `Exif.Photo.FNumber`, `Exif.Photo.ApertureValue` - ISO: `Exif.Photo.PhotographicSensitivity` (or `Exif.Photo.ISOSpeedRatings`) - Title/Author/Comment: - XMP: `Xmp.dc.title`, `Xmp.dc.creator`, `Xmp.dc.description` - EXIF: `Exif.Image.ImageDescription`, `Exif.Image.Artist`, `Exif.Photo.UserComment` - **Windows XP* Unicode**: `Exif.Image.XPTitle`, `Exif.Image.XPAuthor`, `Exif.Image.XPComment` (UTF-16LE) --- ## Notes - Exiv2 CLI build is disabled: `-DEXIV2_BUILD_EXIV2_COMMAND=OFF` - BMFF/HEIF support enabled: `-DEXIV2_ENABLE_BMFF=ON` - If submodules show empty after clone: `git submodule update --init --recursive`