npm package: @refilelabs/image
Description: Wasm-based image processing library developed by re;file labs
Latest version: 0.3.1

# @refilelabs/image
[![NPM Version](https://npmx.dev/api/registry/badge/version/@refilelabs/image?label=npm)](https://npmx.dev/package/@refilelabs/image)

A WebAssembly-powered library for advanced image manipulation and format conversion. Powered by Rust and compiled to WebAssembly — runs in the browser, Node.js, and any modern bundler environment. Supports converting, resizing, cropping, and inspecting images entirely client-side.

Used under the hood at [re;file labs](https://refilelabs.com/image) to power all image processing features.

## Installation

```bash
npm install @refilelabs/image
```

The package ships three builds and automatically selects the right one via the `exports` field in `package.json`:

| Environment | Build used |
|---|---|
| Vite / Webpack / Rollup (bundler) | `bundler` — bundler handles WASM loading, no `init()` needed |
| Node.js | `node` — uses `fs` to load the WASM binary, no `init()` needed |
| Raw browser (`<script type="module">`) | `web` — explicit `init()` required |

## Setup

### Vite / Nuxt

Vite requires `vite-plugin-wasm` to handle `.wasm` imports:

```bash
npm install -D vite-plugin-wasm
```

```js
// vite.config.js
import wasm from 'vite-plugin-wasm'

export default {
  plugins: [wasm()],
}
```

For Nuxt, add it to `nuxt.config.ts`:

```ts
import wasm from 'vite-plugin-wasm'

export default defineNuxtConfig({
  vite: {
    plugins: [wasm()],
  },
})
```

### Webpack 5

No additional config needed — Webpack 5 handles `.wasm` imports natively.

### Raw browser (no bundler)

No plugin needed. Call `init()` explicitly before using any functions.

## Usage

### Bundler (Vite, Webpack, Rollup)

```javascript
import { convertImage, loadMetadata, resizeImage, saveMetadata } from '@refilelabs/image'

const file = new Uint8Array(/* ... */)
const cb = ({ progress, message }) => console.log(`${progress}% — ${message}`)

const metadata = loadMetadata(file, 'image/jpeg', cb)
console.log(metadata.width, metadata.height, metadata.gps)
```

### Node.js

```javascript
import { convertImage } from '@refilelabs/image'

const file = new Uint8Array(/* ... */)
const converted = convertImage(file, 'image/png', 'image/webp', ({ progress }) => {}, null)
```

### Raw browser (no bundler)

```javascript
import init, { resizeImage } from '@refilelabs/image/web'

await init() // must call init() explicitly in web target

const resized = resizeImage(file, 'image/png', 800, 600, ({ progress, message }) => {})
```

---

## API Reference

### `loadMetadata(file, src_type, cb): Metadata`

Extracts dimensions and EXIF metadata from an image file.

**Parameters:**
- `file` (`Uint8Array`): The image file bytes.
- `src_type` (`string`): MIME type of the source image (e.g. `"image/jpeg"`).
- `cb` (`(update: { progress: number, message: string }) => void`): Progress callback.

**Returns:** `Metadata`

---

### `saveMetadata(file, src_type, changes, stripAll, stripGps, cb): Uint8Array`

Saves metadata changes to an image file. Supports JPEG (in-place byte edit, no re-encode), PNG, and WebP (re-encode with EXIF embedded via `set_exif_metadata`).

**Parameters:**
- `file` (`Uint8Array`): The image file bytes.
- `src_type` (`string`): MIME type of the source image.
- `changes` (`MetadataChange[]`): Array of tag changes to apply. Each item: `{ tag: string, value: string | null }`. Pass `null` value to remove a tag.
- `stripAll` (`boolean`): If `true`, re-encodes the image stripping all metadata. Ignores `changes`.
- `stripGps` (`boolean`): If `true`, removes all GPS tags after applying `changes`.
- `cb` (`(update: { progress: number, message: string }) => void`): Progress callback.

**Returns:** `Uint8Array` — the modified image bytes.

---

### `convertImage(file, src_type, target_type, cb, convert_settings?): Uint8Array`

Converts an image from one format to another.

**Parameters:**
- `file` (`Uint8Array`): The image file bytes.
- `src_type` (`string`): MIME type of the source image.
- `target_type` (`string`): Target MIME type (e.g. `"image/webp"`).
- `cb` (`(update: { progress: number, message: string }) => void`): Progress callback.
- `convert_settings` (`Settings | null`, optional): Format-specific settings (e.g. SVG rasterization size).

**Returns:** `Uint8Array` — the converted image bytes.

---

### `resizeImage(file, src_type, width, height, cb): Uint8Array`

Resizes an image to exact pixel dimensions using the Lanczos3 filter.

**Parameters:**
- `file` (`Uint8Array`): The image file bytes.
- `src_type` (`string`): MIME type of the source image.
- `width` (`number`): Target width in pixels.
- `height` (`number`): Target height in pixels.
- `cb` (`(update: { progress: number, message: string }) => void`): Progress callback.

**Returns:** `Uint8Array` — the resized image bytes, in the original format.

**Notes:**
- Resizes to exact dimensions without preserving aspect ratio.
- SVG input is rasterized before resizing; output is PNG.

---

### `cropImage(file, src_type, x, y, width, height, cb): Uint8Array`

Crops an image to the specified region. Preserves the source format.

**Parameters:**
- `file` (`Uint8Array`): The image file bytes.
- `src_type` (`string`): MIME type of the source image (e.g. `"image/jpeg"`).
- `x` (`number`): Left offset of the crop region in pixels.
- `y` (`number`): Top offset of the crop region in pixels.
- `width` (`number`): Width of the crop region in pixels.
- `height` (`number`): Height of the crop region in pixels.
- `cb` (`(update: { progress: number, message: string }) => void`): Progress callback.

**Returns:** `Uint8Array` — the cropped image bytes, in the original format.

---

### `getPixels(file, src_type): ImageData`

Decodes an image to raw RGBA pixel data.

**Parameters:**
- `file` (`Uint8Array`): The image file bytes.
- `src_type` (`string`): MIME type of the source image.

**Returns:** `ImageData`

---

## Interfaces

### `Metadata`

- `width` (`number`): Image width in pixels.
- `height` (`number`): Image height in pixels.
- `other` (`Record<string, string> | null`): Non-GPS EXIF fields, keyed by tag description.
- `gps` (`Record<string, string> | null`): GPS EXIF fields, keyed by tag description (e.g. `"Latitude"`, `"Longitude"`). `null` if no GPS data is present.
- `errors` (`string[] | null`): Non-fatal EXIF parse errors, if any.

### `MetadataChange`

- `tag` (`string`): EXIF tag description (e.g. `"Image Description"`, `"Artist"`).
- `value` (`string | null`): New value, or `null` to remove the tag.

### `ImageData`

- `width` (`number`): Image width.
- `height` (`number`): Image height.
- `aspect_ratio` (`number`): Width / height.
- `color_depth` (`number`): Bits per channel.
- `pixels` (`number[]`): Raw RGBA pixel values.

### `SvgSettings`

- `width` (`number`): Rasterization width.
- `height` (`number`): Rasterization height.

### `Settings`

- `type`: `"svg"`
- Includes all `SvgSettings` properties.

---

## License

MIT