@keeratita/heic-converter 0.4.2 → 0.5.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/README.md +298 -42
- package/dist/heic-decoder-7BA7NJOA.js +5 -0
- package/dist/heic-decoder-WNTZ4MAN.mjs +5 -0
- package/dist/heic-decoder.wasm +0 -0
- package/dist/heic-decoder.wasm.br +0 -0
- package/dist/heic-decoder.wasm.gz +0 -0
- package/dist/index.d.mts +361 -36
- package/dist/index.d.ts +361 -36
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +16 -12
- package/dist/heic-decoder-AAMWPCW2.mjs +0 -5
- package/dist/heic-decoder-L3ME46HT.js +0 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,59 @@
|
|
|
1
1
|
interface DecodedImage {
|
|
2
2
|
width: number;
|
|
3
3
|
height: number;
|
|
4
|
+
/**
|
|
5
|
+
* RGBA pixel data, interleaved, row-major, 4 bytes per pixel.
|
|
6
|
+
*
|
|
7
|
+
* The buffer is always a plain `ArrayBuffer` owned by the returned array
|
|
8
|
+
* (never a view into the WASM heap), so it stays valid after
|
|
9
|
+
* `LibheifDecoder.free()` and can be passed directly to
|
|
10
|
+
* `new ImageData(...)` / `putImageData` — including the `ImageData`
|
|
11
|
+
* overload that requires `Uint8ClampedArray<ArrayBuffer>` under TS >= 5.7.
|
|
12
|
+
*/
|
|
4
13
|
data: Uint8ClampedArray;
|
|
14
|
+
/**
|
|
15
|
+
* Raw EXIF block copied from the source file, normalized to the JPEG APP1
|
|
16
|
+
* payload form: `"Exif\0\0"` followed by the TIFF structure. Present when
|
|
17
|
+
* the file carries an Exif item — including files where libheif already
|
|
18
|
+
* applied `irot`/`imir` (the block is reported independently of
|
|
19
|
+
* {@link DecodedImage.orientation}).
|
|
20
|
+
*
|
|
21
|
+
* `convertHeic` re-injects this block into JPEG (APP1) and PNG (`eXIf`)
|
|
22
|
+
* output when `preserveExif: true`; raw-decode consumers can attach it to
|
|
23
|
+
* their own encoder output (e.g. `sharp`'s `.withMetadata({ exif })`).
|
|
24
|
+
* Owned by the returned object; never a WASM-heap view.
|
|
25
|
+
*/
|
|
26
|
+
exif?: Uint8Array;
|
|
27
|
+
/**
|
|
28
|
+
* EXIF orientation of the **stored** pixels (1–8, EXIF tag 274 semantics;
|
|
29
|
+
* 1 = upright). Absent or 1 means no rotation is pending.
|
|
30
|
+
*
|
|
31
|
+
* libheif already applies `irot`/`imir` container transforms during
|
|
32
|
+
* decode — for those files this is 1 and the pixels are upright. A value
|
|
33
|
+
* > 1 means the orientation comes only from the Exif item: `convertHeic`
|
|
34
|
+
* applies it automatically (unless `applyOrientation: false`), while raw
|
|
35
|
+
* `decode()` consumers get stored pixels and must apply it themselves.
|
|
36
|
+
* Decoders that do not report orientation may omit this field.
|
|
37
|
+
*/
|
|
38
|
+
orientation?: number;
|
|
5
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Decoder contract used by {@link ConvertOptions.decoder} /
|
|
42
|
+
* {@link ConvertManyOptions.decoder} and implemented by `LibheifDecoder`.
|
|
43
|
+
*
|
|
44
|
+
* Lifecycle rules followed by the library (implementations may rely on them):
|
|
45
|
+
* - `initialize()` is called before every `decode()`; implementations must
|
|
46
|
+
* make repeated/concurrent calls cheap (e.g. memoize the load promise).
|
|
47
|
+
* - `decode()` is awaited before the library calls `free()`; the returned
|
|
48
|
+
* `DecodedImage` must therefore not reference decoder-owned memory that
|
|
49
|
+
* `free()` releases (copy pixels out, as `LibheifDecoder` does).
|
|
50
|
+
* - `free()` is called at most once per conversion. Decoders **injected** via
|
|
51
|
+
* options are never freed by the library — the caller owns their lifetime.
|
|
52
|
+
*
|
|
53
|
+
* Concurrency: with `convertMany`, a single injected decoder is shared by
|
|
54
|
+
* all concurrent conversions, so `decode()` must be safe to call concurrently
|
|
55
|
+
* on one instance (no shared mutable state across in-flight decodes).
|
|
56
|
+
*/
|
|
6
57
|
interface IHeicDecoder {
|
|
7
58
|
/**
|
|
8
59
|
* Initializes the decoder (e.g., loading WebAssembly module).
|
|
@@ -15,12 +66,51 @@ interface IHeicDecoder {
|
|
|
15
66
|
*/
|
|
16
67
|
decode(data: Uint8Array, onProgress?: (percent: number) => void): Promise<DecodedImage>;
|
|
17
68
|
/**
|
|
18
|
-
* Cleans up allocated resources.
|
|
69
|
+
* Cleans up allocated resources. Idempotent: safe to call multiple times.
|
|
19
70
|
*/
|
|
20
71
|
free(): void;
|
|
21
72
|
}
|
|
22
|
-
type ImageFormat = 'jpeg' | 'jpg' | 'png' | 'svg' | 'webp';
|
|
73
|
+
type ImageFormat = 'jpeg' | 'jpg' | 'png' | 'svg' | 'webp' | 'avif';
|
|
74
|
+
/**
|
|
75
|
+
* Formats accepted by {@link ConvertOptions.to} (case-insensitive).
|
|
76
|
+
* `'jpg'` is an alias of `'jpeg'`. `'avif'` requires an environment whose
|
|
77
|
+
* canvas can encode AVIF (Chromium/Firefox today); elsewhere it rejects with
|
|
78
|
+
* `format_unsupported`.
|
|
79
|
+
*/
|
|
80
|
+
declare const SUPPORTED_FORMATS: readonly ImageFormat[];
|
|
81
|
+
/** Default JPEG/WebP encoding quality used when `quality` is not provided. */
|
|
82
|
+
declare const DEFAULT_QUALITY = 0.92;
|
|
23
83
|
type HeicInput = Blob | File | ArrayBuffer | Uint8Array;
|
|
84
|
+
/**
|
|
85
|
+
* How {@link convertHeic} returns the converted image.
|
|
86
|
+
* - `'blob'` — a `Blob` (the default; browser-native, works everywhere)
|
|
87
|
+
* - `'dataUrl'` — a `data:image/...;base64,…` string (previews, `<img src>`)
|
|
88
|
+
* - `'arrayBuffer'` — raw bytes (uploads, WebCodecs, Node-friendly transfer)
|
|
89
|
+
*/
|
|
90
|
+
type OutputShape = 'blob' | 'dataUrl' | 'arrayBuffer';
|
|
91
|
+
/** Resolved return type of `convertHeic`/`convertMany` for an output shape. */
|
|
92
|
+
type ConvertResult<S extends OutputShape> = S extends 'dataUrl' ? string : S extends 'arrayBuffer' ? ArrayBuffer : Blob;
|
|
93
|
+
/** Crop rectangle in **post-orientation display pixels** (top-left origin). */
|
|
94
|
+
interface CropOptions {
|
|
95
|
+
/** Left edge of the crop box. @default 0 */
|
|
96
|
+
x?: number;
|
|
97
|
+
/** Top edge of the crop box. @default 0 */
|
|
98
|
+
y?: number;
|
|
99
|
+
/** Crop width in pixels. Must be a positive integer and fit inside the image. */
|
|
100
|
+
width: number;
|
|
101
|
+
/** Crop height in pixels. Must be a positive integer and fit inside the image. */
|
|
102
|
+
height: number;
|
|
103
|
+
}
|
|
104
|
+
/** Per-item outcome when `continueOnError: true`. */
|
|
105
|
+
type ConvertItemResult<T = Blob> = {
|
|
106
|
+
index: number;
|
|
107
|
+
ok: true;
|
|
108
|
+
result: T;
|
|
109
|
+
} | {
|
|
110
|
+
index: number;
|
|
111
|
+
ok: false;
|
|
112
|
+
error: Error;
|
|
113
|
+
};
|
|
24
114
|
interface ResizeOptions {
|
|
25
115
|
/**
|
|
26
116
|
* Maximum width in pixels. The image is downscaled to fit within this
|
|
@@ -42,25 +132,70 @@ interface ResizeOptions {
|
|
|
42
132
|
}
|
|
43
133
|
interface ConvertOptions extends ResizeOptions {
|
|
44
134
|
/**
|
|
45
|
-
* Target format for the conversion.
|
|
135
|
+
* Target format for the conversion. Must be one of the values in
|
|
136
|
+
* {@link SUPPORTED_FORMATS}; an unknown value is rejected up front,
|
|
137
|
+
* before the input is decoded.
|
|
46
138
|
* @default 'jpeg'
|
|
47
139
|
*/
|
|
48
140
|
to?: ImageFormat;
|
|
49
141
|
/**
|
|
50
|
-
* Quality of the converted image
|
|
51
|
-
* Applicable for 'jpeg', 'jpg', and '
|
|
142
|
+
* Quality of the converted image, between 0.0 and 1.0 (inclusive).
|
|
143
|
+
* Applicable for 'jpeg', 'jpg', 'webp', and 'avif' formats — but validated
|
|
144
|
+
* for every format: passing an out-of-range value (e.g. `90` from a 0-100
|
|
145
|
+
* scale) throws regardless of `to`.
|
|
52
146
|
* @default 0.92
|
|
53
147
|
*/
|
|
54
148
|
quality?: number;
|
|
55
149
|
/**
|
|
56
150
|
* Optional custom decoder implementation to inject.
|
|
57
151
|
* If not provided, a default LibheifDecoder is used.
|
|
152
|
+
* The library never calls `free()` on an injected decoder.
|
|
58
153
|
*/
|
|
59
154
|
decoder?: IHeicDecoder;
|
|
60
155
|
/**
|
|
61
|
-
* Optional progress callback that receives the progress percentage
|
|
156
|
+
* Optional progress callback that receives the progress percentage during
|
|
157
|
+
* decoding. Values are normalized and clamped to the range 0 to 100; the
|
|
158
|
+
* final 100% is emitted only when the conversion succeeds. A callback that
|
|
159
|
+
* throws rejects the conversion with `progress_callback_failed`.
|
|
62
160
|
*/
|
|
63
161
|
onProgress?: (percent: number) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Rotate/flip the output so it matches the source's EXIF orientation
|
|
164
|
+
* (applied as a canvas transform during rendering; `irot`/`imir` container
|
|
165
|
+
* transforms are already applied by the decoder and never stacked on top).
|
|
166
|
+
* Set `false` to keep the exact stored-pixel geometry. A non-boolean value
|
|
167
|
+
* is rejected up front with `invalid_input`.
|
|
168
|
+
* @default true
|
|
169
|
+
*/
|
|
170
|
+
applyOrientation?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Representation of the converted image. See {@link OutputShape}.
|
|
173
|
+
* @default 'blob'
|
|
174
|
+
*/
|
|
175
|
+
output?: OutputShape;
|
|
176
|
+
/**
|
|
177
|
+
* AbortSignal that cancels the conversion. Cancellation is checked at
|
|
178
|
+
* stage boundaries (input read, decoder init, before/after decode,
|
|
179
|
+
* before encode) and aborts `convertHeicInWorker` calls immediately by
|
|
180
|
+
* terminating the worker; the synchronous WASM decode itself cannot be
|
|
181
|
+
* preempted mid-call. An aborted signal rejects with code `aborted`.
|
|
182
|
+
*/
|
|
183
|
+
signal?: AbortSignal;
|
|
184
|
+
/**
|
|
185
|
+
* Crop rectangle in post-orientation display pixels (the geometry the
|
|
186
|
+
* image will be displayed in). Applied before resize: `scale`/`maxWidth`/
|
|
187
|
+
* `maxHeight` then downscale the cropped region. Out-of-bounds crops
|
|
188
|
+
* reject with `invalid_crop`.
|
|
189
|
+
*/
|
|
190
|
+
crop?: CropOptions;
|
|
191
|
+
/**
|
|
192
|
+
* Copy the source HEIC's EXIF block into JPEG (APP1) and PNG (`eXIf`
|
|
193
|
+
* chunk) output so converted files keep camera metadata (orientation,
|
|
194
|
+
* GPS, timestamps). Note this **preserves private data** like GPS — set
|
|
195
|
+
* deliberately. Ignored for `webp`/`svg` output.
|
|
196
|
+
* @default false
|
|
197
|
+
*/
|
|
198
|
+
preserveExif?: boolean;
|
|
64
199
|
}
|
|
65
200
|
interface ConvertManyOptions extends Omit<ConvertOptions, 'onProgress'> {
|
|
66
201
|
/**
|
|
@@ -69,17 +204,36 @@ interface ConvertManyOptions extends Omit<ConvertOptions, 'onProgress'> {
|
|
|
69
204
|
*/
|
|
70
205
|
concurrency?: number;
|
|
71
206
|
/**
|
|
72
|
-
* Optional progress callback that receives the item index and
|
|
73
|
-
* progress percentage (0 to 100) during decoding.
|
|
207
|
+
* Optional progress callback that receives the item index (0-based) and
|
|
208
|
+
* its progress percentage (normalized to 0 to 100) during decoding.
|
|
74
209
|
*/
|
|
75
210
|
onProgress?: (index: number, percent: number) => void;
|
|
76
211
|
/**
|
|
77
212
|
* Optional custom decoder implementation to inject. When provided, the
|
|
78
213
|
* same instance is shared by all concurrent conversions, so it must be
|
|
79
|
-
* safe for concurrent `decode()` calls. If not
|
|
80
|
-
* default LibheifDecoder is created per item.
|
|
214
|
+
* safe for concurrent `decode()` calls (see {@link IHeicDecoder}). If not
|
|
215
|
+
* provided, a fresh default LibheifDecoder is created per item.
|
|
81
216
|
*/
|
|
82
217
|
decoder?: IHeicDecoder;
|
|
218
|
+
/**
|
|
219
|
+
* Resolve with per-item results instead of rejecting the whole batch on
|
|
220
|
+
* the first failure: the promise fulfills with `ConvertItemResult[]` in
|
|
221
|
+
* input order, each item `{ index, ok: true, result }` or
|
|
222
|
+
* `{ index, ok: false, error }`. All items always run to completion.
|
|
223
|
+
* Up-front option validation failures still reject normally (a typo is a
|
|
224
|
+
* caller bug, not an item failure).
|
|
225
|
+
* @default false
|
|
226
|
+
*/
|
|
227
|
+
continueOnError?: boolean;
|
|
228
|
+
/**
|
|
229
|
+
* Reuse one library-owned `LibheifDecoder` per concurrent runner across
|
|
230
|
+
* items instead of creating (and WASM-initializing) a fresh instance per
|
|
231
|
+
* item — amortizes the module load in large batches while preserving the
|
|
232
|
+
* exclusive-use invariant (an instance is only ever held by one runner,
|
|
233
|
+
* never decodes concurrently). Ignored when `decoder` is injected.
|
|
234
|
+
* @default false
|
|
235
|
+
*/
|
|
236
|
+
reuseDecoders?: boolean;
|
|
83
237
|
}
|
|
84
238
|
|
|
85
239
|
interface LibheifDecoderOptions {
|
|
@@ -90,9 +244,18 @@ interface LibheifDecoderOptions {
|
|
|
90
244
|
locateFile?: (path: string, prefix: string) => string;
|
|
91
245
|
/**
|
|
92
246
|
* Raw WASM binary buffer. If provided, the library will use this buffer
|
|
93
|
-
* directly instead of attempting to fetch the WASM file.
|
|
247
|
+
* directly instead of attempting to fetch the WASM file. Accepts an
|
|
248
|
+
* `ArrayBuffer` or any `ArrayBufferView` (e.g. a Node.js `Buffer` from
|
|
249
|
+
* `fs.readFileSync`).
|
|
250
|
+
*/
|
|
251
|
+
wasmBinary?: ArrayBuffer | ArrayBufferView;
|
|
252
|
+
/**
|
|
253
|
+
* Advanced: extra properties merged into the Emscripten module argument
|
|
254
|
+
* object (e.g. `instantiateWasm` for streaming compilation). Prefer
|
|
255
|
+
* `locateFile`/`wasmBinary` for the common cases; keys provided here must
|
|
256
|
+
* not collide with them.
|
|
94
257
|
*/
|
|
95
|
-
|
|
258
|
+
moduleOverrides?: Record<string, unknown>;
|
|
96
259
|
}
|
|
97
260
|
declare class LibheifDecoder implements IHeicDecoder {
|
|
98
261
|
private options?;
|
|
@@ -101,8 +264,15 @@ declare class LibheifDecoder implements IHeicDecoder {
|
|
|
101
264
|
/**
|
|
102
265
|
* Memoized module-loading promise so concurrent initialize()/decode() calls
|
|
103
266
|
* on the same instance never instantiate (or mutate) the module twice.
|
|
267
|
+
* Resolves null when a concurrent free() discarded the freshly created
|
|
268
|
+
* instance (see initGeneration).
|
|
104
269
|
*/
|
|
105
270
|
private initPromise;
|
|
271
|
+
/**
|
|
272
|
+
* Generation counter for init/free races: a load that finishes after a
|
|
273
|
+
* concurrent free() must not resurrect module/decoderInstance.
|
|
274
|
+
*/
|
|
275
|
+
private initGeneration;
|
|
106
276
|
constructor(options?: LibheifDecoderOptions);
|
|
107
277
|
/**
|
|
108
278
|
* Initializes the WebAssembly module and instantiates the HEIC decoder.
|
|
@@ -112,18 +282,23 @@ declare class LibheifDecoder implements IHeicDecoder {
|
|
|
112
282
|
/**
|
|
113
283
|
* Decodes HEIC binary data into raw RGBA pixel data.
|
|
114
284
|
* @param data The HEIC file contents as a Uint8Array.
|
|
115
|
-
* @param onProgress Optional progress callback
|
|
285
|
+
* @param onProgress Optional progress callback (receives a normalized
|
|
286
|
+
* percentage clamped to 0-100).
|
|
116
287
|
*/
|
|
117
288
|
decode(data: Uint8Array, onProgress?: (percent: number) => void): Promise<DecodedImage>;
|
|
118
289
|
/**
|
|
119
290
|
* Cleans up the WebAssembly decoder instance and resources.
|
|
120
|
-
* Idempotent: safe to call multiple times. After free(), the
|
|
121
|
-
*
|
|
291
|
+
* Idempotent: safe to call multiple times. After free(), the next
|
|
292
|
+
* initialize() — or decode() directly, which re-initializes transparently
|
|
293
|
+
* — loads a fresh module.
|
|
294
|
+
*
|
|
295
|
+
* free() is also safe to call while initialize() is in flight: a load that
|
|
296
|
+
* completes after free() discards its fresh instance instead of leaking it.
|
|
122
297
|
*/
|
|
123
298
|
free(): void;
|
|
124
299
|
}
|
|
125
300
|
|
|
126
|
-
interface WorkerConvertOptions extends ConvertOptions {
|
|
301
|
+
interface WorkerConvertOptions extends Omit<ConvertOptions, 'decoder'> {
|
|
127
302
|
/**
|
|
128
303
|
* URL of the worker script that performs the conversion. Should be a
|
|
129
304
|
* compile-time constant (e.g. `new URL('./worker.js', import.meta.url)`
|
|
@@ -132,8 +307,8 @@ interface WorkerConvertOptions extends ConvertOptions {
|
|
|
132
307
|
workerUrl: string | URL;
|
|
133
308
|
/**
|
|
134
309
|
* Maximum time in milliseconds to wait for the worker result before
|
|
135
|
-
* rejecting with a timeout
|
|
136
|
-
* disable the timeout.
|
|
310
|
+
* rejecting with a timeout (queueing for a free worker slot counts toward
|
|
311
|
+
* this). Defaults to 60000 (60s). Set to 0 to disable the timeout.
|
|
137
312
|
*/
|
|
138
313
|
timeoutMs?: number;
|
|
139
314
|
/**
|
|
@@ -143,16 +318,44 @@ interface WorkerConvertOptions extends ConvertOptions {
|
|
|
143
318
|
* @default 'classic'
|
|
144
319
|
*/
|
|
145
320
|
workerType?: 'classic' | 'module';
|
|
321
|
+
/**
|
|
322
|
+
* Upper bound on simultaneously live workers for this worker script.
|
|
323
|
+
* Calls beyond the bound queue until a slot frees, which keeps bulk
|
|
324
|
+
* conversions (`inputs.map(i => convertHeicInWorker(i, …))`) from
|
|
325
|
+
* exhausting memory or the browser's worker limit.
|
|
326
|
+
* Defaults to `navigator.hardwareConcurrency` clamped to 1–8.
|
|
327
|
+
*/
|
|
328
|
+
maxConcurrentWorkers?: number;
|
|
329
|
+
}
|
|
330
|
+
/** Progress message a worker script posts to report decode progress. */
|
|
331
|
+
interface WorkerProgressMessage {
|
|
332
|
+
type: 'progress';
|
|
333
|
+
percent: number;
|
|
334
|
+
}
|
|
335
|
+
/** Result message a worker script posts to settle a conversion. */
|
|
336
|
+
interface WorkerResultMessage {
|
|
337
|
+
type: 'result';
|
|
338
|
+
ok: boolean;
|
|
339
|
+
/**
|
|
340
|
+
* The converted image exactly as `convertHeic` returned it inside the
|
|
341
|
+
* worker: a Blob, a data-URL string (`output: 'dataUrl'`), or an
|
|
342
|
+
* ArrayBuffer (`output: 'arrayBuffer'`). The field name `blob` is kept
|
|
343
|
+
* for protocol compatibility.
|
|
344
|
+
*/
|
|
345
|
+
blob?: Blob | string | ArrayBuffer;
|
|
346
|
+
error?: string;
|
|
146
347
|
}
|
|
147
348
|
/**
|
|
148
349
|
* Converts a HEIC image inside a Web Worker so the main thread stays
|
|
149
350
|
* responsive during the (potentially slow) WASM decode.
|
|
150
351
|
*
|
|
151
352
|
* The worker script is user-provided and must handle the following message
|
|
152
|
-
* protocol
|
|
353
|
+
* protocol (types are exported as {@link WorkerProgressMessage} and
|
|
354
|
+
* {@link WorkerResultMessage}):
|
|
153
355
|
*
|
|
154
356
|
* ```js
|
|
155
|
-
* // converter.worker.js
|
|
357
|
+
* // converter.worker.js — keep in sync with docs/worker.js,
|
|
358
|
+
* // test/browser/worker.js, and this JSDoc example.
|
|
156
359
|
* import { convertHeic } from '@keeratita/heic-converter';
|
|
157
360
|
*
|
|
158
361
|
* self.onmessage = async (event) => {
|
|
@@ -178,15 +381,106 @@ interface WorkerConvertOptions extends ConvertOptions {
|
|
|
178
381
|
* ```
|
|
179
382
|
*
|
|
180
383
|
* Only `progress` and `result` messages are understood; any other message
|
|
181
|
-
* type is ignored
|
|
182
|
-
*
|
|
384
|
+
* type is ignored (the first unknown type is reported in the timeout
|
|
385
|
+
* diagnostic). Use `workerType: 'module'` when the script uses ES module
|
|
386
|
+
* imports (as in the example above); `'classic'` scripts must be
|
|
183
387
|
* pre-bundled, since static ES imports are not supported there.
|
|
184
388
|
*
|
|
389
|
+
* The `decoder` option is rejected: class instances cannot cross the
|
|
390
|
+
* worker boundary; the worker creates its own decoder.
|
|
391
|
+
*
|
|
185
392
|
* @param input HEIC image as a Blob, File, ArrayBuffer, or Uint8Array.
|
|
186
393
|
* @param options Conversion options plus the worker script URL.
|
|
187
|
-
* @returns
|
|
394
|
+
* @returns The converted image as a Blob, data URL string, or ArrayBuffer
|
|
395
|
+
* depending on `options.output` (default Blob).
|
|
188
396
|
*/
|
|
189
|
-
declare function convertHeicInWorker(input: HeicInput, options: WorkerConvertOptions
|
|
397
|
+
declare function convertHeicInWorker<S extends OutputShape = 'blob'>(input: HeicInput, options: WorkerConvertOptions & {
|
|
398
|
+
output?: S;
|
|
399
|
+
}): Promise<ConvertResult<S>>;
|
|
400
|
+
/**
|
|
401
|
+
* Options for {@link convertManyInWorker}: the {@link convertHeicInWorker}
|
|
402
|
+
* worker options plus the batch semantics of `convertMany`.
|
|
403
|
+
*/
|
|
404
|
+
interface WorkerBatchOptions extends Omit<WorkerConvertOptions, 'onProgress'> {
|
|
405
|
+
/**
|
|
406
|
+
* Per-item progress callback: receives the 0-based item index and its
|
|
407
|
+
* progress percentage (normalized 0–100). Fires only for successful items.
|
|
408
|
+
*/
|
|
409
|
+
onProgress?: (index: number, percent: number) => void;
|
|
410
|
+
/**
|
|
411
|
+
* Resolve with per-item results instead of rejecting the batch on the
|
|
412
|
+
* first failure; all items run to completion (see
|
|
413
|
+
* `ConvertManyOptions.continueOnError`).
|
|
414
|
+
* @default false
|
|
415
|
+
*/
|
|
416
|
+
continueOnError?: boolean;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Converts multiple HEIC images inside Web Workers, mirroring
|
|
420
|
+
* {@link convertMany} semantics (input order, bounded concurrency,
|
|
421
|
+
* `batch_item_failed` aggregation or `continueOnError` per-item results).
|
|
422
|
+
* Concurrency is bounded by `maxConcurrentWorkers` (default
|
|
423
|
+
* `navigator.hardwareConcurrency` clamped to 1–8): items queue behind the
|
|
424
|
+
* worker semaphore, so a large batch never exhausts memory or the browser's
|
|
425
|
+
* worker limit. Each item runs in its own worker instance via
|
|
426
|
+
* {@link convertHeicInWorker}, which means `decoder` cannot be injected and
|
|
427
|
+
* `workerUrl` is required.
|
|
428
|
+
*
|
|
429
|
+
* ```ts
|
|
430
|
+
* const blobs = await convertManyInWorker(heicFiles, {
|
|
431
|
+
* workerUrl: new URL('./converter.worker.js', import.meta.url),
|
|
432
|
+
* workerType: 'module',
|
|
433
|
+
* to: 'webp',
|
|
434
|
+
* continueOnError: true, // get per-item results instead of batch rejection
|
|
435
|
+
* });
|
|
436
|
+
* ```
|
|
437
|
+
*
|
|
438
|
+
* @param inputs HEIC images as Blobs, Files, ArrayBuffers, or Uint8Arrays.
|
|
439
|
+
* @param options Batch + worker conversion options (see {@link WorkerBatchOptions}).
|
|
440
|
+
* @returns The converted images in input order, or per-item result entries
|
|
441
|
+
* when `continueOnError: true`.
|
|
442
|
+
*/
|
|
443
|
+
declare function convertManyInWorker<S extends OutputShape = 'blob'>(inputs: HeicInput[], options: WorkerBatchOptions & {
|
|
444
|
+
output?: S;
|
|
445
|
+
continueOnError: true;
|
|
446
|
+
}): Promise<ConvertItemResult<ConvertResult<S>>[]>;
|
|
447
|
+
declare function convertManyInWorker<S extends OutputShape = 'blob'>(inputs: HeicInput[], options: WorkerBatchOptions & {
|
|
448
|
+
output?: S;
|
|
449
|
+
continueOnError?: false;
|
|
450
|
+
}): Promise<ConvertResult<S>[]>;
|
|
451
|
+
declare function convertManyInWorker<S extends OutputShape = 'blob'>(inputs: HeicInput[], options: WorkerBatchOptions & {
|
|
452
|
+
output?: S;
|
|
453
|
+
continueOnError: boolean;
|
|
454
|
+
}): Promise<Array<ConvertResult<S> | ConvertItemResult<ConvertResult<S>>>>;
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Stable, machine-readable error codes attached to every error the library
|
|
458
|
+
* throws (as `HeicConverterError.code`). Codes are part of the public API:
|
|
459
|
+
* they are additive-only and never repurposed, so callers can branch on
|
|
460
|
+
* `error.code` instead of matching on message strings.
|
|
461
|
+
*/
|
|
462
|
+
type HeicConverterErrorCode = 'invalid_input' | 'invalid_quality' | 'invalid_resize' | 'invalid_format' | 'invalid_crop' | 'invalid_concurrency' | 'decoder_init_failed' | 'decode_failed' | 'progress_callback_failed' | 'render_encode_failed' | 'unsupported_environment' | 'format_unsupported' | 'aborted' | 'worker_unsupported' | 'worker_create_failed' | 'worker_post_failed' | 'worker_failed' | 'worker_timeout' | 'batch_item_failed';
|
|
463
|
+
/**
|
|
464
|
+
* Error thrown by all first-party code paths. Extends `Error` so existing
|
|
465
|
+
* `instanceof Error` / message-based handling keeps working; the `code`
|
|
466
|
+
* (and, for batch failures, `itemIndex`/`itemTotal`/`failedCount`) fields
|
|
467
|
+
* add a structured discriminator without changing message text.
|
|
468
|
+
*/
|
|
469
|
+
declare class HeicConverterError extends Error {
|
|
470
|
+
readonly code: HeicConverterErrorCode;
|
|
471
|
+
/** 0-based index of the failing input. Only set on `batch_item_failed` errors. */
|
|
472
|
+
readonly itemIndex?: number;
|
|
473
|
+
/** Total number of inputs in the batch. Only set on `batch_item_failed` errors. */
|
|
474
|
+
readonly itemTotal?: number;
|
|
475
|
+
/** How many items failed overall. Only set on `batch_item_failed` errors. */
|
|
476
|
+
readonly failedCount?: number;
|
|
477
|
+
constructor(code: HeicConverterErrorCode, message: string, options?: {
|
|
478
|
+
cause?: unknown;
|
|
479
|
+
itemIndex?: number;
|
|
480
|
+
itemTotal?: number;
|
|
481
|
+
failedCount?: number;
|
|
482
|
+
});
|
|
483
|
+
}
|
|
190
484
|
|
|
191
485
|
/**
|
|
192
486
|
* Releases any cached decoder resources.
|
|
@@ -196,26 +490,57 @@ declare function convertHeicInWorker(input: HeicInput, options: WorkerConvertOpt
|
|
|
196
490
|
*/
|
|
197
491
|
declare function freeSharedDecoder(): void;
|
|
198
492
|
/**
|
|
199
|
-
* Converts HEIC image data to a standard web format (JPEG, PNG, WebP,
|
|
493
|
+
* Converts HEIC image data to a standard web format (JPEG, PNG, WebP, AVIF,
|
|
494
|
+
* or SVG).
|
|
200
495
|
*
|
|
201
496
|
* @param input HEIC image as a Blob, File, ArrayBuffer, or Uint8Array.
|
|
202
|
-
* @param options Conversion configuration options.
|
|
203
|
-
* @returns
|
|
497
|
+
* @param options Conversion configuration options (see {@link ConvertOptions}).
|
|
498
|
+
* @returns The converted image as a Blob, data URL string, or ArrayBuffer
|
|
499
|
+
* depending on `options.output` (default Blob).
|
|
500
|
+
* @throws HeicConverterError with a machine-readable `code`:
|
|
501
|
+
* `invalid_input` (unsupported input type or option value),
|
|
502
|
+
* `invalid_quality`, `invalid_resize`, `invalid_crop`,
|
|
503
|
+
* `invalid_format` (unknown `to` value), `decoder_init_failed` (WASM
|
|
504
|
+
* module could not load), `decode_failed` (invalid/corrupt HEIC),
|
|
505
|
+
* `unsupported_environment` (no canvas APIs — e.g. Node.js, where raw RGBA
|
|
506
|
+
* decoding via `LibheifDecoder` is the supported path),
|
|
507
|
+
* `format_unsupported` (environment cannot encode the format, e.g. AVIF
|
|
508
|
+
* in Safari), `aborted` (`options.signal` aborted), or
|
|
509
|
+
* `render_encode_failed`.
|
|
204
510
|
*/
|
|
205
|
-
declare function convertHeic(input: HeicInput, options?: ConvertOptions
|
|
511
|
+
declare function convertHeic<S extends OutputShape = 'blob'>(input: HeicInput, options?: ConvertOptions & {
|
|
512
|
+
output?: S;
|
|
513
|
+
}): Promise<ConvertResult<S>>;
|
|
206
514
|
/**
|
|
207
515
|
* Converts multiple HEIC images to a standard web format.
|
|
208
516
|
*
|
|
209
517
|
* Conversions run with a bounded concurrency (default 4) and results are
|
|
210
|
-
* returned in the same order as the inputs.
|
|
211
|
-
* returned promise rejects as soon as the failure is known
|
|
212
|
-
* conversions are allowed to finish in the background) with
|
|
213
|
-
*
|
|
518
|
+
* returned in the same order as the inputs. By default, if any conversion
|
|
519
|
+
* fails, the returned promise rejects as soon as the failure is known
|
|
520
|
+
* (in-flight conversions are allowed to finish in the background) with a
|
|
521
|
+
* `batch_item_failed` HeicConverterError carrying `itemIndex`, `itemTotal`,
|
|
522
|
+
* and `failedCount` — a batch is all-or-nothing. With
|
|
523
|
+
* `options.continueOnError: true` the promise instead fulfills with
|
|
524
|
+
* per-item `ConvertItemResult` entries and all items run to completion
|
|
525
|
+
* (a mid-batch abort completes not-yet-started items with `aborted`
|
|
526
|
+
* entries instead of launching them).
|
|
214
527
|
*
|
|
215
528
|
* @param inputs HEIC images as Blobs, Files, ArrayBuffers, or Uint8Arrays.
|
|
216
|
-
* @param options Batch conversion options.
|
|
217
|
-
* @returns
|
|
529
|
+
* @param options Batch conversion options (see {@link ConvertManyOptions}).
|
|
530
|
+
* @returns The converted images in input order: results array by default,
|
|
531
|
+
* or per-item result entries when `continueOnError: true`.
|
|
218
532
|
*/
|
|
219
|
-
declare function convertMany(inputs: HeicInput[], options
|
|
533
|
+
declare function convertMany<S extends OutputShape = 'blob'>(inputs: HeicInput[], options: ConvertManyOptions & {
|
|
534
|
+
output?: S;
|
|
535
|
+
continueOnError: true;
|
|
536
|
+
}): Promise<ConvertItemResult<ConvertResult<S>>[]>;
|
|
537
|
+
declare function convertMany<S extends OutputShape = 'blob'>(inputs: HeicInput[], options?: ConvertManyOptions & {
|
|
538
|
+
output?: S;
|
|
539
|
+
continueOnError?: false;
|
|
540
|
+
}): Promise<ConvertResult<S>[]>;
|
|
541
|
+
declare function convertMany<S extends OutputShape = 'blob'>(inputs: HeicInput[], options: ConvertManyOptions & {
|
|
542
|
+
output?: S;
|
|
543
|
+
continueOnError: boolean;
|
|
544
|
+
}): Promise<Array<ConvertResult<S> | ConvertItemResult<ConvertResult<S>>>>;
|
|
220
545
|
|
|
221
|
-
export { type ConvertManyOptions, type ConvertOptions, type DecodedImage, type HeicInput, type IHeicDecoder, type ImageFormat, LibheifDecoder, type LibheifDecoderOptions, type ResizeOptions, type WorkerConvertOptions, convertHeic, convertHeicInWorker, convertMany, freeSharedDecoder };
|
|
546
|
+
export { type ConvertItemResult, type ConvertManyOptions, type ConvertOptions, type ConvertResult, type CropOptions, DEFAULT_QUALITY, type DecodedImage, HeicConverterError, type HeicConverterErrorCode, type HeicInput, type IHeicDecoder, type ImageFormat, LibheifDecoder, type LibheifDecoderOptions, type OutputShape, type ResizeOptions, SUPPORTED_FORMATS, type WorkerBatchOptions, type WorkerConvertOptions, type WorkerProgressMessage, type WorkerResultMessage, convertHeic, convertHeicInWorker, convertMany, convertManyInWorker, freeSharedDecoder };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var i={QualityInvalid:e=>`Quality must be a number between 0.0 and 1.0, got: ${e}`,UnsupportedInputType:e=>`Unsupported input type. Expected Blob, File, ArrayBuffer, or Uint8Array. Got: ${e}`,DecoderInitFailed:e=>`Failed to initialize HEIC decoder: ${e}`,RenderEncodeFailed:(e,r)=>`Failed to render and encode image as ${e}: ${r}`,ConcurrencyInvalid:e=>`Concurrency must be a positive integer, got: ${e}`,ScaleInvalid:e=>`Scale must be a positive finite number, got: ${e}`,MaxWidthInvalid:e=>`maxWidth must be a positive finite number, got: ${e}`,MaxHeightInvalid:e=>`maxHeight must be a positive finite number, got: ${e}`,TargetSizeTooLarge:(e,r,n)=>`Target image size ${e}x${r} exceeds the maximum supported dimension of ${n}px`,BlobToBase64Failed:"Failed to convert Blob to base64 string",BlobToBase64FailedWithCause:e=>`Failed to convert Blob to base64 string: ${e}`,CanvasToBlobFailed:e=>`Failed to convert canvas to blob (type: ${e})`,CanvasUnsupported:"Canvas is not supported in the current environment. Conversion requires a browser environment or canvas polyfills.",InvalidDimensions:(e,r)=>`Invalid image dimensions: ${e}x${r}. Width and height must be positive integers.`,DataLengthMismatch:(e,r,n,t)=>`Image data length mismatch. Expected ${e} bytes for ${r}x${n}, got ${t}`,ContextUnavailable:"Failed to acquire 2D rendering context from canvas",UnsupportedFormat:e=>`Unsupported output format: ${e}`,DecodeFailed:"HEIC decoding failed",DecodeFailedWithDetail:e=>`HEIC decoding failed: ${e}`,WorkerUnsupported:"Web Worker is not supported in the current environment",WorkerCreateFailed:e=>`Failed to create Web Worker: ${e}`,WorkerPostFailed:e=>`Failed to post message to Web Worker: ${e}`,WorkerConversionFailed:"Worker conversion failed",WorkerFailed:"Worker failed",WorkerTimeout:"Web Worker conversion timed out",InputsMustBeArray:"Inputs must be an array of HEIC images",ConvertManyItemFailed:(e,r,n)=>`Conversion of item ${e} of ${r} failed: ${n}`};var y=class{options;module=null;decoderInstance=null;initPromise=null;constructor(r){this.options=r;}async initialize(){if(!this.initPromise){let r={};this.options?.locateFile&&(r.locateFile=this.options.locateFile),this.options?.wasmBinary&&(r.wasmBinary=this.options.wasmBinary),this.initPromise=import('./heic-decoder-L3ME46HT.js').then(({default:n})=>n(r)).then(n=>(this.module=n,this.decoderInstance=new n.HeicDecoder,n)).catch(n=>{throw this.initPromise=null,n});}await this.initPromise;}async decode(r,n){(!this.module||!this.decoderInstance)&&await this.initialize();let t=this.decoderInstance.decode(r,n??null);if(!t)throw new Error(i.DecodeFailed);if(typeof t=="string")throw new Error(i.DecodeFailedWithDetail(t));let o=t.width,a=t.height,s=new Uint8ClampedArray(t.data);return {width:o,height:a,data:s}}free(){this.decoderInstance&&(this.decoderInstance.delete(),this.decoderInstance=null),this.module=null,this.initPromise=null;}};var E=16384;function C(e){if(!e)return;let{maxWidth:r,maxHeight:n,scale:t}=e;if(t!==void 0&&(typeof t!="number"||!Number.isFinite(t)||t<=0))throw new Error(i.ScaleInvalid(t));if(r!==void 0&&(typeof r!="number"||!Number.isFinite(r)||r<=0))throw new Error(i.MaxWidthInvalid(r));if(n!==void 0&&(typeof n!="number"||!Number.isFinite(n)||n<=0))throw new Error(i.MaxHeightInvalid(n))}function B(e,r,n){if(C(n),!n)return {width:e,height:r};let{maxWidth:t,maxHeight:o,scale:a}=n;if(a!==void 0){let g=Math.max(1,Math.round(e*a)),c=Math.max(1,Math.round(r*a));return F(g,c),{width:g,height:c}}if(t===void 0&&o===void 0)return {width:e,height:r};let s=Math.min(t!==void 0?t/e:Number.POSITIVE_INFINITY,o!==void 0?o/r:Number.POSITIVE_INFINITY);if(s>=1)return {width:e,height:r};let l=Math.min(Math.max(1,Math.round(e*s)),t!==void 0?Math.floor(t):Number.POSITIVE_INFINITY),d=Math.min(Math.max(1,Math.round(r*s)),o!==void 0?Math.floor(o):Number.POSITIVE_INFINITY);return F(l,d),{width:l,height:d}}function F(e,r){if(!Number.isFinite(e)||!Number.isFinite(r)||e>E||r>E)throw new Error(i.TargetSizeTooLarge(e,r,E))}async function W(e){if(typeof FileReader<"u")return new Promise((r,n)=>{let t=new FileReader;t.onloadend=()=>{typeof t.result=="string"?r(t.result):n(new Error(i.BlobToBase64Failed));},t.onerror=()=>n(t.error),t.readAsDataURL(e);});try{let r=await e.arrayBuffer(),n=new Uint8Array(r),t="",o=32768;for(let s=0;s<n.length;s+=o)t+=String.fromCharCode(...n.subarray(s,s+o));let a=btoa(t);return `data:${e.type};base64,${a}`}catch(r){throw new Error(i.BlobToBase64FailedWithCause(r instanceof Error?r.message:String(r)),{cause:r})}}function I(e,r,n){return "convertToBlob"in e?e.convertToBlob({type:r,quality:n}):new Promise((t,o)=>{e.toBlob(a=>{a?t(a):o(new Error(i.CanvasToBlobFailed(r)));},r,n);})}function M(e,r){if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(e,r);if(typeof document<"u"){let n=document.createElement("canvas");return n.width=e,n.height=r,n}throw new Error(i.CanvasUnsupported)}function T(e){typeof e.close=="function"?e.close():e.width=0;}function D(e,r,n,t){if(typeof ImageData<"u")e.putImageData(new ImageData(r,n,t),0,0);else {let o=e.createImageData(n,t);o.data.set(r),e.putImageData(o,0,0);}}async function x(e,r,n,t){let{width:o,height:a,data:s}=e;if(!Number.isInteger(o)||o<=0||!Number.isInteger(a)||a<=0)throw new Error(i.InvalidDimensions(o,a));let l=o*a*4;if(s.length!==l)throw new Error(i.DataLengthMismatch(l,o,a,s.length));let d=B(o,a,t),g=d.width!==o||d.height!==a,c=M(d.width,d.height),m=c.getContext("2d");if(!m)throw new Error(i.ContextUnavailable);if(g){let w=M(o,a),f=w.getContext("2d");if(!f)throw new Error(i.ContextUnavailable);D(f,s,o,a),m.drawImage(w,0,0,d.width,d.height),T(w);}else D(m,s,o,a);let p=r.toLowerCase();if(p==="png")return I(c,"image/png");if(p==="jpeg"||p==="jpg")return I(c,"image/jpeg",n);if(p==="webp")return I(c,"image/webp",n);if(p==="svg"){let w=await I(c,"image/png"),f=await W(w),b=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${d.width} ${d.height}" width="${d.width}" height="${d.height}">
|
|
2
|
-
<image width="${
|
|
3
|
-
</svg>`;return new Blob([
|
|
1
|
+
'use strict';var s={QualityInvalid:e=>`Quality must be a number between 0.0 and 1.0, got: ${e}`,ApplyOrientationInvalid:e=>`applyOrientation must be a boolean, got: ${e}`,UnsupportedInputType:e=>`Unsupported input type. Expected Blob, File, ArrayBuffer, or Uint8Array. Got: ${e}`,DecoderInitFailed:e=>`Failed to initialize HEIC decoder: ${e} \u2014 verify heic-decoder.wasm is served (dist/heic-decoder.wasm; see the README "Serving and Locating WASM" section / locateFile option) and that your CSP allows 'wasm-unsafe-eval'`,RenderEncodeFailed:(e,r)=>`Failed to render and encode image as ${e}: ${r}`,ConcurrencyInvalid:e=>`Concurrency must be a positive integer, got: ${e}`,MaxConcurrentWorkersInvalid:e=>`maxConcurrentWorkers must be a positive integer, got: ${e}`,TimeoutInvalid:e=>`timeoutMs must be a finite number >= 0 (0 disables the timeout), got: ${e}`,InputsMustBeArray:"Inputs must be an array of HEIC images",OutputShapeInvalid:e=>`output must be one of 'blob', 'dataUrl', 'arrayBuffer', got: ${e}`,ReuseDecodersInvalid:e=>`reuseDecoders must be a boolean, got: ${e}`,ContinueOnErrorInvalid:e=>`continueOnError must be a boolean, got: ${e}`,PreserveExifInvalid:e=>`preserveExif must be a boolean, got: ${e}`,SignalInvalid:e=>`signal must be an AbortSignal, got: ${e}`,Aborted:"Conversion aborted (AbortSignal was aborted)",ConvertManyItemFailed:(e,r,t)=>`Conversion of item ${e} of ${r} failed: ${t}`,ConvertManyExtraFailures:(e,r)=>` (${e} of ${r} items failed in total)`,ConvertManyOtherErrors:e=>`; other errors: ${e.join(" | ")}`,BatchItemProducedNoResult:e=>`Item ${String(e)} produced no result`,BatchEndedWithoutResult:"Batch ended without a result",ScaleInvalid:e=>`Scale must be a positive finite number, got: ${e}`,MaxWidthInvalid:e=>`maxWidth must be a positive finite number, got: ${e}`,MaxHeightInvalid:e=>`maxHeight must be a positive finite number, got: ${e}`,TargetSizeTooLarge:(e,r,t)=>`Target image size ${e}x${r} exceeds the maximum supported dimension of ${t}px`,BlobToBase64Failed:"Failed to convert Blob to base64 string",BlobToBase64FailedWithCause:e=>`Failed to convert Blob to base64 string: ${e}`,CanvasToBlobFailed:e=>`Failed to convert canvas to blob (type: ${e})`,CanvasUnsupported:"Canvas is not supported in the current environment. In a browser this requires OffscreenCanvas or HTMLCanvasElement. In Node.js there is no canvas: decode raw RGBA with LibheifDecoder and encode externally (see the Node.js section of the README).",InvalidDimensions:(e,r)=>`Invalid image dimensions: ${e}x${r}. Width and height must be positive integers.`,DataLengthMismatch:(e,r,t,n)=>`Image data length mismatch. Expected ${e} bytes for ${r}x${t}, got ${n}`,ContextUnavailable:"Failed to acquire 2D rendering context from canvas",UnsupportedFormat:e=>`Unsupported output format: ${e}`,FormatUnsupported:e=>`The current environment cannot encode '${e}' \u2014 canvas encoding produced no '${e}' image (e.g. AVIF encoding is not supported in this browser). Try 'jpeg', 'png', or 'webp' instead.`,CropInvalid:(e,r)=>`crop.${e} must be ${e==="width"||e==="height"?"a positive integer":"a non-negative integer"}, got: ${r}`,CropOutOfBounds:(e,r,t,n,o,i)=>`crop ${t}x${n} at (${e}, ${r}) exceeds the ${o}x${i} image (crop coordinates are in post-orientation display pixels)`,DecoderFreedDuringDecode:"Decoder was freed before decoding completed; call initialize() again.",DecodeInputAllocFailed:e=>`Failed to allocate ${e} bytes in the WASM heap for decode input`,DecodeFailed:e=>`HEIC decoding failed (no result returned; input: ${e} bytes \u2014 is the file truncated or empty?)`,DecodeFailedWithDetail:(e,r)=>`HEIC decoding failed: ${e} (input: ${r} bytes)`,ProgressCallbackThrew:e=>`onProgress callback threw during decode: ${e}`,WorkerUnsupported:"Web Worker is not supported in the current environment",WorkerCreateFailed:e=>`Failed to create Web Worker: ${e}`,WorkerPostFailed:e=>`Failed to post message to Web Worker: ${e}`,WorkerConversionFailed:"Worker conversion failed",WorkerDecoderUnsupported:"The decoder option is not supported by convertHeicInWorker: the worker creates its own decoder (functions and class instances cannot cross the worker boundary). Use convertHeic with an injected decoder instead.",WorkerFailed:e=>"Worker failed"+(e!==void 0?` (could not load worker script at ${String(e)}; check the path resolves and the script is served as JavaScript, e.g. Content-Type: text/javascript)`:""),WorkerTimeout:(e,r)=>{let t=[`${r.progressMessages} progress message(s) received`];return r.lastPercent!==void 0&&t.push(`last percent ${r.lastPercent}`),r.unknownType!==void 0&&t.push(`last unknown message type '${r.unknownType}' (worker may not implement the progress/result protocol)`),r.workerUrl!==void 0&&t.push(`worker ${String(r.workerUrl)}`),`Web Worker conversion timed out after ${e}ms (${t.join("; ")}). Increase timeoutMs for large images, set timeoutMs to 0 to disable the timeout, and verify the worker script implements the { type: "progress" | "result" } protocol.`}};function T(e){let r=Number(e);return Number.isFinite(r)?Math.min(100,Math.max(0,r)):0}var a=class extends Error{code;itemIndex;itemTotal;failedCount;constructor(r,t,n){super(t,{cause:n?.cause}),this.name="HeicConverterError",this.code=r,n?.itemIndex!==void 0&&(this.itemIndex=n.itemIndex),n?.itemTotal!==void 0&&(this.itemTotal=n.itemTotal),n?.failedCount!==void 0&&(this.failedCount=n.failedCount);}};var _=class{options;module=null;decoderInstance=null;initPromise=null;initGeneration=0;constructor(r){this.options=r;}async initialize(){if(!this.initPromise){let r=++this.initGeneration,t={};this.options?.moduleOverrides&&Object.assign(t,this.options.moduleOverrides),this.options?.locateFile&&(t.locateFile=this.options.locateFile),this.options?.wasmBinary&&(t.wasmBinary=this.options.wasmBinary);let n=import('./heic-decoder-7BA7NJOA.js').then(({default:o})=>o(t)).then(o=>{let i=new o.HeicDecoder;return r!==this.initGeneration?(i.delete(),null):(this.module=o,this.decoderInstance=i,o)}).catch(o=>{throw this.initPromise===n&&(this.initPromise=null),o});this.initPromise=n;}await this.initPromise;}async decode(r,t){if((!this.module||!this.decoderInstance)&&await this.initialize(),!this.module||!this.decoderInstance)throw new a("decode_failed",s.DecoderFreedDuringDecode);let n,o=t?O=>{try{t(T(O));}catch(k){n=n??k;}}:null,i=this.module,c=this.decoderInstance,u;if(typeof c.decodeFromPointer=="function"&&typeof i._malloc=="function"&&typeof i._free=="function"&&i.HEAPU8 instanceof Uint8Array&&r.buffer!==i.HEAPU8.buffer){let O=i._malloc(r.byteLength);if(O===0)throw new a("decode_failed",s.DecodeInputAllocFailed(r.byteLength));try{i.HEAPU8.set(r,O),u=c.decodeFromPointer(O,r.byteLength,o);}finally{i._free(O);}}else u=c.decode(r,o);if(typeof u=="string")throw new a("decode_failed",s.DecodeFailedWithDetail(u,r.byteLength));if(!u)throw new a("decode_failed",s.DecodeFailed(r.byteLength));if(n!==void 0)throw new a("progress_callback_failed",s.ProgressCallbackThrew(n instanceof Error?n.message:String(n)),{cause:n});let d=u.width,l=u.height,m=u.orientation,y=typeof m=="number"&&Number.isInteger(m)&&m>=1&&m<=8?m:1,h=i.HEAPU8 instanceof Uint8Array?i.HEAPU8.buffer:void 0,w=h!==void 0&&u.data.buffer!==h?new Uint8ClampedArray(u.data.buffer,u.data.byteOffset,u.data.byteLength):new Uint8ClampedArray(u.data),g={width:d,height:l,data:w};y>1&&(g.orientation=y);let p=u.exif;return p instanceof Uint8Array&&p.length>=14&&(g.exif=h!==void 0&&p.buffer!==h?new Uint8Array(p.buffer,p.byteOffset,p.byteLength):new Uint8Array(p)),g}free(){this.initGeneration+=1,this.decoderInstance&&(this.decoderInstance.delete(),this.decoderInstance=null),this.module=null,this.initPromise=null;}};var ie=["jpeg","jpg","png","svg","webp","avif"],Se=.92;function R(e){$(e?.to??"jpeg"),e?.quality!==void 0&&ke(e.quality),Ae(e?.applyOrientation),_e(e?.output),Te(e?.signal),X(e?.crop),Me(e?.preserveExif),Q(e?.maxWidth!==void 0||e?.maxHeight!==void 0||e?.scale!==void 0?e:void 0);}function ae(e){Y(e?.continueOnError),Pe(e?.reuseDecoders);}function ke(e){if(typeof e!="number"||!Number.isFinite(e)||e<0||e>1)throw new a("invalid_quality",s.QualityInvalid(e))}function Ae(e){if(e!==void 0&&typeof e!="boolean")throw new a("invalid_input",s.ApplyOrientationInvalid(e))}function _e(e){if(e!==void 0&&e!=="blob"&&e!=="dataUrl"&&e!=="arrayBuffer")throw new a("invalid_input",s.OutputShapeInvalid(e))}function Pe(e){if(e!==void 0&&typeof e!="boolean")throw new a("invalid_input",s.ReuseDecodersInvalid(e))}function Y(e){if(e!==void 0&&typeof e!="boolean")throw new a("invalid_input",s.ContinueOnErrorInvalid(e))}function Me(e){if(e!==void 0&&typeof e!="boolean")throw new a("invalid_input",s.PreserveExifInvalid(e))}function Te(e){if(e!==void 0&&(typeof e!="object"||e===null||typeof e.addEventListener!="function"))throw new a("invalid_input",s.SignalInvalid(e))}function U(e){if(e?.aborted)throw new a("aborted",s.Aborted)}function $(e){let r=String(e).toLowerCase();if(!ie.includes(r))throw new a("invalid_format",s.UnsupportedFormat(String(e)))}function Q(e){if(!e)return;let{maxWidth:r,maxHeight:t,scale:n}=e;if(n!==void 0&&(typeof n!="number"||!Number.isFinite(n)||n<=0))throw new a("invalid_resize",s.ScaleInvalid(n));if(r!==void 0&&(typeof r!="number"||!Number.isFinite(r)||r<=0))throw new a("invalid_resize",s.MaxWidthInvalid(r));if(t!==void 0&&(typeof t!="number"||!Number.isFinite(t)||t<=0))throw new a("invalid_resize",s.MaxHeightInvalid(t))}function X(e){if(!e)return;let{x:r=0,y:t=0,width:n,height:o}=e;if(!Number.isInteger(n)||n<=0)throw new a("invalid_crop",s.CropInvalid("width",n));if(!Number.isInteger(o)||o<=0)throw new a("invalid_crop",s.CropInvalid("height",o));if(!Number.isInteger(r)||r<0)throw new a("invalid_crop",s.CropInvalid("x",r));if(!Number.isInteger(t)||t<0)throw new a("invalid_crop",s.CropInvalid("y",t))}function J(e){if(e!==void 0&&(!Number.isInteger(e)||e<1))throw new a("invalid_concurrency",s.MaxConcurrentWorkersInvalid(e))}function K(e){if(e!==void 0&&(typeof e!="number"||!Number.isFinite(e)||e<0))throw new a("invalid_input",s.TimeoutInvalid(e))}var B=new Uint8Array([69,120,105,102,0,0]),se=new Uint8Array([137,80,78,71,13,10,26,10]);function Z(e){if(e.length<B.length+8)return false;for(let r=0;r<B.length;r++)if(e[r]!==B[r])return false;return Re(e,B.length)}function Re(e,r){if(r+8>e.length)return false;let t=e[r]===73&&e[r+1]===73,n=e[r]===77&&e[r+1]===77;return !t&&!n?false:(t?e[r+2]|e[r+3]<<8:e[r+2]<<8|e[r+3])===42}function Ue(e,r){return e[r]<<8|e[r+1]}function ue(e,r){return (e[r]<<24|e[r+1]<<16|e[r+2]<<8|e[r+3])>>>0}function de(e){try{if(!Z(e))return e;let r=B.length,t=e[r]===73,n=d=>t?e[d]|e[d+1]<<8:e[d]<<8|e[d+1],o=d=>t?(e[d+3]<<24|e[d+2]<<16|e[d+1]<<8|e[d])>>>0:(e[d]<<24|e[d+1]<<16|e[d+2]<<8|e[d+3])>>>0,i=o(r+4);if(i<8||r+i+2>e.length)return e;let c=r+i,u=n(c);for(let d=0;d<u;d++){let l=c+2+d*12;if(l+12>e.length)return e;if(n(l)!==274)continue;let m=n(l+2),y=o(l+4);if(m!==3||y!==1||(t?e[l+8]|e[l+9]<<8:e[l+8]<<8|e[l+9])===1)return e;let w=e.slice();return w[l+8]=t?1:0,w[l+9]=t?0:1,w[l+10]=0,w[l+11]=0,w}return e}catch{return e}}function ce(e,r){try{if(e.length<4||e[0]!==255||e[1]!==216||!Z(r))return e;let t=r.length+2;if(t>65535)return e;let n=2;for(;n<e.length;){if(n+4>e.length||e[n]!==255)return e;let i=e[n+1];if(i===255){n+=1;continue}if(!(i>=224&&i<=239||i===254))break;let u=Ue(e,n+2);if(u<2||n+2+u>e.length)return e;n+=2+u;}let o=new Uint8Array(e.length+4+r.length);return o.set(e.subarray(0,n),0),o[n]=255,o[n+1]=225,o[n+2]=t>>8&255,o[n+3]=t&255,o.set(r,n+4),o.set(e.subarray(n),n+4+r.length),o}catch{return e}}var L;function Be(){if(!L){L=new Uint32Array(256);for(let e=0;e<256;e++){let r=e;for(let t=0;t<8;t++)r=r&1?3988292384^r>>>1:r>>>1;L[e]=r>>>0;}}return L}function Fe(e){let r=Be(),t=4294967295;for(let n=0;n<e.length;n++)t=r[(t^e[n])&255]^t>>>8;return (t^4294967295)>>>0}function N(e,r,t){return e[r]===t.charCodeAt(0)&&e[r+1]===t.charCodeAt(1)&&e[r+2]===t.charCodeAt(2)&&e[r+3]===t.charCodeAt(3)}function le(e,r){try{if(e.length<33)return e;for(let u=0;u<se.length;u++)if(e[u]!==se[u])return e;if(ue(e,8)!==13||!N(e,12,"IHDR")||!Z(r))return e;let t=r.subarray(B.length),n=33;for(;n+8<=e.length;){let u=ue(e,n);if(u>e.length||n+12+u>e.length)return e;if(N(e,n+4,"IDAT")||N(e,n+4,"IEND"))break;if(N(e,n+4,"eXIf"))return e;n+=12+u;}let o=new Uint8Array(12+t.length);o[0]=t.length>>>24&255,o[1]=t.length>>>16&255,o[2]=t.length>>>8&255,o[3]=t.length&255,o.set([101,88,73,102],4),o.set(t,8);let i=Fe(o.subarray(4,8+t.length));o[8+t.length]=i>>>24&255,o[9+t.length]=i>>>16&255,o[10+t.length]=i>>>8&255,o[11+t.length]=i&255;let c=new Uint8Array(e.length+o.length);return c.set(e.subarray(0,n),0),c.set(o,n),c.set(e.subarray(n),n+o.length),c}catch{return e}}var j=16384;function re(){if(typeof OffscreenCanvas>"u"&&typeof document>"u")throw new a("unsupported_environment",s.CanvasUnsupported)}var z=null,De=5e3;async function We(){let e=ee(1,1),r=F(e,"image/avif"),t,n=new Promise(o=>{t=setTimeout(()=>o("timeout"),De);});try{let o=await Promise.race([r,n]);return o==="timeout"?(z=null,!1):o.type==="image/avif"&&o.size>0}finally{t!==void 0&&clearTimeout(t),P(e);}}function ge(){return z===null&&(z=We().catch(()=>false)),z}async function ne(e){if($(e),String(e).toLowerCase()==="avif"&&!await ge())throw new a("format_unsupported",s.FormatUnsupported("avif"))}function He(e,r,t){if(Q(t),!t)return {width:e,height:r};let{maxWidth:n,maxHeight:o,scale:i}=t;if(i!==void 0){let l=Math.max(1,Math.round(e*i)),m=Math.max(1,Math.round(r*i));return fe(l,m),{width:l,height:m}}if(n===void 0&&o===void 0)return {width:e,height:r};let c=Math.min(n!==void 0?n/e:Number.POSITIVE_INFINITY,o!==void 0?o/r:Number.POSITIVE_INFINITY);if(c>=1)return {width:e,height:r};let u=Math.min(Math.max(1,Math.round(e*c)),n!==void 0?Math.floor(n):Number.POSITIVE_INFINITY),d=Math.min(Math.max(1,Math.round(r*c)),o!==void 0?Math.floor(o):Number.POSITIVE_INFINITY);return fe(u,d),{width:u,height:d}}function fe(e,r){if(!Number.isFinite(e)||!Number.isFinite(r)||e>j||r>j)throw new a("invalid_resize",s.TargetSizeTooLarge(e,r,j))}async function te(e){if(typeof FileReader<"u")return new Promise((r,t)=>{let n=new FileReader;n.onloadend=()=>{typeof n.result=="string"?r(n.result):t(new a("render_encode_failed",s.BlobToBase64Failed));},n.onerror=()=>t(new a("render_encode_failed",s.BlobToBase64FailedWithCause(n.error?.message??"FileReader failed"),{cause:n.error??void 0})),n.readAsDataURL(e);});try{let r=await e.arrayBuffer(),t=new Uint8Array(r),n="",o=32768;for(let c=0;c<t.length;c+=o)n+=String.fromCharCode(...t.subarray(c,c+o));let i=btoa(n);return `data:${e.type};base64,${i}`}catch(r){throw new a("render_encode_failed",s.BlobToBase64FailedWithCause(r instanceof Error?r.message:String(r)),{cause:r})}}function F(e,r,t){return "convertToBlob"in e?e.convertToBlob({type:r,quality:t}):new Promise((n,o)=>{e.toBlob(i=>{i?n(i):o(new a("render_encode_failed",s.CanvasToBlobFailed(r)));},r,t);})}function ee(e,r){if(typeof OffscreenCanvas<"u")return new OffscreenCanvas(e,r);if(typeof document<"u"){let t=document.createElement("canvas");return t.width=e,t.height=r,t}throw new a("unsupported_environment",s.CanvasUnsupported)}function P(e){let r=e;typeof r.close=="function"?r.close():e.width=0;}function me(e,r,t,n){if(typeof ImageData<"u")e.putImageData(new ImageData(r,t,n),0,0);else {let o=e.createImageData(t,n);o.data.set(r),e.putImageData(o,0,0);}}function $e(e,r,t){switch(e){case 2:return [-1,0,0,1,r,0];case 3:return [-1,0,0,-1,r,t];case 4:return [1,0,0,-1,0,t];case 5:return [0,1,1,0,0,0];case 6:return [0,1,-1,0,t,0];case 7:return [0,-1,-1,0,t,r];case 8:return [0,-1,1,0,0,r];default:return null}}function Le(e,r){return !r||typeof e!="number"||!Number.isInteger(e)?1:e>=1&&e<=8?e:1}async function pe(e,r,t,n,o){let i=r.exif;if(!t||!i||i.length===0)return e;let c=o?de(i):i,u=new Uint8Array(await e.arrayBuffer()),d=n==="jpeg"?ce(u,c):le(u,c);return d===u?e:new Blob([d.buffer],{type:e.type})}async function he(e,r,t,n,o=true,i,c=false){$(r),X(i);let u=r.toLowerCase();if(u==="avif"&&!await ge())throw new a("format_unsupported",s.FormatUnsupported("avif"));let{width:d,height:l,data:m}=e;if(!Number.isInteger(d)||d<=0||!Number.isInteger(l)||l<=0)throw new a("render_encode_failed",s.InvalidDimensions(d,l));let y=d*l*4;if(m.length!==y)throw new a("render_encode_failed",s.DataLengthMismatch(y,d,l,m.length));let h=Le(e.orientation,o),g=!(e.orientation!==void 0&&e.orientation>=2&&e.orientation<=8)||o,p=$e(h,d,l),O=h>=5,k=O?l:d,M=O?d:l,A=i?.x??0,v=i?.y??0,b=i?i.width:k,E=i?i.height:M;if(i&&(A+b>k||v+E>M))throw new a("invalid_crop",s.CropOutOfBounds(A,v,b,E,k,M));let C=He(b,E,n),q=C.width!==b||C.height!==E,I=p!==null||i!==void 0,f=ee(C.width,C.height),S=f.getContext("2d");if(!S)throw new a("render_encode_failed",s.ContextUnavailable);if(I||q){let x=ee(d,l),H=x.getContext("2d");if(!H)throw new a("render_encode_failed",s.ContextUnavailable);if(me(H,m,d,l),I){let D=C.width/b,W=C.height/E,ye=p?p[0]:1,xe=p?p[1]:0,Ce=p?p[2]:0,Ie=p?p[3]:1,Oe=p?p[4]:0,Ee=p?p[5]:0;S.setTransform(ye*D,xe*W,Ce*D,Ie*W,D*(Oe-A),W*(Ee-v)),S.drawImage(x,0,0);}else S.drawImage(x,0,0,C.width,C.height);P(x);}else me(S,m,d,l);if(u==="png"){let x=await F(f,"image/png");return P(f),pe(x,e,c,"png",g)}if(u==="jpeg"||u==="jpg"){let x=await F(f,"image/jpeg",t);return P(f),pe(x,e,c,"jpeg",g)}if(u==="webp"){let x=await F(f,"image/webp",t);return P(f),x}if(u==="avif"){let x=await F(f,"image/avif",t);if(P(f),x.type!=="image/avif")throw new a("format_unsupported",s.FormatUnsupported("avif"));return x}if(u==="svg"){let x=await F(f,"image/png");P(f);let H=await te(x),D=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${C.width} ${C.height}" width="${C.width}" height="${C.height}">
|
|
2
|
+
<image width="${C.width}" height="${C.height}" href="`,W=`" />
|
|
3
|
+
</svg>`;return new Blob([D,H,W],{type:"image/svg+xml"})}throw new a("invalid_format",s.UnsupportedFormat(String(r)))}async function V(e,r,t,n){let o=n?.continueOnError===true,i=n?.signal,c=new Array(e.length),u=0,d=false,l=0,m=null,y=-1,h=0,w=[],g,p=new Promise(v=>{g=v;}),O=()=>g?.();i&&!o&&i.addEventListener("abort",O,{once:true});let k=async()=>{for(;!d&&!i?.aborted||o;){let v=u;if(u+=1,v>=e.length)return;if(o&&i?.aborted){let b=new a("aborted",s.Aborted);for(let E=v;E<e.length;E++)c[E]={index:E,ok:false,error:b};u=e.length;return}try{let b=await t(e[v],v);c[v]={index:v,ok:!0,result:b},l+=1;}catch(b){if(h+=1,o){c[v]={index:v,ok:false,error:b instanceof Error?b:new Error(String(b))};continue}d?w.length<2&&w.push(b instanceof Error?b.message:String(b)):(d=true,m=b,y=v,g?.());}}},M=Math.min(r,e.length),A=Array.from({length:M},()=>k());try{if(o)return await Promise.all(A),c;if(await Promise.race([Promise.all(A),p]),l===e.length)return c.map(v=>{if(!v||!v.ok)throw new a("batch_item_failed",s.BatchItemProducedNoResult(v?.index));return v.result});if(i?.aborted)throw new a("aborted",s.Aborted);if(d){let v=m instanceof Error?m.message:String(m),b=s.ConvertManyItemFailed(y+1,e.length,v);throw h>1&&(b+=s.ConvertManyExtraFailures(h,e.length),w.length>0&&(b+=s.ConvertManyOtherErrors(w))),new a("batch_item_failed",b,{cause:m,itemIndex:y,itemTotal:e.length,failedCount:h})}throw new a("batch_item_failed",s.BatchEndedWithoutResult)}finally{i?.removeEventListener("abort",O);}}function Ne(){let e=typeof navigator<"u"&&typeof navigator.hardwareConcurrency=="number"?navigator.hardwareConcurrency:4;return Math.max(1,Math.min(e,8))}var G=new Map;function ze(e,r,t){let n=G.get(e);n||(n={active:0,waiters:[]},G.set(e,n));let o={granted:false,released:false},i=()=>{let d=n.waiters.shift();d?d():n.active===0&&n.waiters.length===0&&G.delete(e);},c=()=>{if(!o.released)if(o.released=true,o.granted)o.granted=false,n.active-=1,i();else {let d=n.waiters.indexOf(u);d!==-1&&n.waiters.splice(d,1),n.active===0&&n.waiters.length===0&&G.delete(e);}},u=()=>{o.released||(o.granted=true,n.active+=1,t(c));};return n.active<r?u():n.waiters.push(u),c}function ve(e){return new a("progress_callback_failed",s.ProgressCallbackThrew(e instanceof Error?e.message:String(e)),{cause:e})}function be(e,r){return new Promise((t,n)=>{if(typeof Worker>"u"){n(new a("worker_unsupported",s.WorkerUnsupported));return}if(r.decoder!==void 0){n(new a("invalid_input",s.WorkerDecoderUnsupported));return}try{R(r),J(r?.maxConcurrentWorkers),K(r?.timeoutMs);}catch(I){n(I);return}if(r.signal?.aborted){n(new a("aborted",s.Aborted));return}let o={progressMessages:0},i,c=false,u,d,l=()=>{c||(c=true,u!==void 0&&clearTimeout(u),r.signal?.removeEventListener("abort",m),i&&(i.removeEventListener("message",h),i.removeEventListener("messageerror",g),i.removeEventListener("error",w),i.terminate()),d?.());},m=()=>{l(),n(new a("aborted",s.Aborted));};r.signal?.addEventListener("abort",m,{once:true});let y=r.timeoutMs??6e4;y>0&&(u=setTimeout(()=>{l(),n(new a("worker_timeout",s.WorkerTimeout(y,{progressMessages:o.progressMessages,lastPercent:o.lastPercent,unknownType:o.unknownType,workerUrl:r.workerUrl})));},y));let h=I=>{let f=I.data;if(f?.type==="progress"){o.progressMessages+=1;let S=T(f.percent);if(o.lastPercent=S,S>=100)return;try{r.onProgress?.(S);}catch(x){l(),n(ve(x));}return}if(f?.type!=="result"){typeof f?.type=="string"&&(o.unknownType=f.type);return}if(l(),f.ok&&f.blob!==void 0){try{r.onProgress?.(100);}catch(S){n(ve(S));return}t(f.blob);}else n(new a("worker_failed",f.error??s.WorkerConversionFailed));},w=I=>{l();let f=I.filename?` (${I.filename}:${I.lineno})`:"";n(new a("worker_failed",`${I.message||s.WorkerFailed(r.workerUrl)}${f}`));},g=I=>{l();let f=I.data;n(new a("worker_failed",f instanceof Error?f.message:f!==void 0?String(f):s.WorkerFailed(r.workerUrl),{cause:f}));},{workerUrl:p,onProgress:O,timeoutMs:k,workerType:M,maxConcurrentWorkers:A,signal:v,...b}=r,E=I=>{if(d=I,!c){try{i=new Worker(p,r.workerType==="module"?{type:"module"}:void 0);}catch(f){l(),n(new a("worker_create_failed",s.WorkerCreateFailed(f instanceof Error?f.message:String(f)),{cause:f}));return}i.addEventListener("message",h),i.addEventListener("messageerror",g),i.addEventListener("error",w);try{i.postMessage({input:e,options:b});}catch(f){l(),n(new a("worker_post_failed",s.WorkerPostFailed(f instanceof Error?f.message:String(f)),{cause:f}));}}},C=`${String(p)}|${r.workerType??"classic"}`,q=we(r.maxConcurrentWorkers);d=ze(C,q,E);})}function we(e){return typeof e=="number"&&Number.isInteger(e)?Math.max(1,e):Ne()}async function Ve(e,r){if(!Array.isArray(e))throw new a("invalid_input",s.InputsMustBeArray);if(typeof Worker>"u")throw new a("worker_unsupported",s.WorkerUnsupported);if(r.decoder!==void 0)throw new a("invalid_input",s.WorkerDecoderUnsupported);R(r),Y(r?.continueOnError),J(r?.maxConcurrentWorkers),K(r?.timeoutMs);let{onProgress:t,continueOnError:n,...o}=r??{};return V(e,we(r?.maxConcurrentWorkers),(i,c)=>be(i,{...o,...t!==void 0?{onProgress:u=>t(c,u)}:{}}),{continueOnError:r?.continueOnError===true,signal:r?.signal})}function _r(){}async function Ge(e,r){return r==="dataUrl"?await te(e):r==="arrayBuffer"?await e.arrayBuffer():e}async function qe(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(typeof Blob<"u"&&e instanceof Blob)return new Uint8Array(await e.arrayBuffer());if(e!==null&&typeof e=="object"&&typeof e.arrayBuffer=="function"){let r=await e.arrayBuffer();if(r instanceof ArrayBuffer)return new Uint8Array(r)}if(ArrayBuffer.isView(e)){let r=e;return new Uint8Array(r.buffer,r.byteOffset,r.byteLength)}throw new a("invalid_input",s.UnsupportedInputType(Object.prototype.toString.call(e)))}function Ye(e){if(typeof e!="function")return;let r=false,t,n=o=>{try{e(o);}catch(i){throw new a("progress_callback_failed",s.ProgressCallbackThrew(i instanceof Error?i.message:String(i)),{cause:i})}};return {report:o=>{if(r)return;let i=T(o);if(!(i>=100))try{e(i);}catch(c){t=t??c;}},complete:()=>{if(!r){if(r=true,t!==void 0)throw new a("progress_callback_failed",s.ProgressCallbackThrew(t instanceof Error?t.message:String(t)),{cause:t});n(100);}}}}async function Qe(e,r){let t=r?.to??"jpeg";R(r),re(),await ne(t);let n=r?.signal;U(n);let o=r?.maxWidth!==void 0||r?.maxHeight!==void 0||r?.scale!==void 0?r:void 0,i=await qe(e);U(n);let c=r?.decoder??new _,u=!r?.decoder,d=false,l=()=>{if(!(!u||d)){d=true;try{c.free();}catch{}}};try{try{await c.initialize();}catch(g){throw new a("decoder_init_failed",s.DecoderInitFailed(g instanceof Error?g.message:String(g)),{cause:g})}U(n);let m=Ye(r?.onProgress),y=await c.decode(i,m?m.report:void 0);l(),U(n);let h=r?.quality!==void 0?r.quality:.92,w;try{w=await he(y,t,h,o,r?.applyOrientation??!0,r?.crop,r?.preserveExif??!1);}catch(g){throw g instanceof a?g:new a("render_encode_failed",s.RenderEncodeFailed(t,g instanceof Error?g.message:String(g)),{cause:g})}return U(n),m?.complete(),Ge(w,r?.output??"blob")}finally{l();}}var oe=class{max;idle=[];waiters=[];leasedCount=0;disposed=false;constructor(r){this.max=Math.max(1,r);}async acquire(){let r=this.idle.pop();return r||(this.leasedCount<this.max?(this.leasedCount+=1,new _):new Promise(t=>this.waiters.push(t)))}release(r){if(this.disposed){try{r.free();}catch{}return}let t=this.waiters.shift();t?t(r):this.idle.push(r);}dispose(){this.disposed=true;for(let r of this.idle)try{r.free();}catch{}this.idle.length=0;for(let r of this.waiters.splice(0))r(new _);}};async function Pr(e,r){if(!Array.isArray(e))throw new a("invalid_input",s.InputsMustBeArray);let t=r?.concurrency??4;if(!Number.isInteger(t)||t<1)throw new a("invalid_concurrency",s.ConcurrencyInvalid(t));R(r),ae(r),re(),await ne(r?.to??"jpeg");let{concurrency:n,onProgress:o,continueOnError:i,reuseDecoders:c,...u}=r??{},l=c===true&&r?.decoder===void 0?new oe(Math.min(t,e.length)):null;try{return await V(e,t,async(m,y)=>{let h=l?await l.acquire():null;try{return await Qe(m,{...u,...h?{decoder:h}:{},onProgress:o!==void 0?w=>o(y,w):void 0})}finally{h&&l.release(h);}},{continueOnError:r?.continueOnError===!0,signal:r?.signal})}finally{l?.dispose();}}exports.DEFAULT_QUALITY=Se;exports.HeicConverterError=a;exports.LibheifDecoder=_;exports.SUPPORTED_FORMATS=ie;exports.convertHeic=Qe;exports.convertHeicInWorker=be;exports.convertMany=Pr;exports.convertManyInWorker=Ve;exports.freeSharedDecoder=_r;
|