format-png 0.2.0 → 0.3.0
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/CHANGELOG.md +93 -0
- package/README.md +121 -6
- package/dist/async.d.ts +28 -0
- package/dist/async.js +48 -0
- package/dist/core.d.ts +393 -0
- package/dist/core.js +405 -0
- package/dist/index.d.ts +5 -371
- package/dist/index.js +3 -370
- package/dist/pool.d.ts +82 -0
- package/dist/pool.js +407 -0
- package/dist/port-node.d.ts +3 -0
- package/dist/port-node.js +9 -0
- package/dist/port-web.d.ts +3 -0
- package/dist/port-web.js +7 -0
- package/dist/protocol.d.ts +40 -0
- package/dist/protocol.js +36 -0
- package/dist/spawn-node.d.ts +3 -0
- package/dist/spawn-node.js +9 -0
- package/dist/spawn-web.d.ts +2 -0
- package/dist/spawn-web.js +9 -0
- package/dist/wasm/format_png_wasm.d.ts +127 -68
- package/dist/wasm/format_png_wasm.js +947 -366
- package/dist/wasm/format_png_wasm_bg.wasm.base64.js +1 -1
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +137 -0
- package/package.json +24 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
Worker pools now encode one large image on all their workers, built on the
|
|
6
|
+
format-png crate's new segment API.
|
|
7
|
+
|
|
8
|
+
### Faster
|
|
9
|
+
|
|
10
|
+
- A pool, and the async functions, compress a large image's data in 1 MiB
|
|
11
|
+
segments across all the workers. A 2500x3800 photo-like image at level 6,
|
|
12
|
+
in Node on a 20-core machine: 7.8 s on one worker, 4.3 s on two, 2.7 s on
|
|
13
|
+
four, 2.0 s on eight (3.8x). Images with 1 MiB of filtered data or less are
|
|
14
|
+
encoded whole, as before.
|
|
15
|
+
- Jobs take turns: while a large image is split, other jobs still start as
|
|
16
|
+
soon as a worker is free, in the order they were submitted.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- A pool's `encode` and `encodeRgba8`, and `encodeAsync` and
|
|
21
|
+
`encodeRgba8Async`, default to `threads: "auto"`. For large images the file
|
|
22
|
+
is a little larger (about 0.1% for that photo) and its bytes differ from the
|
|
23
|
+
sync `encode`'s. Pass `threads: "single"` for the sync function's bytes.
|
|
24
|
+
- Cancelling a running job no longer stops its worker if that worker holds
|
|
25
|
+
an image another job is splitting: the task finishes, and its result is
|
|
26
|
+
dropped. The job still rejects at once.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- `threads` encode option: "single" (the default for the sync API) or
|
|
31
|
+
"auto", as the crate's `Threads`. In WebAssembly, "auto" isn't faster on its
|
|
32
|
+
own; it gives the same bytes as a pool.
|
|
33
|
+
|
|
34
|
+
### Other
|
|
35
|
+
|
|
36
|
+
- Built against the format-png crate 0.2.0 (from 0.1.1).
|
|
37
|
+
- `npm run bench:pool` times a pool splitting one image, at several sizes.
|
|
38
|
+
|
|
39
|
+
## 0.3.0
|
|
40
|
+
|
|
41
|
+
An async API that runs format-png in Web Workers, or worker_threads in Node,
|
|
42
|
+
so large images don't block the main thread. The sync API is unchanged.
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- Async versions of the functions: `decodeAsync`, `decodeRgba8Async`,
|
|
47
|
+
`encodeAsync`, `encodeRgba8Async`, `readChunksAsync`, `readHeaderAsync` and
|
|
48
|
+
`parseTextAsync`. They need no setup: they share one worker pool, created on
|
|
49
|
+
first use. `terminateDefaultWorkerPool()` frees it, and
|
|
50
|
+
`defaultWorkerPool()` returns it.
|
|
51
|
+
- `createWorkerPool(options?)` returns a pool with async versions of `decode`,
|
|
52
|
+
`decodeRgba8`, `encode`, `encodeRgba8`, `readChunks`, `readHeader` and
|
|
53
|
+
`parseText`. They take the same arguments and options, resolve to the same
|
|
54
|
+
results, and reject with the same `PngError`.
|
|
55
|
+
- Pools need no `init()`: each worker loads the embedded module. By default a
|
|
56
|
+
pool has one worker per CPU core, at most 8.
|
|
57
|
+
- Workers start as jobs need them and stay alive until `terminate()`, each
|
|
58
|
+
reusing its decoders and encoders. Jobs queue when every worker is busy and
|
|
59
|
+
start in the order they were submitted.
|
|
60
|
+
- Inputs are copied to the worker by default. With `transfer: true` they're
|
|
61
|
+
moved instead, which detaches the caller's buffer. Results always come back
|
|
62
|
+
without a copy.
|
|
63
|
+
- Pass `signal` to cancel a queued or running job.
|
|
64
|
+
- `WorkerPoolError` with `code` "terminated" (rejected by `terminate()`, and
|
|
65
|
+
by calls after it) or "worker-crashed" (the pool replaces the worker).
|
|
66
|
+
- `createWorker` option, for bundlers that don't bundle
|
|
67
|
+
`new Worker(new URL(..., import.meta.url))`, such as esbuild and Rollup.
|
|
68
|
+
Vite and webpack 5 need no setup.
|
|
69
|
+
|
|
70
|
+
### Faster
|
|
71
|
+
|
|
72
|
+
The WebAssembly module is now optimized for speed rather than size
|
|
73
|
+
(`opt-level = 3`). Outputs are byte for byte the same. Measured with
|
|
74
|
+
`npm run bench` in Node 22, on 2500x3800 RGBA images:
|
|
75
|
+
|
|
76
|
+
| | Photo-like | Smooth |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `decodeRgba8` | 304 → 195 ms (36% faster) | 137 → 72 ms (48% faster) |
|
|
79
|
+
| Encode, level 6 | 7.3 → 7.1 s (3% faster) | 1.01 → 0.86 s (15% faster) |
|
|
80
|
+
| Encode, level 9 | 16.5 → 16.0 s (3% faster) | 15.6 → 14.9 s (5% faster) |
|
|
81
|
+
| Encode, filter "none" | 1.50 → 1.43 s (5% faster) | unchanged |
|
|
82
|
+
|
|
83
|
+
The module is 261 kB, up from 229 kB, and the package is about 170 kB packed.
|
|
84
|
+
|
|
85
|
+
### Other
|
|
86
|
+
|
|
87
|
+
- A `PngError` now has the underlying WebAssembly error as its `cause`.
|
|
88
|
+
- No new runtime dependencies, and no `SharedArrayBuffer` or WebAssembly
|
|
89
|
+
threads, so no COOP/COEP headers are needed.
|
|
90
|
+
|
|
3
91
|
## 0.2.0
|
|
4
92
|
|
|
5
93
|
The WebAssembly module is now embedded in the package, and `init()` with no
|
|
@@ -21,6 +109,11 @@ fetched: the package makes no network requests.
|
|
|
21
109
|
`optimizeDeps: { exclude: ["format-png"] }` is no longer needed.
|
|
22
110
|
- If you passed a URL to `init`, call `init()` instead.
|
|
23
111
|
|
|
112
|
+
### Other
|
|
113
|
+
|
|
114
|
+
- The WebAssembly module is a third smaller (229 kB, down from 335 kB): it no
|
|
115
|
+
longer carries symbol names and debug info. Speed is unchanged.
|
|
116
|
+
|
|
24
117
|
## 0.1.2
|
|
25
118
|
|
|
26
119
|
- Built against the `format-png` crate 0.1.1. The API and behavior are unchanged.
|
package/README.md
CHANGED
|
@@ -11,7 +11,8 @@ A PNG decoder and encoder for the browser and Node, compiled from Rust to WebAss
|
|
|
11
11
|
- **Reads every chunk** without decompressing the image: header, palette, transparency, `gAMA`, `cHRM`, `sRGB`, `iCCP`, `cICP`, `pHYs`, `tIME`, `eXIf`, `tEXt`, `zTXt`, `iTXt`, plus private and unknown chunks raw.
|
|
12
12
|
- **Writes metadata** back: color space, ICC profiles, Exif, text and your own chunks.
|
|
13
13
|
- **Makes files smaller:** converts images with up to 256 colors to a palette, and strips the chunks you don't need, without changing a pixel.
|
|
14
|
-
- **
|
|
14
|
+
- **Runs off the main thread** with a built-in worker pool, so large images don't freeze the page.
|
|
15
|
+
- **No dependencies.** About 170 kB packed, mostly the WebAssembly module. Ships with TypeScript types.
|
|
15
16
|
|
|
16
17
|
## Install
|
|
17
18
|
|
|
@@ -52,7 +53,7 @@ canvas.getContext("2d").putImageData(toImageData(image), 0, 0);
|
|
|
52
53
|
import { encodeRgba8 } from "format-png";
|
|
53
54
|
|
|
54
55
|
const imageData = context.getImageData(0, 0, width, height);
|
|
55
|
-
const png = encodeRgba8(imageData, { compression:
|
|
56
|
+
const png = encodeRgba8(imageData, { compression: 6 }); // 6 is the default
|
|
56
57
|
|
|
57
58
|
const blob = new Blob([png], { type: "image/png" });
|
|
58
59
|
```
|
|
@@ -95,7 +96,7 @@ import { decode, encode } from "format-png";
|
|
|
95
96
|
const image = decode(bytes, { preserveMetadata: true, preserveChunks: true });
|
|
96
97
|
const smaller = encode(
|
|
97
98
|
{ ...image, header: { ...image.header, interlaced: false } },
|
|
98
|
-
{
|
|
99
|
+
{ palette: "auto", strip: "safe" },
|
|
99
100
|
);
|
|
100
101
|
```
|
|
101
102
|
|
|
@@ -137,12 +138,120 @@ const png = encodeRgba8({
|
|
|
137
138
|
```js
|
|
138
139
|
import { PngEncoder } from "format-png";
|
|
139
140
|
|
|
140
|
-
const encoder = new PngEncoder({
|
|
141
|
+
const encoder = new PngEncoder({ palette: "auto" });
|
|
141
142
|
const pngs = frames.map((frame) => encoder.encodeRgba8(frame));
|
|
142
143
|
encoder.free();
|
|
143
144
|
```
|
|
144
145
|
|
|
145
|
-
Each instance runs on the thread that created it. To encode in parallel, use
|
|
146
|
+
Each instance runs on the thread that created it. To decode or encode in parallel, use the async functions or a worker pool.
|
|
147
|
+
|
|
148
|
+
## Off the main thread
|
|
149
|
+
|
|
150
|
+
WebAssembly runs on the thread that calls it, so decoding or encoding a large PNG with the functions above blocks the page until it's done. Each function has an async version that runs it in a Web Worker instead (worker_threads in Node):
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
import { decodeRgba8Async, encodeRgba8Async } from "format-png";
|
|
154
|
+
|
|
155
|
+
decodeRgba8Async(bytes).then((image) => {
|
|
156
|
+
// the same RgbaImage as decodeRgba8(bytes)
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const png = await encodeRgba8Async(imageData, { palette: "auto" });
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`decodeAsync`, `decodeRgba8Async`, `encodeAsync`, `encodeRgba8Async`, `readChunksAsync`, `readHeaderAsync` and `parseTextAsync` take the same arguments and options as the functions they're named after, resolve to the same results, and reject with the same `PngError`.
|
|
163
|
+
|
|
164
|
+
You don't need to call `init()` or set anything up. The functions share one worker pool, created on first use with the default size. Its workers start only as jobs need them, so one call starts one worker. To free the workers and their memory, call `terminateDefaultWorkerPool()`; the next call starts a new pool. `defaultWorkerPool()` returns that pool.
|
|
165
|
+
|
|
166
|
+
### Worker pools
|
|
167
|
+
|
|
168
|
+
For control over the workers, such as their number, or a pool per part of your app that you terminate separately, create a pool:
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
import { createWorkerPool } from "format-png";
|
|
172
|
+
|
|
173
|
+
const pool = createWorkerPool(); // or { size: 4 }
|
|
174
|
+
|
|
175
|
+
const image = await pool.decodeRgba8(bytes);
|
|
176
|
+
const png = await pool.encodeRgba8(image, { palette: "auto" });
|
|
177
|
+
const pngs = await Promise.all(frames.map((frame) => pool.encodeRgba8(frame)));
|
|
178
|
+
|
|
179
|
+
await pool.terminate();
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
- **The same API, async.** A pool's `decode`, `decodeRgba8`, `encode`, `encodeRgba8`, `readChunks`, `readHeader` and `parseText` methods work like the async functions.
|
|
183
|
+
- **No `init()` needed.** Each worker loads the embedded WebAssembly module itself.
|
|
184
|
+
- **Size.** By default, one worker per CPU core (`navigator.hardwareConcurrency`, or `os.availableParallelism()` in Node), at most 8.
|
|
185
|
+
- **Lazy workers.** Creating a pool starts nothing. Workers start as jobs need them, up to `size`, and then stay alive between jobs, each keeping its own decoders and encoders, so a batch keeps their buffer reuse.
|
|
186
|
+
- **A queue.** When every worker is busy, jobs wait and start in the order they were submitted. A large image split across the workers takes turns with the jobs after it, so it doesn't hold them up.
|
|
187
|
+
- **Node.** An idle pool doesn't keep the process alive, but call `terminate()` to free the workers' memory.
|
|
188
|
+
|
|
189
|
+
### One large image, across all the workers
|
|
190
|
+
|
|
191
|
+
Encoding a large image is mostly compression. A pool spreads one image's compression across its workers: one worker filters the image and splits the result into 1 MiB segments, all the workers compress segments, and the first worker joins them into the PNG. Images with more than 1 MiB of filtered data are split, which is about 512×512 RGBA and up; smaller ones are encoded whole on one worker.
|
|
192
|
+
|
|
193
|
+
On a 2500×3800 photo-like image at the default level, in Node on a 20-core machine:
|
|
194
|
+
|
|
195
|
+
| Workers | Time | Speedup |
|
|
196
|
+
|---|---|---|
|
|
197
|
+
| 1 | 7.8 s | 1.0× |
|
|
198
|
+
| 2 | 4.3 s | 1.8× |
|
|
199
|
+
| 4 | 2.7 s | 2.8× |
|
|
200
|
+
| 8 | 2.0 s | 3.8× |
|
|
201
|
+
|
|
202
|
+
Filtering and joining run on one worker, so the speedup levels off. Run `npm run bench:pool` in the repository to measure your machine.
|
|
203
|
+
|
|
204
|
+
The segments are compressed independently, so the file is a little larger than one compressed as a single stream, about 0.1% for that photo. A split image's bytes are the same as `encode(image, { threads: "auto" })` gives on any thread, with any number of workers. For the smallest file, pass `threads: "single"`: the pool then encodes on one worker, with the same bytes as the sync `encode`.
|
|
205
|
+
|
|
206
|
+
### When to use which
|
|
207
|
+
|
|
208
|
+
Use the async functions or a pool for large images, for batches that can run in parallel, and whenever the page has to stay responsive. Use the sync functions for small images such as icons: posting the bytes to a worker and back costs more than decoding them, and the sync call returns in well under a frame.
|
|
209
|
+
|
|
210
|
+
WebAssembly memory never shrinks, so each worker keeps as much as the largest image it handled until the pool is terminated. For very large images, use a smaller pool, or a short-lived one, or call `terminateDefaultWorkerPool()` when you're done.
|
|
211
|
+
|
|
212
|
+
### Copying and transferring buffers
|
|
213
|
+
|
|
214
|
+
By default the input bytes (or `image.data` for `encode` and `encodeRgba8`) are **copied** to the worker, so you can keep using them. Results always come back without a copy.
|
|
215
|
+
|
|
216
|
+
With `transfer: true`, the input's `ArrayBuffer` is **moved** to the worker instead, which saves the copy:
|
|
217
|
+
|
|
218
|
+
```js
|
|
219
|
+
const image = await decodeRgba8Async(bytes, { transfer: true });
|
|
220
|
+
bytes.byteLength; // 0: the buffer is detached as soon as decodeRgba8 is called
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
> [!WARNING]
|
|
224
|
+
> Transferring detaches the **whole** `ArrayBuffer`, including every other view of it, as soon as the method is called. It can't be a `SharedArrayBuffer`. In Node, don't transfer a small `Buffer` made by `Buffer.from` or `Buffer.allocUnsafe`: it may share Node's internal buffer pool.
|
|
225
|
+
|
|
226
|
+
`readChunks` returns each chunk's `data` as a view into its input, just as the sync function does: into your `bytes` by default, or into the buffer moved back from the worker with `transfer: true`.
|
|
227
|
+
|
|
228
|
+
### Cancelling and errors
|
|
229
|
+
|
|
230
|
+
Pass a `signal` to cancel a job. It rejects with `signal.reason` at once. A queued job leaves the queue. WebAssembly can't be interrupted, so a running job's worker is stopped and replaced, unless it holds an image another job is splitting: then the task finishes first, and its result is dropped.
|
|
231
|
+
|
|
232
|
+
```js
|
|
233
|
+
const controller = new AbortController();
|
|
234
|
+
const job = encodeRgba8Async(image, { signal: controller.signal });
|
|
235
|
+
controller.abort(); // job rejects with an AbortError
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Failures that come from the pool rather than the PNG reject with a `WorkerPoolError`:
|
|
239
|
+
- `code: "terminated"`: the pool was terminated. This applies to queued and running jobs, and to every call after `terminate()`.
|
|
240
|
+
- `code: "worker-crashed"`: the worker stopped unexpectedly. The pool starts a new one for the next job.
|
|
241
|
+
|
|
242
|
+
### Bundlers
|
|
243
|
+
|
|
244
|
+
Pools start their workers with `new Worker(new URL("./worker.js", import.meta.url), { type: "module" })`.
|
|
245
|
+
- **Vite and webpack 5** find and bundle that worker with no setup. With Vite, set `worker: { format: "es" }`.
|
|
246
|
+
- **esbuild and Rollup** need it built as a second entry, `format-png/worker.js` (the file `node_modules/format-png/dist/worker.js`), given to the pool with `createWorker`:
|
|
247
|
+
|
|
248
|
+
```js
|
|
249
|
+
const pool = createWorkerPool({
|
|
250
|
+
createWorker: () => new Worker(new URL("./worker.js", import.meta.url), { type: "module" }),
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
`createWorker` also lets you start workers your own way. In Node it may return a `worker_threads` `Worker`.
|
|
146
255
|
|
|
147
256
|
## API
|
|
148
257
|
|
|
@@ -159,6 +268,9 @@ Each instance runs on the thread that created it. To encode in parallel, use one
|
|
|
159
268
|
| `toImageData(image)` | Wraps decoded RGBA for `putImageData`. Browser only. |
|
|
160
269
|
| `pixelsPerInch(dimensions)` | Converts `pHYs` to pixels per inch. |
|
|
161
270
|
| `PngDecoder`, `PngEncoder` | Reusable decoder and encoder. |
|
|
271
|
+
| `decodeAsync`, `decodeRgba8Async`, `encodeAsync`, `encodeRgba8Async`, `readChunksAsync`, `readHeaderAsync`, `parseTextAsync` | The functions above, in a Web Worker or worker_thread, returning promises. |
|
|
272
|
+
| `createWorkerPool(options?)` | A pool of workers with the same async methods, for control over the workers. |
|
|
273
|
+
| `defaultWorkerPool()`, `terminateDefaultWorkerPool()` | The pool behind the async functions, and a way to free it. |
|
|
162
274
|
|
|
163
275
|
**Decode options:**
|
|
164
276
|
- `validateCrc` (default `true`): check each chunk's checksum.
|
|
@@ -176,6 +288,9 @@ Each instance runs on the thread that created it. To encode in parallel, use one
|
|
|
176
288
|
| `palette` | `"keep"`, `"auto"` | `"keep"` |
|
|
177
289
|
| `strip` | `"keep"`, `"safe"`, `"all"` | `"keep"` |
|
|
178
290
|
| `keepUnsafeChunks` | Also write raw chunks whose data depends on the pixels, such as `bKGD` and `sBIT`. Only when the pixels are unchanged. | `false` |
|
|
291
|
+
| `threads` | `"single"`: compress the image data as one stream. `"auto"`: in independent 1 MiB segments, which a worker pool compresses in parallel; the file is a little larger. | `"single"`; `"auto"` in worker pools and the async functions |
|
|
292
|
+
|
|
293
|
+
On photos, levels 7 to 9 are much slower than the default for very little gain (level 9 takes about twice as long for a file about 1% smaller), and levels 4 and 5 are several times faster for files 4 to 7% larger, which suits large photos. Smooth images and graphics gain more from higher levels, but take longer still: level 9 can be over 10 times slower.
|
|
179
294
|
|
|
180
295
|
Every type is exported, and documented in the bundled `.d.ts` file.
|
|
181
296
|
|
|
@@ -195,7 +310,7 @@ try {
|
|
|
195
310
|
|
|
196
311
|
## Browser support
|
|
197
312
|
|
|
198
|
-
The package is ES2022 with WebAssembly: Chrome and Edge 85, Firefox 90, Safari 14.1 and later.
|
|
313
|
+
The package is ES2022 with WebAssembly: Chrome and Edge 85, Firefox 90, Safari 14.1 and later. Worker pools use module workers: Firefox 114 and Safari 15 or later, and Safari 15.4 for `transfer: true`. A pool can also be created inside a Web Worker.
|
|
199
314
|
|
|
200
315
|
## License
|
|
201
316
|
|
package/dist/async.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { DecodeOptions, EncodeOptions, PngChunks, PngHeader, PngImage, PngText, RawImage, ReadChunksOptions, RgbaImage, RgbaImageInput } from "./core.js";
|
|
2
|
+
import { type JobOptions, type WorkerPool } from "./pool.js";
|
|
3
|
+
/**
|
|
4
|
+
* The pool behind the async functions, created on first use with the default
|
|
5
|
+
* size. Its workers start as jobs need them, and in Node an idle pool doesn't
|
|
6
|
+
* keep the process alive.
|
|
7
|
+
*/
|
|
8
|
+
export declare function defaultWorkerPool(): WorkerPool;
|
|
9
|
+
/**
|
|
10
|
+
* Terminates the shared pool, freeing its workers and their memory. Its
|
|
11
|
+
* pending jobs reject with a `WorkerPoolError`; the next async call starts a
|
|
12
|
+
* new pool.
|
|
13
|
+
*/
|
|
14
|
+
export declare function terminateDefaultWorkerPool(): Promise<void>;
|
|
15
|
+
/** `decode`, in a worker. */
|
|
16
|
+
export declare function decodeAsync(bytes: Uint8Array, options?: DecodeOptions & JobOptions): Promise<RawImage>;
|
|
17
|
+
/** `decodeRgba8`, in a worker. */
|
|
18
|
+
export declare function decodeRgba8Async(bytes: Uint8Array, options?: DecodeOptions & JobOptions): Promise<RgbaImage>;
|
|
19
|
+
/** `readChunks`, in a worker. */
|
|
20
|
+
export declare function readChunksAsync(bytes: Uint8Array, options?: ReadChunksOptions & JobOptions): Promise<PngChunks>;
|
|
21
|
+
/** `readHeader`, in a worker. */
|
|
22
|
+
export declare function readHeaderAsync(bytes: Uint8Array, options?: JobOptions): Promise<PngHeader>;
|
|
23
|
+
/** `parseText`, in a worker. */
|
|
24
|
+
export declare function parseTextAsync(type: PngText["chunkType"], data: Uint8Array, options?: JobOptions): Promise<PngText>;
|
|
25
|
+
/** `encode`, in a worker. */
|
|
26
|
+
export declare function encodeAsync(image: PngImage, options?: EncodeOptions & JobOptions): Promise<Uint8Array>;
|
|
27
|
+
/** `encodeRgba8`, in a worker. */
|
|
28
|
+
export declare function encodeRgba8Async(image: RgbaImageInput, options?: EncodeOptions & JobOptions): Promise<Uint8Array>;
|
package/dist/async.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { createWorkerPool } from "./pool.js";
|
|
2
|
+
let shared;
|
|
3
|
+
/**
|
|
4
|
+
* The pool behind the async functions, created on first use with the default
|
|
5
|
+
* size. Its workers start as jobs need them, and in Node an idle pool doesn't
|
|
6
|
+
* keep the process alive.
|
|
7
|
+
*/
|
|
8
|
+
export function defaultWorkerPool() {
|
|
9
|
+
return (shared ??= createWorkerPool());
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Terminates the shared pool, freeing its workers and their memory. Its
|
|
13
|
+
* pending jobs reject with a `WorkerPoolError`; the next async call starts a
|
|
14
|
+
* new pool.
|
|
15
|
+
*/
|
|
16
|
+
export async function terminateDefaultWorkerPool() {
|
|
17
|
+
const pool = shared;
|
|
18
|
+
shared = undefined;
|
|
19
|
+
await pool?.terminate();
|
|
20
|
+
}
|
|
21
|
+
/** `decode`, in a worker. */
|
|
22
|
+
export function decodeAsync(bytes, options) {
|
|
23
|
+
return defaultWorkerPool().decode(bytes, options);
|
|
24
|
+
}
|
|
25
|
+
/** `decodeRgba8`, in a worker. */
|
|
26
|
+
export function decodeRgba8Async(bytes, options) {
|
|
27
|
+
return defaultWorkerPool().decodeRgba8(bytes, options);
|
|
28
|
+
}
|
|
29
|
+
/** `readChunks`, in a worker. */
|
|
30
|
+
export function readChunksAsync(bytes, options) {
|
|
31
|
+
return defaultWorkerPool().readChunks(bytes, options);
|
|
32
|
+
}
|
|
33
|
+
/** `readHeader`, in a worker. */
|
|
34
|
+
export function readHeaderAsync(bytes, options) {
|
|
35
|
+
return defaultWorkerPool().readHeader(bytes, options);
|
|
36
|
+
}
|
|
37
|
+
/** `parseText`, in a worker. */
|
|
38
|
+
export function parseTextAsync(type, data, options) {
|
|
39
|
+
return defaultWorkerPool().parseText(type, data, options);
|
|
40
|
+
}
|
|
41
|
+
/** `encode`, in a worker. */
|
|
42
|
+
export function encodeAsync(image, options) {
|
|
43
|
+
return defaultWorkerPool().encode(image, options);
|
|
44
|
+
}
|
|
45
|
+
/** `encodeRgba8`, in a worker. */
|
|
46
|
+
export function encodeRgba8Async(image, options) {
|
|
47
|
+
return defaultWorkerPool().encodeRgba8(image, options);
|
|
48
|
+
}
|