@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.
Files changed (2) hide show
  1. package/README.md +226 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,226 @@
1
+ # @squoosh-kit/imagequant
2
+
3
+ [![npm version](https://badge.fury.io/js/%40squoosh-kit%2Fimagequant.svg)](https://badge.fury.io/js/%40squoosh-kit%2Fimagequant)
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/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.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>",