@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/dist/index.d.mts 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 (between 0.0 and 1.0).
51
- * Applicable for 'jpeg', 'jpg', and 'webp' formats.
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 (0 to 100) during decoding.
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 its
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 provided, a fresh
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
- wasmBinary?: ArrayBuffer;
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 instance must
121
- * be re-initialized (createHeicDecoderModule runs again on the next call).
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. Defaults to 60000 (60s). Set to 0 to
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. Use `workerType: 'module'` when the script uses ES
182
- * module imports (as in the example above); `'classic'` scripts must be
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 A Promise resolving to the converted image as a Blob.
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): Promise<Blob>;
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, or SVG).
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 A Promise resolving to the converted image as a Blob.
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): Promise<Blob>;
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. If any conversion fails, the
211
- * returned promise rejects as soon as the failure is known (in-flight
212
- * conversions are allowed to finish in the background) with an error that
213
- * identifies the failing item index.
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 A Promise resolving to the converted images as Blobs, in input order.
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?: ConvertManyOptions): Promise<Blob[]>;
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 };