@squoosh-kit/qoi 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +227 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # @squoosh-kit/qoi
2
+
3
+ [![npm version](https://badge.fury.io/js/%40squoosh-kit%2Fqoi.svg)](https://badge.fury.io/js/%40squoosh-kit%2Fqoi)
4
+ [![Bun](https://img.shields.io/badge/Bun-000000?logo=bun&logoColor=white)](https://bun.sh/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
7
+
8
+ ![Squoosh-Kit](https://github.com/bnowak008/squoosh-kit/blob/main/squoosh-kit-banner.webp)
9
+
10
+ ## Squoosh-Kit
11
+
12
+ Squoosh-Kit is built on a simple idea: provide a lightweight and modular bridge to the powerful, production-tested codecs from Google's Squoosh project. This package (`@squoosh-kit/qoi`) is one of those modules.
13
+
14
+ **Directly from the Source**
15
+ We don't modify the core QOI codec. The WebAssembly (`.wasm`) binary is taken directly from the official Squoosh repository builds. This means you get the exact same performance, quality, and reliability you'd expect from Squoosh.
16
+
17
+ **A Thin, Modern Wrapper**
18
+ Our goal is to provide a minimal, modern JavaScript wrapper around the codec. We handle the tricky parts—like loading WASM, managing web workers, and providing a clean, type-safe API—so you can focus on your application. The library is designed to be a thin bridge, not a heavy framework.
19
+
20
+ **Modular by Design**
21
+ We believe you should only install what you need. As a standalone package, `@squoosh-kit/qoi` allows you to add QOI encoding and decoding to your project without pulling in other unrelated image processing tools.
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ bun add @squoosh-kit/qoi
27
+ # or
28
+ npm install @squoosh-kit/qoi
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ```typescript
34
+ import { encode, decode, createQoiEncoder } from '@squoosh-kit/qoi';
35
+ import type { ImageInput } from '@squoosh-kit/qoi';
36
+
37
+ // Your image data - from a file, canvas, or anywhere
38
+ const imageData: ImageInput = {
39
+ data: imageBuffer,
40
+ width: 800,
41
+ height: 600,
42
+ };
43
+
44
+ // Encode to QOI (lossless, extremely fast)
45
+ const qoiBuffer = await encode(imageData);
46
+
47
+ // Decode a QOI file back to raw pixel data
48
+ const rawImage = await decode(existingQoi);
49
+
50
+ // For multiple images, create a persistent encoder
51
+ const encoder = createQoiEncoder('worker');
52
+ const qoi = await encoder(imageData);
53
+ await encoder.terminate();
54
+ ```
55
+
56
+ ## What is QOI?
57
+
58
+ QOI (Quite OK Image format) is a fast, lossless image format designed as a simpler alternative to PNG. It trades slightly larger file sizes for dramatically faster encode/decode speed — often 20-50x faster than PNG. QOI is a good fit for:
59
+
60
+ - Image pipelines where speed matters more than file size
61
+ - Intermediate storage between processing steps
62
+ - Applications that need lossless quality with minimal CPU overhead
63
+
64
+ ## Public API
65
+
66
+ Only the following exports are part of the public API and guaranteed to be stable across versions:
67
+
68
+ - `encode(image, signal?)` - Encode raw pixel data to QOI format
69
+ - `decode(data, signal?)` - Decode a QOI file to raw pixel data
70
+ - `createQoiEncoder(mode?)` - Create a reusable encoder function
71
+ - `createQoiDecoder(mode?)` - Create a reusable decoder function
72
+ - `ImageInput` type - Input image data structure
73
+ - `QoiEncoderFactory` type - Type for reusable encoder functions
74
+ - `QoiDecoderFactory` type - Type for reusable decoder functions
75
+
76
+ ## Real-World Examples
77
+
78
+ **Fast intermediate storage in a processing pipeline**
79
+
80
+ ```typescript
81
+ // Step 1: decode source image
82
+ const source = await decode(inputPng);
83
+
84
+ // Step 2: process (resize, filter, etc.)
85
+ const processed = await someProcessingStep(source);
86
+
87
+ // Step 3: store as QOI for fast re-reads
88
+ const qoiBuffer = await encode(processed);
89
+ await writeFile('intermediate.qoi', qoiBuffer);
90
+
91
+ // Later: fast reload
92
+ const reloaded = await decode(await readFile('intermediate.qoi'));
93
+ ```
94
+
95
+ **Batch conversion with cancellation**
96
+
97
+ ```typescript
98
+ const encoder = createQoiEncoder('client'); // Direct encoding, no worker
99
+ const controller = new AbortController();
100
+ setTimeout(() => controller.abort(), 30000);
101
+
102
+ try {
103
+ for (const imageData of images) {
104
+ const qoiData = await encoder(imageData, controller.signal);
105
+ await writeFile(`output.qoi`, qoiData);
106
+ }
107
+ } catch (error) {
108
+ if (error.name === 'AbortError') {
109
+ console.log('Batch cancelled');
110
+ }
111
+ } finally {
112
+ await encoder.terminate();
113
+ }
114
+ ```
115
+
116
+ ## API Reference
117
+
118
+ ### `encode(image, signal?)`
119
+
120
+ Encodes raw RGBA pixel data to QOI format. QOI is always lossless.
121
+
122
+ - `image` - `ImageInput` object with your pixel data
123
+ - `signal` - (optional) `AbortSignal` to cancel the operation
124
+ - **Returns** - `Promise<Uint8Array>` with the encoded QOI data
125
+
126
+ ### `decode(data, signal?)`
127
+
128
+ Decodes a QOI file back to raw RGBA pixel data.
129
+
130
+ - `data` - `BufferSource` containing the QOI file bytes
131
+ - `signal` - (optional) `AbortSignal` to cancel the operation
132
+ - **Returns** - `Promise<ImageData>` with decoded pixel data, width, and height
133
+
134
+ ### `createQoiEncoder(mode?)`
135
+
136
+ Creates a reusable encoder. More efficient for processing multiple images.
137
+
138
+ - `mode` - (optional) `'worker'` or `'client'`, defaults to `'worker'`
139
+ - **Returns** - A function with the same signature as `encode()`
140
+
141
+ ### `createQoiDecoder(mode?)`
142
+
143
+ Creates a reusable decoder. More efficient for processing multiple images.
144
+
145
+ - `mode` - (optional) `'worker'` or `'client'`, defaults to `'worker'`
146
+ - **Returns** - A function with the same signature as `decode()`
147
+
148
+ ## Cancellation Support
149
+
150
+ To cancel an operation in progress, pass an `AbortSignal`:
151
+
152
+ ```typescript
153
+ const controller = new AbortController();
154
+
155
+ const encodePromise = encode(imageData, controller.signal);
156
+ setTimeout(() => controller.abort(), 5000);
157
+
158
+ try {
159
+ const result = await encodePromise;
160
+ } catch (error) {
161
+ if (error.name === 'AbortError') {
162
+ console.log('Encoding was cancelled');
163
+ }
164
+ }
165
+ ```
166
+
167
+ **Important**: If no signal is provided, the operation cannot be cancelled. It will run to completion.
168
+
169
+ ## Input Validation
170
+
171
+ All inputs are automatically validated before processing:
172
+
173
+ ```typescript
174
+ // Will throw TypeError: image must be an object
175
+ await encode(null);
176
+
177
+ // Will throw TypeError: image.data must be Uint8Array or Uint8ClampedArray
178
+ await encode({ data: [0, 0, 0, 255], width: 32, height: 32 });
179
+
180
+ // Will throw RangeError: image.data too small
181
+ await encode({ data: new Uint8Array(100), width: 800, height: 600 });
182
+ ```
183
+
184
+ All validation happens synchronously before WASM processing.
185
+
186
+ ### Package Size
187
+
188
+ This package includes a WebAssembly binary for the QOI codec (~10-15KB gzipped).
189
+
190
+ **Size breakdown:**
191
+
192
+ - JavaScript code: ~4-6KB gzipped
193
+ - TypeScript definitions: ~2KB
194
+ - WASM binary: ~10-15KB gzipped
195
+
196
+ ### Worker Cleanup
197
+
198
+ When using worker mode, always clean up when done:
199
+
200
+ ```typescript
201
+ const encoder = createQoiEncoder('worker');
202
+
203
+ try {
204
+ const qoiData = await encoder(imageData);
205
+ } finally {
206
+ await encoder.terminate();
207
+ }
208
+ ```
209
+
210
+ **Note**: In client mode, `terminate()` is a no-op. It's always safe to call for consistency.
211
+
212
+ ## Performance Tips
213
+
214
+ - **QOI shines in pipelines** - Use it for intermediate steps where you need fast lossless storage
215
+ - **Use client mode for servers** - QOI is already fast; worker overhead can exceed encode time for small images
216
+ - **Compare to PNG** - QOI files are slightly larger but encode/decode significantly faster
217
+
218
+ ## Works With
219
+
220
+ - **Bun** - First-class support, fastest performance
221
+ - **Node.js** - Works great in server environments
222
+ - **Browsers** - Full Web Worker support for responsive UIs
223
+ - **TypeScript** - Complete type definitions included
224
+
225
+ ## License
226
+
227
+ MIT - use it freely in your projects
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squoosh-kit/qoi",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "description": "QOI (Quite OK Image) codec for squoosh-kit, providing lossless encoding and decoding.",
6
6
  "author": "Bartosz Nowak <bnowak008@gmail.com>",
@@ -47,6 +47,6 @@
47
47
  "test": "bun test"
48
48
  },
49
49
  "dependencies": {
50
- "@squoosh-kit/runtime": "workspace:*"
50
+ "@squoosh-kit/runtime": "0.2.4"
51
51
  }
52
52
  }