@gmitch215/tinyimg 1.1.0 → 1.2.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # 🏞️ tinyimg
2
2
 
3
- > Lightweight & fast image processing library for Cloudflare Workers
3
+ > Lightweight & fast image processing library for WebAssembly
4
4
 
5
5
  tinyimg decodes, transforms, draws on and re-encodes images inside a Worker, with no binding, no
6
6
  subrequest and no per-transformation charge. It is freestanding C compiled to one wasm32 module,
@@ -172,9 +172,15 @@ half the time. Across twelve JPEGs, milliseconds per megapixel spread 7.1x while
172
172
  megabyte spread 1.95x at this scale. The practical rule for a 200 px thumbnail is roughly **480 KB of
173
173
  compressed source**, whatever its dimensions.
174
174
 
175
- The estimate `decide()` returns still prices against source samples and is wrong by up to 12.8x for
176
- that reason, so treat `budgetMs` as a coarse guard rather than a promise. Past the ceiling the
177
- artifact has to be computed once and cached; see [Caching](#caching).
175
+ `decide().estimateMs` covers decode and resample and leaves the encoder out. On 878 held-out cells
176
+ timed against the v1.1.1 model (one machine, sources with alpha excluded) it ran a median 2.0x under
177
+ the clock, 38.6% of cells landed within 0.6x to 2.0x, and the worst was 10.97x under. Adding the
178
+ encoder, which is what `budgetMs` compares against, moved the median to 1.3x under and 59.8% in
179
+ band, with the worst at 9.04x under (a JPEG source) and 7.44x over (a PNG). AVIF sources were the
180
+ worst group, 3.7% in band. The model in this release prices the compressed bytes as well as the
181
+ samples and carries a calibrated upper bound, described under [Admission](#admission). Treat
182
+ `budgetMs` as a coarse guard with no guarantee behind it. Past the ceiling the artifact has to be computed
183
+ once and cached; see [Caching](#caching).
178
184
 
179
185
  A progressive JPEG is the exception worth knowing about. At an eighth scale the transform reads the
180
186
  DC term alone, so the scans that carry only high-frequency detail are stepped over rather than
@@ -190,13 +196,16 @@ the per-stage profile and the comparison against `@jsquash`.
190
196
 
191
197
  ### Gaps
192
198
 
193
- - **AVIF encode has no partition search.** Decode is complete and matches `dav1d` exactly. The
199
+ - **AVIF encode has no partition search.** Decode reads AV1 intra. The
194
200
  encoder uses fixed 8x8 blocks and picks the luma mode from four candidates by absolute
195
201
  difference, so its files run 1.1x to 1.3x libaom's size at matched quality. A partition search is
196
202
  where most of AV1's compression lives.
197
203
  - **No 10 or 12 bit AVIF.** The reconstruction is 8 bits a sample end to end, so an HDR AVIF is
198
204
  refused rather than truncated. 4:2:2 is refused too, for a reason in the format: the
199
205
  specification's own subsampled-size table has no answer for a tall block on such a plane.
206
+ - **Some AVIF files are refused rather than decoded wrong.** Film grain, superres, `grid` and
207
+ `iovl` images, a cropping `clap` aperture, PQ and HLG transfer, and an alpha plane the decoder
208
+ cannot read each return an unsupported-variant error.
200
209
  - **No animation.** Both decode a first frame; neither re-times or composes one.
201
210
  - **You own the caching.** Images caches derivatives at the edge as a product feature. tinyimg gives
202
211
  you the key and leaves the cache to you; see [Caching](#caching).
@@ -298,12 +307,18 @@ carry `.bytes()`, `.blob()`, `.response()` and `.dataUrl()`.
298
307
  | `format` | `ImageFormat` | Container to encode as. Defaults to the source's own. |
299
308
  | `quality` | `number` | 1 through 100, for a lossy format. |
300
309
  | `lossless`, `progressive` | `boolean` | Where the format has the mode. |
301
- | `metadata` | `'keep' \| 'none'` | Whether EXIF survives the encode. Defaults to `keep`. |
310
+ | `metadata` | `'keep' \| 'none'` | Accepted, but a transformation writes no EXIF either way. |
302
311
 
303
312
  The options apply in a fixed order, exported as `TRANSFORM_ORDER`: crop, resize or fit, rotate, flip,
304
313
  the color adjustments, blur, sharpen, trim. An option object has no order of its own, so two callers
305
314
  writing the same keys get the same image.
306
315
 
316
+ A JPEG with an EXIF orientation, or an AVIF with `irot` and `imir` properties, is turned upright before anything else runs, so `width`, `height`,
317
+ `crop` and `fit` all read the image as displayed. A phone photo stored landscape and tagged 90
318
+ degrees comes out portrait, and a request for 400 wide is a portrait 400 wide. `probe` reports the
319
+ tag as `orientation`, and the chainable API applies it with `Image.autoOrient()`, which has to be
320
+ the first operation. Only JPEG and AVIF report it; every other format reports 1.
321
+
307
322
  ### Fit Modes
308
323
 
309
324
  | Mode | Absorbs the mismatch by | Scale may |
@@ -351,6 +366,11 @@ it, call `dispose()` in a `finally`. Encoding does not consume the plan.
351
366
 
352
367
  `pixels()` hands back the raw samples for a caller who wants them rather than a container.
353
368
 
369
+ `edit(fn)` runs after the plan, like `trim` and `rotateFree`, and hands `fn` the materialized image as
370
+ RGBA to change in place. It is for per-pixel arithmetic the library does not carry, such as another
371
+ library's exact blend or a fixed convolution kernel. The extent and channel count cannot change, and
372
+ the view is valid only inside the call.
373
+
354
374
  ## The Planner
355
375
 
356
376
  Nothing runs until the output is asked for. Operations append to a fixed-capacity list, and the plan
@@ -390,13 +410,19 @@ On that chain the planner is worth 3.63x against running the same operations one
390
410
  | ------ | ------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
391
411
  | PNG | 8 and 16 bit, gray/palette/truecolor with and without alpha, Adam7 | hash-chain LZ77, static and dynamic Huffman, the five filters |
392
412
  | JPEG | baseline and progressive, 4:4:4 / 4:2:2 / 4:2:0, CMYK and YCCK, restart markers | quality-scaled tables, optimized Huffman, progressive scan script |
393
- | WebP | VP8 lossy and VP8L lossless | both modes |
413
+ | WebP | VP8 lossy and VP8L lossless | both modes, alpha kept through an `ALPH` chunk when lossy |
394
414
  | GIF | LZW, local and global palettes, interlace, transparency | median-cut palette with Floyd-Steinberg dithering |
395
415
  | TIFF | strips, uncompressed / PackBits / LZW / Deflate, both byte orders | uncompressed and PackBits |
396
416
  | BMP | uncompressed and RLE8 | uncompressed |
397
417
  | AVIF | AV1 intra: every transform, all 13 intra modes, deblock and CDEF | fixed 8x8 partitions, no rate-distortion search |
398
418
  | HEIF | container only; `probe` answers and decode reports a specific error | no |
399
419
 
420
+ A lossy WebP with transparency is written as a `VP8X` header, an `ALPH` chunk holding the alpha plane
421
+ as a lossless stream, and the lossy frame, so alpha is exact at any `quality`; an image whose alpha
422
+ is all 255 gets the plain frame. The JPEG and AVIF encoders write no alpha, and GIF keeps one bit of
423
+ it. When a `transform` output has transparency its format cannot carry, `degraded` contains
424
+ `'alpha'`.
425
+
400
426
  JPEG carries true DCT-domain scaled decode at 1/2, 1/4 and 1/8, and region decode that Huffman-scans
401
427
  past blocks outside the box without transforming them. PNG, GIF, TIFF and BMP row-skip and
402
428
  column-skip.
@@ -726,9 +752,9 @@ const result = await transform(tinyimg, source, {
726
752
  result.format; // 'webp' if it fits inside 7 ms, otherwise 'jpeg'
727
753
  ```
728
754
 
729
- A format you name is never substituted, however far over budget it is. The estimate is accurate to
730
- about 20% on the machine its rates were measured on, so give a budget below the limit rather than at
731
- it, and use [`measure`](#work-counters) when you need what a request cost.
755
+ A format you name is never substituted, however far over budget it is. On the machine its rates were
756
+ measured on, the estimate's median decode error on images held out of the fit is within 10% for every
757
+ format except TIFF (54% under), the encoder is priced separately, and single requests spread wider, so give a budget below the limit rather than at it, and use [`measure`](#work-counters) when you need what a request cost.
732
758
 
733
759
  **A budget the container change cannot meet degrades the plan, and the result says what it gave up.**
734
760
  Container first, because a cheaper encoder costs bytes and nothing else; then the planner's own
@@ -761,6 +787,108 @@ The output extent never changes. A budget decides how the pixels are made, not h
761
787
  is degraded when the estimate already fits. `degraded` is empty on a pass-through, which needs no
762
788
  lever at all.
763
789
 
790
+ ### Admission
791
+
792
+ Naming `admission` beside `budgetMs` turns the budget into a decision on the calibrated upper bound
793
+ instead of the point estimate. `'strict'` throws `TinyImgBudgetError`, carrying the numbers, when the
794
+ bound plus the encoder is over budget, and gives nothing up. `'degrade'` takes the ladder above,
795
+ judged on the bound, and runs the cheapest request that results. `'passthrough'` degrades the same
796
+ way and returns the source bytes unchanged, with `'passthrough'` in `degraded`, when no rung fits;
797
+ that needs the output format to be the source's own, or none asked for.
798
+
799
+ ```ts
800
+ const result = await transform(tinyimg, source, {
801
+ width: 200,
802
+ budgetMs: 10,
803
+ admission: 'passthrough',
804
+ platformScale: 1.9
805
+ });
806
+ ```
807
+
808
+ An admitted request also stops itself. The module sums the work its decoders and encoders have
809
+ counted into a work clock, a function of the counters and not of a timer, because a Worker's timers
810
+ do not advance during CPU work. When the clock passes the budget, the operation returns
811
+ `TINYIMG_ERR_BUDGET`, which `transform` throws as `TinyImgBudgetError`, or answers with the source
812
+ under `'passthrough'`. `Image.admit(budgetMs, options)` returns the decision without running
813
+ anything.
814
+
815
+ The bound is a calibrated prediction under exchangeability, not a guarantee. It is relative to the
816
+ machine the cost model was timed on, so `platformScale` carries your own factor; a Worker ran the same
817
+ module 1.9x slower at the median and 2.4x to 4.7x slower on cheap requests, and the library applies
818
+ none. Leaving `admission` unset keeps `budgetMs` exactly as described above.
819
+
820
+ How it held on 423 requests the model never saw, at five budgets from 5 to 100 ms (2,115 request and
821
+ budget pairs, timed on the Apple M2 Pro the model was calibrated on): the bound admitted 739 pairs
822
+ and 67 of them, 9.07%, ran over budget. The v1.1.1 estimate admitted 1,174 and 451 of them, 38.42%,
823
+ ran over, so the bound admits with 6.73x fewer overruns. It misses the 5% overrun rate set for it
824
+ before the run, so use it as a filter and not as a limit. AVIF sources are the weak spot: 26 of the
825
+ 32 pairs admitted for them ran over. The other formats together ran over on about 6%. The bound also
826
+ refuses requests that fit, 7.31% of the pairs that did (WebP sources 33.9%). The test left out
827
+ sources with alpha, and lossy WebP with alpha and TIFF encode are priced less tightly (held-out
828
+ coverage 0.82 and 0.89). The tables are in `bench/baselines/v1.2/admission-summary.md`.
829
+
830
+ ### Selection
831
+
832
+ `Image.select(options)` searches the decode levers (scale, filter, effort), the output format and its
833
+ quality together, drops each combination that breaks a limit, and returns the best of the rest. It
834
+ reads no pixels and no clock. `Image.bytesFor(selection)` runs the choice and returns the encoded bytes.
835
+
836
+ ```ts
837
+ using image = await Image.open(tinyimg, source);
838
+ image.resize(400, 300);
839
+
840
+ const selection = image.select({ budgetMs: 20, platformScale: 1.9, minDb: 35 });
841
+
842
+ if (selection.feasible) {
843
+ const bytes = await image.bytesFor(selection);
844
+ // serve bytes as selection.choice.format
845
+ } else {
846
+ // selection.reason names the check the nearest miss failed
847
+ }
848
+ ```
849
+
850
+ | Option | Default | Meaning |
851
+ | ----------------- | ------------------------------- | ----------------------------------------------------------------- |
852
+ | `budgetMs` | no limit | CPU the request may spend, judged on the calibrated upper bound |
853
+ | `platformScale` | `1` | How much slower your machine is than the calibrated one |
854
+ | `peakBytes` | the module's heap ceiling | Largest heap bound a candidate may have |
855
+ | `minDb` | no floor | Predicted PSNR against the undegraded output, in dB |
856
+ | `formats` | the source's own, JPEG and WebP | Output containers to consider |
857
+ | `objective` | `'bytes'` | `'bytes'`, `'time'` or `'quality'`, among the candidates that fit |
858
+ | `uncharacterized` | `'refuse'` | `'allow'` keeps a candidate whose quality is unknown |
859
+ | `assumeOpaque` | `false` | Treat an RGBA source as opaque, so JPEG, AVIF and GIF qualify |
860
+
861
+ A `Selection` carries `feasible`, `reason`, `choice` (format, quality, whether it is lossless, the
862
+ lattice position `bytesFor` runs, and the predicted upper-bound cost, peak heap, dB and bytes), the
863
+ output `width` and `height`, whether the source counted as having `alpha`, the measured `coverage` of
864
+ each table, and every candidate in `considered` with the check that removed it. An infeasible
865
+ selection is a normal answer.
866
+
867
+ On the held-out test images at 10, 20 and 50 ms, with and without a 35 dB floor, the joint search
868
+ served 37.8% of 1,137 requests, the planner's own ladder 17.2% and format-and-quality chosen
869
+ independently 33.8%. Against independent choice the gain is 4 points, interval 3.0 to 5.1, and all of
870
+ it comes from requests without a quality floor. The tables are in
871
+ `bench/baselines/v1.2/selector-summary.md`.
872
+
873
+ The predictions come from tables measured on other images, so each one has a stated reach:
874
+
875
+ - **`db` is a table percentile.** It composes the fifth percentile of the decode lever with the fifth
876
+ percentile of the encoder. On images held out of the fit the lever table's percentile held for
877
+ 89.3% of cells (WebP sources 64.5%) and the encode table's for 94.8%, against a 95% target. Read it
878
+ as a likely floor, not a guarantee; `coverage` reports the figure for your source and format.
879
+ - **`bytes` is a median over 99 opaque images.** On the images the table was fitted on, it ordered
880
+ two formats at the same quality tier correctly in 93.5% of pairs. It cannot say how large this
881
+ image will be: measured bytes over predicted ran from 0.32 to 0.58 at the fifth percentile and
882
+ 1.27 to 1.84 at the 95th, by format, at quality 75.
883
+ - **Alpha is priced pessimistically.** The tables come from opaque images, so `db` is low and `bytes`
884
+ leaves out the alpha plane. An RGBA source cannot go to JPEG, AVIF or GIF unless `assumeOpaque` is
885
+ set, and the planner cannot see whether the pixels are opaque.
886
+ - **Lossless TIFF, BMP and WebP outputs have no quality class.** Their error is unmeasured, so
887
+ `'refuse'` drops them, and asking for `formats: ['tiff']` or `['bmp']` returns an infeasible
888
+ selection with reason `'uncharacterized'`. A TIFF or BMP source can still go to JPEG or WebP.
889
+ `uncharacterized: 'allow'` keeps the unclassified candidates with an unknown `db`, which cannot
890
+ satisfy a `minDb`.
891
+
764
892
  ## Caching
765
893
 
766
894
  A cache hit costs no CPU at all, which is how a request too expensive to serve synchronously still
@@ -793,6 +921,9 @@ const { work } = await tinyimg.measure(() => transform(tinyimg, source, { width:
793
921
  work.samplesPerTransform; // 1 at an eighth scale, 4 at a quarter, 64 at full
794
922
  work.decodedSamples / work.sourceSamples; // what the reduction was worth
795
923
  work.filtered; // macroblocks a region did not skip
924
+ work.entropyBytes; // compressed bytes the decoder read, which a region or progressive 1/8 lowers
925
+ work.encodeProbes; // match candidates a PNG encode compared, the cost `encoded` cannot see
926
+ work.alphaDropped; // samples whose alpha a JPEG, AVIF or GIF encode wrote without it
796
927
  ```
797
928
 
798
929
  `samplesPerTransform` is the one to read for a scaled decode: a decode transforming whole blocks and
package/dist/image.d.ts CHANGED
@@ -1,5 +1,44 @@
1
- import { type Color, type Fit, type FlipAxis, type Gravity, type ImageFormat, type PlanDecision, type RawImage, type ResampleFilter, type Source } from './types.js';
1
+ import { type Admission, type Color, type Fit, type FlipAxis, type Gravity, type ImageFormat, type PlanDecision, type RawImage, type ResampleFilter, type Selection, type Source } from './types.js';
2
2
  import { TinyImgModule } from './wasm.js';
3
+ /** What {@link Image.admit} takes beyond the budget. */
4
+ export interface AdmitOptions {
5
+ /**
6
+ * `'degrade'` walks the budget ladder on the upper bound before it rejects; `'strict'` rejects
7
+ * a request that is over as it stands. Defaults to `'degrade'`.
8
+ */
9
+ mode?: 'strict' | 'degrade';
10
+ /** The container the result is written as, which prices the encoder. Defaults to the source's. */
11
+ format?: ImageFormat;
12
+ /** How much slower this machine is than the calibrated one. Defaults to 1. */
13
+ platformScale?: number;
14
+ /** The encoder's quality, which moves its price for JPEG, WebP and AVIF. */
15
+ quality?: number;
16
+ /** Whether WebP is written lossless, which is dearer to encode. */
17
+ lossless?: boolean;
18
+ /** The encoder's compression level for PNG and TIFF. Defaults to `'auto'`. */
19
+ compression?: EncodeOptions['compression'];
20
+ /** The encoder's effort. Defaults to `'fancy'`. */
21
+ effort?: 'fancy' | 'fast';
22
+ }
23
+ /** What {@link Image.select} takes. */
24
+ export interface SelectOptions {
25
+ /** CPU the request may spend, in milliseconds on the machine it runs on. Omitted means no limit. */
26
+ budgetMs?: number;
27
+ /** How much slower this machine is than the calibrated one. Defaults to 1. */
28
+ platformScale?: number;
29
+ /** Largest heap bound a candidate may have, in bytes. Defaults to the module's heap ceiling. */
30
+ peakBytes?: number;
31
+ /** Quality floor as predicted PSNR in dB against the undegraded output. Omitted means no floor. */
32
+ minDb?: number;
33
+ /** Output containers to consider. Defaults to the source's own, JPEG and WebP. */
34
+ formats?: ImageFormat[];
35
+ /** What to minimize among the candidates that fit. Defaults to `'bytes'`. */
36
+ objective?: 'bytes' | 'time' | 'quality';
37
+ /** What to do with a candidate whose quality is unknown. Defaults to `'refuse'`. */
38
+ uncharacterized?: 'refuse' | 'allow';
39
+ /** Treat an RGBA source as opaque, so the search may pick JPEG, AVIF or GIF. */
40
+ assumeOpaque?: boolean;
41
+ }
3
42
  /** What {@link Image.bytes} and its siblings take. */
4
43
  export interface EncodeOptions {
5
44
  /** Quality for a lossy format, 1 through 100. */
@@ -137,6 +176,21 @@ export declare class Image {
137
176
  rotate(degrees: 0 | 90 | 180 | 270): this;
138
177
  /** Mirrors along one axis or both. */
139
178
  flip(axis?: FlipAxis): this;
179
+ /**
180
+ * Turns the source upright by the orientation its EXIF (JPEG) or its `irot` and `imir`
181
+ * properties (AVIF) name.
182
+ *
183
+ * The decoder returns pixels as stored and a plan's output carries no EXIF block, so an image
184
+ * tagged as rotated would otherwise come out sideways. This appends the flip and turn that
185
+ * orientation stands for, which fold into the output addressing like any other, so it costs no
186
+ * pass. A source with no tag, and every format but JPEG and AVIF, appends nothing.
187
+ *
188
+ * Call it before any other operation: a crop or resize after it works in display coordinates,
189
+ * and one before it would not.
190
+ *
191
+ * @throws Error If an operation has already been appended.
192
+ */
193
+ autoOrient(): this;
140
194
  /**
141
195
  * Turns by an arbitrary angle, filling the corners with the background.
142
196
  *
@@ -156,6 +210,18 @@ export declare class Image {
156
210
  * @param tolerance How far a pixel may differ from the border color and still be trimmed.
157
211
  */
158
212
  trim(tolerance?: number): this;
213
+ /**
214
+ * Changes the materialized pixels in place, with a function of your own.
215
+ *
216
+ * **Runs after the plan rather than inside it.** The escape hatch for per-pixel arithmetic the
217
+ * library does not carry, such as another library's exact integer blend or a fixed convolution
218
+ * kernel. The image is widened to RGBA first, so `fn` always sees four channels, and it gets a
219
+ * live view into the module's memory: write to `pixels` and the encoder reads what you wrote.
220
+ * The extent and the channel count cannot change, and the view is only valid inside the call.
221
+ *
222
+ * @param fn Receives the extent and `width * height * 4` bytes, rows tightly packed.
223
+ */
224
+ edit(fn: (image: RawImage) => void): this;
159
225
  /** Scales every channel. 1 is unchanged. */
160
226
  brightness(factor: number): this;
161
227
  /** Scales every channel about mid gray. 1 is unchanged. */
@@ -252,8 +318,43 @@ export declare class Image {
252
318
  * {@link transform}, which does that for you.
253
319
  *
254
320
  * @param milliseconds The budget, or 0 to remove it.
321
+ * @param basis Which cost the ladder compares to the budget. `'point'`, the default, is the
322
+ * estimate; `'upper'` is the calibrated upper bound, so a rung that fits is one whose bound
323
+ * fits.
255
324
  */
256
- budget(milliseconds: number): this;
325
+ budget(milliseconds: number, basis?: 'point' | 'upper'): this;
326
+ /**
327
+ * Decides whether this request fits a CPU budget, on the calibrated upper bound.
328
+ *
329
+ * Prices the plan undegraded, adds the encoder for the format being written, and multiplies by
330
+ * `platformScale`. The request is admitted when that bound is within `budgetMs`. In the default
331
+ * `'degrade'` mode an over-budget request walks the planner's ladder on the bound and is
332
+ * `'degraded'` when a rung fits and `'reject'` when none does; `'strict'` rejects without
333
+ * trying. The plan's own {@link budget} is not read and not changed.
334
+ *
335
+ * The bound is a prediction under exchangeability, not a guarantee, and it is relative to the
336
+ * machine the cost model was calibrated on.
337
+ *
338
+ * @param budgetMs CPU the request may spend, in milliseconds on the machine it runs on.
339
+ * @param options The mode, the output format, the machine factor and the encoder's settings.
340
+ * @return The decision and the numbers behind it.
341
+ */
342
+ admit(budgetMs: number, options?: AdmitOptions): Admission;
343
+ /**
344
+ * Searches the ways to run this request and picks the best one that fits the limits.
345
+ *
346
+ * Crosses the planner's decode levers (scale, filter, effort) with the output format and its
347
+ * quality, drops each combination that breaks a limit, and takes the best by `objective`. It
348
+ * reads no pixels and no clock, so it costs a few table lookups per candidate. Run the choice
349
+ * with {@link bytesFor}.
350
+ *
351
+ * The limits are the options', not the plan's own {@link budget}. A selection with `feasible`
352
+ * false is a normal answer: `reason` names the check the nearest miss failed.
353
+ *
354
+ * @param options The limits and the objective.
355
+ * @return The choice, the predicted figures behind it and every candidate looked at.
356
+ */
357
+ select(options?: SelectOptions): Selection;
257
358
  /**
258
359
  * Runs the plan and encodes the result.
259
360
  *
@@ -265,6 +366,19 @@ export declare class Image {
265
366
  * @return The encoded bytes.
266
367
  */
267
368
  bytes(format?: ImageFormat, options?: EncodeOptions): Promise<Uint8Array<ArrayBuffer>>;
369
+ /**
370
+ * Runs the plan the way a {@link select} chose and encodes it as that choice says.
371
+ *
372
+ * Decodes at the lattice point the selection names (its scale, filter and effort) and writes
373
+ * the format, quality and coding it names. `options` supplies the settings the selection does
374
+ * not carry: `progressive`, `stripMetadata`, `effort` and `compression`. The selection has to
375
+ * come from this image, with no operation added since.
376
+ *
377
+ * @param selection A feasible selection from {@link select}.
378
+ * @param options Encoder settings other than quality and lossless.
379
+ * @return The encoded bytes.
380
+ */
381
+ bytesFor(selection: Selection, options?: Omit<EncodeOptions, 'quality' | 'lossless'>): Promise<Uint8Array<ArrayBuffer>>;
268
382
  /**
269
383
  * Runs the plan and hands back the raw samples.
270
384
  *
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/ts/image.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/ts/image.ts"],"names":[],"mappings":"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"}