@squoosh-kit/imagequant 0.2.2 → 0.2.3
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.
- package/README.md +226 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# @squoosh-kit/imagequant
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40squoosh-kit%2Fimagequant)
|
|
4
|
+
[](https://bun.sh/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT) [](https://www.apache.org/licenses/LICENSE-2.0)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
|
|
8
|
+

|
|
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/imagequant`) is one of those modules.
|
|
13
|
+
|
|
14
|
+
**Directly from the Source**
|
|
15
|
+
We don't modify the core ImageQuant 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/imagequant` allows you to add palette-based lossy PNG compression to your project without pulling in other unrelated image processing tools.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bun add @squoosh-kit/imagequant
|
|
27
|
+
# or
|
|
28
|
+
npm install @squoosh-kit/imagequant
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { quantize, createImagequantQuantizer } from '@squoosh-kit/imagequant';
|
|
35
|
+
import type { ImageInput } from '@squoosh-kit/imagequant';
|
|
36
|
+
|
|
37
|
+
const imageData: ImageInput = {
|
|
38
|
+
data: rawPixelBuffer,
|
|
39
|
+
width: 800,
|
|
40
|
+
height: 600,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Quantize to 256 colors (default)
|
|
44
|
+
const quantized = await quantize(imageData);
|
|
45
|
+
// quantized.data is a palette-mapped Uint8ClampedArray
|
|
46
|
+
|
|
47
|
+
// Reduce to 64 colors with full dithering
|
|
48
|
+
const reduced = await quantize(imageData, { numColors: 64, dither: 1.0 });
|
|
49
|
+
|
|
50
|
+
// For multiple images, use a persistent quantizer
|
|
51
|
+
const quantizer = createImagequantQuantizer('worker');
|
|
52
|
+
const result = await quantizer(imageData, { numColors: 128 });
|
|
53
|
+
await quantizer.terminate();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## What is ImageQuant?
|
|
57
|
+
|
|
58
|
+
ImageQuant is a palette quantizer — it reduces a full-color (24-bit RGB) image to a smaller palette of up to 256 colors. This is the same technique used to create indexed-color PNGs (PNG-8), which can be significantly smaller than full-color PNGs for images with limited color ranges like icons, illustrations, and logos.
|
|
59
|
+
|
|
60
|
+
The output is quantized pixel data, not an encoded file. To save as PNG-8, pass the result to `@squoosh-kit/png` or another encoder.
|
|
61
|
+
|
|
62
|
+
ImageQuant is a good fit for:
|
|
63
|
+
|
|
64
|
+
- Icons, logos, and illustrations with limited colors
|
|
65
|
+
- Reducing PNG file sizes for web delivery
|
|
66
|
+
- Preparing images for platforms with palette constraints
|
|
67
|
+
|
|
68
|
+
## Public API
|
|
69
|
+
|
|
70
|
+
Only the following exports are part of the public API and guaranteed to be stable across versions:
|
|
71
|
+
|
|
72
|
+
- `quantize(image, options?, signal?)` - Reduce an image to a limited color palette
|
|
73
|
+
- `createImagequantQuantizer(mode?)` - Create a reusable quantizer function
|
|
74
|
+
- `ImageInput` type - Input image data structure
|
|
75
|
+
- `ImagequantOptions` type - Quantization configuration
|
|
76
|
+
- `ImagequantQuantizerFactory` type - Type for reusable quantizer functions
|
|
77
|
+
|
|
78
|
+
## Real-World Examples
|
|
79
|
+
|
|
80
|
+
**Create a palette-optimized PNG for web delivery**
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { quantize } from '@squoosh-kit/imagequant';
|
|
84
|
+
import { encode } from '@squoosh-kit/png';
|
|
85
|
+
|
|
86
|
+
// Quantize to 256 colors
|
|
87
|
+
const quantized = await quantize(iconImage, { numColors: 256, dither: 1.0 });
|
|
88
|
+
|
|
89
|
+
// Encode the quantized data to PNG
|
|
90
|
+
const png = await encode(quantized);
|
|
91
|
+
|
|
92
|
+
// The resulting PNG will be much smaller than encoding full-color directly
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Batch optimize icons with limited palette**
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
const quantizer = createImagequantQuantizer('worker');
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const optimized = await Promise.all(
|
|
102
|
+
icons.map((icon) => quantizer(icon, { numColors: 32, dither: 0.8 }))
|
|
103
|
+
);
|
|
104
|
+
// Encode and save each...
|
|
105
|
+
} finally {
|
|
106
|
+
await quantizer.terminate();
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## API Reference
|
|
111
|
+
|
|
112
|
+
### `quantize(image, options?, signal?)`
|
|
113
|
+
|
|
114
|
+
Reduces an image to a limited color palette using ImageQuant's lossy quantization algorithm.
|
|
115
|
+
|
|
116
|
+
- `image` - `ImageInput` object with your pixel data
|
|
117
|
+
- `options` - (optional) `ImagequantOptions` for quality and palette settings
|
|
118
|
+
- `signal` - (optional) `AbortSignal` to cancel the operation
|
|
119
|
+
- **Returns** - `Promise<{ data: Uint8ClampedArray; width: number; height: number }>` with the quantized pixel data
|
|
120
|
+
|
|
121
|
+
**Note**: `quantize()` uses a global singleton worker. For long-running applications where worker cleanup is important, use `createImagequantQuantizer()` instead.
|
|
122
|
+
|
|
123
|
+
### `createImagequantQuantizer(mode?)`
|
|
124
|
+
|
|
125
|
+
Creates a reusable quantizer. More efficient for processing multiple images.
|
|
126
|
+
|
|
127
|
+
- `mode` - (optional) `'worker'` or `'client'`, defaults to `'worker'`
|
|
128
|
+
- **Returns** - A function with the same signature as `quantize()`
|
|
129
|
+
|
|
130
|
+
## Cancellation Support
|
|
131
|
+
|
|
132
|
+
To cancel a quantization in progress, pass an `AbortSignal`:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
const controller = new AbortController();
|
|
136
|
+
|
|
137
|
+
const quantizePromise = quantize(
|
|
138
|
+
imageData,
|
|
139
|
+
{ numColors: 256 },
|
|
140
|
+
controller.signal
|
|
141
|
+
);
|
|
142
|
+
setTimeout(() => controller.abort(), 10000);
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
const result = await quantizePromise;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (error.name === 'AbortError') {
|
|
148
|
+
console.log('Quantization was cancelled');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Input Validation
|
|
154
|
+
|
|
155
|
+
All inputs are automatically validated before processing:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// Will throw TypeError: image must be an object
|
|
159
|
+
await quantize(null);
|
|
160
|
+
|
|
161
|
+
// Will throw TypeError: image.data must be Uint8Array or Uint8ClampedArray
|
|
162
|
+
await quantize({ data: [0, 0, 0, 255], width: 32, height: 32 });
|
|
163
|
+
|
|
164
|
+
// Will throw RangeError: image.data too small
|
|
165
|
+
await quantize({ data: new Uint8Array(100), width: 800, height: 600 });
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Package Size
|
|
169
|
+
|
|
170
|
+
**Size breakdown:**
|
|
171
|
+
|
|
172
|
+
- JavaScript code: ~4-6KB gzipped
|
|
173
|
+
- TypeScript definitions: ~2KB
|
|
174
|
+
- WASM binary: ~15-25KB gzipped
|
|
175
|
+
|
|
176
|
+
### Worker Cleanup
|
|
177
|
+
|
|
178
|
+
When using worker mode, clean up when done:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
const quantizer = createImagequantQuantizer('worker');
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const quantized = await quantizer(imageData, { numColors: 256 });
|
|
185
|
+
} finally {
|
|
186
|
+
await quantizer.terminate();
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### `ImagequantOptions`
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
type ImagequantOptions = {
|
|
194
|
+
numColors?: number; // 2–256, palette size (default: 256)
|
|
195
|
+
dither?: number; // 0–1, dithering strength (default: 1.0)
|
|
196
|
+
zx?: boolean; // Use auto color count (default: false)
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
- `numColors` — How many colors to include in the palette. Fewer colors = smaller file, lower quality.
|
|
201
|
+
- `256` — Maximum palette (best quality)
|
|
202
|
+
- `64-128` — Good tradeoff for illustrations
|
|
203
|
+
- `2-32` — Very small palettes; noticeable quality loss on complex images
|
|
204
|
+
- `dither` — Controls Floyd-Steinberg dithering, which approximates missing colors with patterns.
|
|
205
|
+
- `1.0` — Maximum dithering (best visual quality)
|
|
206
|
+
- `0.0` — No dithering (banding visible on gradients)
|
|
207
|
+
- `zx` — When `true`, ImageQuant automatically determines the optimal color count instead of using `numColors`.
|
|
208
|
+
|
|
209
|
+
## Performance Tips
|
|
210
|
+
|
|
211
|
+
- **Use workers for UI apps** - Keeps your interface responsive
|
|
212
|
+
- **Use client mode for servers** - Avoids worker overhead for batch processing
|
|
213
|
+
- **More colors = better quality** - Start with 256 and reduce if file size is still too large
|
|
214
|
+
- **Dithering improves perceived quality** - Leave at `1.0` unless you specifically need hard edges
|
|
215
|
+
- **Pair with OxiPNG** - After quantizing, run through `@squoosh-kit/oxipng` for additional compression
|
|
216
|
+
|
|
217
|
+
## Works With
|
|
218
|
+
|
|
219
|
+
- **Bun** - First-class support, fastest performance
|
|
220
|
+
- **Node.js** - Works great in server environments
|
|
221
|
+
- **Browsers** - Full Web Worker support for responsive UIs
|
|
222
|
+
- **TypeScript** - Complete type definitions included
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT - use it freely in your projects
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squoosh-kit/imagequant",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "ImageQuant palette quantizer for squoosh-kit, providing lossy PNG compression via palette quantization.",
|
|
6
6
|
"author": "Bartosz Nowak <bnowak008@gmail.com>",
|