@squoosh-kit/png 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.
- package/README.md +222 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# @squoosh-kit/png
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/%40squoosh-kit%2Fpng)
|
|
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/png`) is one of those modules.
|
|
13
|
+
|
|
14
|
+
**Directly from the Source**
|
|
15
|
+
We don't modify the core PNG 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/png` allows you to add lossless PNG 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/png
|
|
27
|
+
# or
|
|
28
|
+
npm install @squoosh-kit/png
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { encode, decode, createPngEncoder } from '@squoosh-kit/png';
|
|
35
|
+
import type { ImageInput } from '@squoosh-kit/png';
|
|
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 PNG (lossless, no options needed)
|
|
45
|
+
const pngBuffer = await encode(imageData);
|
|
46
|
+
|
|
47
|
+
// Decode a PNG back to raw pixel data
|
|
48
|
+
const rawImage = await decode(existingPng);
|
|
49
|
+
|
|
50
|
+
// For multiple images, create a persistent encoder
|
|
51
|
+
const encoder = createPngEncoder('worker');
|
|
52
|
+
const png = await encoder(imageData);
|
|
53
|
+
await encoder.terminate();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Public API
|
|
57
|
+
|
|
58
|
+
Only the following exports are part of the public API and guaranteed to be stable across versions:
|
|
59
|
+
|
|
60
|
+
- `encode(imageData, signal?)` - Encode raw pixel data to PNG format
|
|
61
|
+
- `decode(data, signal?)` - Decode a PNG file to raw pixel data
|
|
62
|
+
- `createPngEncoder(mode?)` - Create a reusable encoder function
|
|
63
|
+
- `createPngDecoder(mode?)` - Create a reusable decoder function
|
|
64
|
+
- `ImageInput` type - Input image data structure
|
|
65
|
+
- `PngEncoderFactory` type - Type for reusable encoder functions
|
|
66
|
+
- `PngDecoderFactory` type - Type for reusable decoder functions
|
|
67
|
+
|
|
68
|
+
## Real-World Examples
|
|
69
|
+
|
|
70
|
+
**Save canvas content as PNG**
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// From a browser canvas
|
|
74
|
+
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
|
|
75
|
+
const ctx = canvas.getContext('2d')!;
|
|
76
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
77
|
+
|
|
78
|
+
const pngBuffer = await encode({
|
|
79
|
+
data: imageData.data,
|
|
80
|
+
width: canvas.width,
|
|
81
|
+
height: canvas.height,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Download in the browser
|
|
85
|
+
const blob = new Blob([pngBuffer], { type: 'image/png' });
|
|
86
|
+
const url = URL.createObjectURL(blob);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Batch PNG processing with timeout**
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const encoder = createPngEncoder('worker');
|
|
93
|
+
const controller = new AbortController();
|
|
94
|
+
setTimeout(() => controller.abort(), 60000);
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
const results = await Promise.all(
|
|
98
|
+
images.map((img) => encoder(img, controller.signal))
|
|
99
|
+
);
|
|
100
|
+
// Save results...
|
|
101
|
+
} finally {
|
|
102
|
+
await encoder.terminate();
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## API Reference
|
|
107
|
+
|
|
108
|
+
### `encode(imageData, signal?)`
|
|
109
|
+
|
|
110
|
+
Encodes raw RGBA pixel data to PNG format. PNG is always lossless — the encoded output is a pixel-perfect representation of the input.
|
|
111
|
+
|
|
112
|
+
- `imageData` - `ImageInput` object with your pixel data
|
|
113
|
+
- `signal` - (optional) `AbortSignal` to cancel the operation
|
|
114
|
+
- **Returns** - `Promise<Uint8Array>` with the encoded PNG data
|
|
115
|
+
|
|
116
|
+
### `decode(data, signal?)`
|
|
117
|
+
|
|
118
|
+
Decodes a PNG file back to raw RGBA pixel data.
|
|
119
|
+
|
|
120
|
+
- `data` - `Uint8Array` containing the PNG file bytes
|
|
121
|
+
- `signal` - (optional) `AbortSignal` to cancel the operation
|
|
122
|
+
- **Returns** - `Promise<ImageData>` with decoded pixel data, width, and height
|
|
123
|
+
|
|
124
|
+
### `createPngEncoder(mode?)`
|
|
125
|
+
|
|
126
|
+
Creates a reusable encoder. More efficient for processing multiple images.
|
|
127
|
+
|
|
128
|
+
- `mode` - (optional) `'worker'` or `'client'`, defaults to `'worker'`
|
|
129
|
+
- **Returns** - A function with the same signature as `encode()`
|
|
130
|
+
|
|
131
|
+
### `createPngDecoder(mode?)`
|
|
132
|
+
|
|
133
|
+
Creates a reusable decoder. More efficient for processing multiple images.
|
|
134
|
+
|
|
135
|
+
- `mode` - (optional) `'worker'` or `'client'`, defaults to `'worker'`
|
|
136
|
+
- **Returns** - A function with the same signature as `decode()`
|
|
137
|
+
|
|
138
|
+
## Cancellation Support
|
|
139
|
+
|
|
140
|
+
To cancel an operation in progress, pass an `AbortSignal`:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
const controller = new AbortController();
|
|
144
|
+
|
|
145
|
+
const encodePromise = encode(imageData, controller.signal);
|
|
146
|
+
|
|
147
|
+
// Cancel after 5 seconds if still running
|
|
148
|
+
setTimeout(() => controller.abort(), 5000);
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const result = await encodePromise;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error.name === 'AbortError') {
|
|
154
|
+
console.log('Encoding was cancelled');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Important**: If no signal is provided, the operation cannot be cancelled. It will run to completion.
|
|
160
|
+
|
|
161
|
+
## Input Validation
|
|
162
|
+
|
|
163
|
+
All inputs are automatically validated before processing:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
// Will throw TypeError: image must be an object
|
|
167
|
+
await encode(null);
|
|
168
|
+
|
|
169
|
+
// Will throw TypeError: image.data must be Uint8Array or Uint8ClampedArray
|
|
170
|
+
await encode({ data: [0, 0, 0, 255], width: 32, height: 32 });
|
|
171
|
+
|
|
172
|
+
// Will throw RangeError: image.data too small
|
|
173
|
+
// (needs width * height * 4 bytes)
|
|
174
|
+
await encode({ data: new Uint8Array(100), width: 800, height: 600 });
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
All validation happens synchronously before WASM processing, so you get errors immediately.
|
|
178
|
+
|
|
179
|
+
### Package Size
|
|
180
|
+
|
|
181
|
+
This package includes a WebAssembly binary for the PNG codec (~15-20KB gzipped). PNG encoding is lossless and uses the libpng-based WASM from Squoosh.
|
|
182
|
+
|
|
183
|
+
**Size breakdown:**
|
|
184
|
+
|
|
185
|
+
- JavaScript code: ~4-6KB gzipped
|
|
186
|
+
- TypeScript definitions: ~2KB
|
|
187
|
+
- WASM binary: ~15-20KB gzipped
|
|
188
|
+
|
|
189
|
+
### Worker Cleanup
|
|
190
|
+
|
|
191
|
+
When using worker mode (`createPngEncoder('worker')`), always clean up the worker when done:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
const encoder = createPngEncoder('worker');
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const pngData = await encoder(imageData);
|
|
198
|
+
// Use the encoded data...
|
|
199
|
+
} finally {
|
|
200
|
+
await encoder.terminate();
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**Note**: In client mode (`createPngEncoder('client')`), `terminate()` is a no-op. It's always safe to call for consistency.
|
|
205
|
+
|
|
206
|
+
## Performance Tips
|
|
207
|
+
|
|
208
|
+
- **Use workers for UI apps** - Keeps your interface responsive during encoding
|
|
209
|
+
- **Use client mode for servers** - Direct encoding without worker overhead
|
|
210
|
+
- **Batch with persistent encoders** - More efficient than one-off calls
|
|
211
|
+
- **PNG is lossless** - File sizes are larger than AVIF/WebP/MozJPEG; use OxiPNG to optimize afterwards
|
|
212
|
+
|
|
213
|
+
## Works With
|
|
214
|
+
|
|
215
|
+
- **Bun** - First-class support, fastest performance
|
|
216
|
+
- **Node.js** - Works great in server environments
|
|
217
|
+
- **Browsers** - Full Web Worker support for responsive UIs
|
|
218
|
+
- **TypeScript** - Complete type definitions included
|
|
219
|
+
|
|
220
|
+
## License
|
|
221
|
+
|
|
222
|
+
MIT - use it freely in your projects
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@squoosh-kit/png",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "PNG codec for squoosh-kit, providing lossless PNG 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": "
|
|
50
|
+
"@squoosh-kit/runtime": "0.2.4"
|
|
51
51
|
}
|
|
52
52
|
}
|