@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.
Files changed (2) hide show
  1. package/README.md +222 -0
  2. package/package.json +2 -2
package/README.md ADDED
@@ -0,0 +1,222 @@
1
+ # @squoosh-kit/png
2
+
3
+ [![npm version](https://badge.fury.io/js/%40squoosh-kit%2Fpng.svg)](https://badge.fury.io/js/%40squoosh-kit%2Fpng)
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/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.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": "workspace:*"
50
+ "@squoosh-kit/runtime": "0.2.4"
51
51
  }
52
52
  }