rapier-jxl 2.0.0 → 2.1.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/AGENTS.md CHANGED
@@ -11,7 +11,11 @@
11
11
  `encodePhoto(rgba, width, height, {quality: 90})`. The answer is a `Uint8Array` of codestream bytes: save it
12
12
  as `.jxl` or in a `Blob` of type `image/jxl`.
13
13
  4. A JPEG: `transcode(jpegBytes)` gives `{bytes, width, height, orientation}` without decoding. On `JXL_JPEG`,
14
- decode it and call `encodePhoto` on the pixels.
14
+ decode it and call `encodePhoto` on the pixels. Both doors accept `{effort: 4}` to try a smaller entropy
15
+ representation with identical reconstructed pixels; the default is 1.
16
+ For an additional ANS candidate, use the same API from `rapier-jxl/jpeg-ans` or `rapier-jxl/photo-ans` with
17
+ `{effort: 2}`. These optional imports cost about 1.1 kB gzip more than their ordinary door and keep the smaller
18
+ complete stream; benchmark the extra encode work for your use. Default effort 1 stays prefix-coded.
15
19
  5. Anything larger than an icon runs in a worker. Calls are synchronous, so cancel by terminating the worker, or
16
20
  loop over the door's twin (`encodeSteps`, `transcodeSteps`, `encodePhotoSteps`) and leave the loop. A
17
21
  transferred buffer is gone from the sender: copy first if you may retry.
@@ -5,10 +5,10 @@ A bounded survey, not proof of a global minimum; the encoders differ in what the
5
5
 
6
6
  | Encoder / entry | Version | Minified JS + WASM bytes | gzip bytes | Included capability |
7
7
  | --- | --- | ---: | ---: | --- |
8
- | Rapier JXL core | 2.0.0 | 19,495 | 8,475 | 8-bit lossless RGBA, lossy modular with exact alpha |
9
- | Rapier JXL effort door | 2.0.0 | 25,229 | 10,606 | The core, and the weighted predictor searched for lossless |
10
- | Rapier JXL JPEG door | 2.0.0 | 29,592 | 12,533 | JPEG coefficients, orientation; no JPEG reconstruction |
11
- | Rapier JXL photo door | 2.0.0 | 25,646 | 10,804 | 8-bit photographic VarDCT, exact alpha; q100 lossless |
8
+ | Rapier JXL core | 2.1.0 | 19,539 | 8,511 | 8-bit lossless RGBA, lossy modular with exact alpha |
9
+ | Rapier JXL effort door | 2.1.0 | 30,008 | 12,320 | The core, and the weighted predictor searched for lossless |
10
+ | Rapier JXL JPEG door | 2.1.0 | 32,218 | 13,439 | JPEG coefficients, orientation; no JPEG reconstruction |
11
+ | Rapier JXL photo door | 2.1.0 | 31,288 | 12,872 | 8-bit photographic VarDCT, exact alpha; q100 lossless |
12
12
  | [jSquash](https://github.com/jamsinclair/jSquash/tree/main/packages/jxl) | 1.3.0 | 1,388,572 | 525,782 | 8-bit lossless/lossy RGBA |
13
13
  | [Discourse's jSquash package](https://www.npmjs.com/package/@discourse/jxl) | 1.3.0 | 1,388,572 | 525,782 | The same encoder bytes as jSquash |
14
14
  | [Lacinak's jSquash fork](https://github.com/kelaci/jSquash) | 1.3.0-kelaci.0 | 2,071,514 | 844,866 | High bit-depth input options |
package/README.md CHANGED
@@ -7,11 +7,15 @@ JavaScript or WebAssembly JPEG XL encoder among the payloads [we measured](ENCOD
7
7
  - **Lossless.** Every pixel back as it went in: 8-bit grey, grey with alpha, RGB, RGBA.
8
8
  - **Lossy**, quality 1 to 99, for flat-colour rasters (screenshots, pixel art, scanned line art). Alpha stays exact.
9
9
  A picture of few colours is written exact when that is smaller.
10
- - **Smaller exact pictures, slower**: `rapier-jxl/effort`, the same `encode` with `{effort: 2}` or `3`, each never
10
+ - **Smaller exact pictures, slower**: `rapier-jxl/effort`, the same `encode` with `{effort: 2}`, `3`, `4` or `6`, each never
11
11
  larger than the effort below. Effort 1, its default, is the core's bytes.
12
- - **Photographs**: `rapier-jxl/photo`, DCT8 compression with exact alpha, a door of its own.
12
+ - **Photographs**: `rapier-jxl/photo`, DCT8 compression with exact alpha, a door of its own. Effort 5 searches
13
+ quantisation per block and keeps a candidate only when its complete stream is smaller.
13
14
  - **A JPEG carried as its coefficients**: `rapier-jxl/jpeg`, one call, no decode, the way libjxl transcodes. Not
14
15
  carried: the reconstruction data (the JPEG file cannot be rebuilt), the ICC bytes, Exif beyond the orientation, XMP.
16
+ - **Optional ANS entropy coding**: import `transcode` from `rapier-jxl/jpeg-ans` or `encodePhoto` from
17
+ `rapier-jxl/photo-ans` and pass `{effort: 2}`. Each tries ANS after writing the prefix-coded floor and keeps
18
+ the smaller complete stream, with identical reconstructed pixels. These imports leave the core unchanged.
15
19
  - **sRGB or Display P3.** `{colorSpace: 'display-p3'}` declares a wide-gamut canvas's samples. A JPEG's profile is
16
20
  read by what it does, not what it says: sRGB and Display P3 are carried and declared.
17
21
 
@@ -35,12 +39,19 @@ const {bytes, width: w, height: h, orientation} = transcode(new Uint8Array(await
35
39
  holding a bare JPEG XL codestream; `encodePhoto` takes the same. `transcode(jpeg)` returns
36
40
  `{bytes, width, height, orientation}`: the size as shown, the orientation kept in the header.
37
41
 
38
- Doors: `rapier-jxl` (the core), `rapier-jxl/effort`, `rapier-jxl/jpeg`, `rapier-jxl/photo`, each readable, so a
42
+ Doors: `rapier-jxl` (the core), `rapier-jxl/effort`, `rapier-jxl/jpeg`, `rapier-jxl/photo`, and the two optional
43
+ ANS doors above, each readable, so a
39
44
  bundler carries their shared modules once; `rapier-jxl/min` is the core as one minified file. `rapier-jxl/writer`
40
45
  gives a module's author the layers beneath the doors (readable only; they change only with the major version).
41
46
  TypeScript declarations sit beside each door, and a worker and a page are under `public/examples/`. Quality numbers
42
47
  are not the same fidelity across encoders or pictures, and lossy is not always smaller than lossless.
43
48
 
49
+ The photo door defaults to effort 1. Its higher efforts keep the preceding stream as a candidate; effort 5 also
50
+ bounds effort 1's unclipped RGB sample reconstruction error on edge-extended DCT blocks, before clipping and integer output.
51
+ Decoded integer RGB error can differ from that model. Quality 100 remains exact at every effort.
52
+ The quantisation search keeps the preceding stream when its estimated memory would exceed the photo door's
53
+ working budget; the door's 40-million-pixel admission stays the same.
54
+
44
55
  ### In a worker
45
56
 
46
57
  Encoding is synchronous. Run it off the main thread:
@@ -63,9 +74,26 @@ Each door has a twin that does the same work in steps: `encodeSteps`, `transcode
63
74
  job, `for (const done of job)` runs one group of one pass per step (`done` is the fraction, the last exactly 1), and
64
75
  `job.bytes` is the stream after the loop, the same bytes the door writes. Leaving the loop cancels, so a worker can
65
76
  take messages and report progress between steps (`public/examples/worker.mjs`). `job.hurry = true` (the example's
66
- `deadline` sets it) ends the effort door's search at its next step with the smallest stream written so far, never
77
+ `deadline` sets it) ends a door's search at its next step with the smallest stream written so far, never
67
78
  larger than effort 1's.
68
79
 
80
+ The JPEG and photograph doors also read effort: 3 tries a 32-cluster budget, and 4 also tries an order learned
81
+ from coefficient counts. These entropy rungs keep the smaller complete stream and preserve every reconstructed pixel. Their
82
+ default remains 1; effort 2 keeps the default plan. A hurried JPEG job finishes its effort-1 floor in its first
83
+ half; through effort 4 the photo job first makes coefficients, then writes that floor, and searches in its final
84
+ quarter. At effort 5, its first half finishes the preceding stream and its second half searches quantisation,
85
+ keeping the completed floor on a hurry.
86
+
87
+ The optional ANS doors keep default effort 1's prefix bytes. Effort 2 adds one ANS candidate; efforts 3 and 4
88
+ also retain the ordinary prefix searches, and photo effort 5 retains its quantisation search. ANS uses a bounded
89
+ group buffer of 1,376,256 bytes plus histogram tables; encoding both candidates costs more CPU and may raise peak
90
+ RSS. Hurry keeps a completed candidate even when it arrives at the final group's yield.
91
+
92
+ Version 2.1.0 fits the photo door's existing quantisation constants across thumbnail and source-sized photos.
93
+ Lossy photo bytes change deliberately; lossless and ordinary JPEG streams retain their hashes. Pin a package
94
+ version when exact lossy output bytes matter. Quality numbers remain a setting, not a guarantee of equal
95
+ perceptual quality on every image.
96
+
69
97
  ### Limits and errors
70
98
 
71
99
  One picture at a time, at most 16,384 pixels a side and a 16 MiB stream. Each door's `LIMITS` sets its pixels by its
@@ -97,23 +125,26 @@ New: `rapier-jxl/effort`, each door's twin in steps with `hurry`, `colorSpace: '
97
125
 
98
126
  | file | bytes | gzip | Brotli | added to the core, gzip |
99
127
  | --- | ---: | ---: | ---: | ---: |
100
- | `rapier-jxl.min.mjs`, the core: `encode` | 19,495 | 8,475 | 7,494 | |
101
- | `effort.min.mjs`: `encode` with effort | 25,229 | 10,606 | 9,351 | 2,131 |
102
- | `jpeg.min.mjs`: `transcode` | 29,592 | 12,533 | 11,072 | 7,673 |
103
- | `photo.min.mjs`: `encodePhoto` | 25,646 | 10,804 | 9,537 | 4,242 |
104
- | every door in one bundle | 47,499 | 19,228 | 16,977 | |
105
- | all readable modules | 136,580 | 42,707 | | |
106
-
107
- Exact bytes of release 2.0.0's files, measured by the script that stages this repository; `sizes.json`
128
+ | `rapier-jxl.min.mjs`, the core: `encode` | 19,539 | 8,511 | 7,515 | |
129
+ | `effort.min.mjs`: `encode` with effort | 30,008 | 12,320 | 10,860 | 3,809 |
130
+ | `jpeg.min.mjs`: `transcode` | 32,218 | 13,439 | 11,874 | 8,497 |
131
+ | `photo.min.mjs`: `encodePhoto` | 31,288 | 12,872 | 11,370 | 6,257 |
132
+ | `jpeg-ans.min.mjs`: optional ANS carrier | 35,281 | 14,506 | 12,804 | 9,564 |
133
+ | `photo-ans.min.mjs`: optional ANS photo | 34,293 | 13,899 | 12,295 | 7,298 |
134
+ | every door in one bundle | 61,101 | 24,091 | 21,147 | |
135
+ | all readable modules | 174,894 | 53,445 | | |
136
+
137
+ Exact bytes of release 2.1.0's files, measured by the script that stages this repository; `sizes.json`
108
138
  carries their hashes and tools (terser 5.51.2, Node v22.22.2; gzip 9, Brotli 11). Each minified file stands alone
109
139
  and is proved at staging to write the same bytes as its readable source; the last column is what a door adds to a
110
140
  bundle that already holds the core. `effort`'s `encode` is the core's at effort 1, so it takes the core's place, in
111
141
  that column and in the bundle of every door.
112
142
 
113
- What it writes: bare codestreams, 8-bit, prefix codes (never ANS), one frame, no preview, animation, ICC (sRGB or
143
+ What it writes: bare codestreams, 8-bit, prefix codes (or ANS in the optional doors), one frame, no preview, animation, ICC (sRGB or
114
144
  Display P3 is declared), XYB, chroma-from-luma or filters. Lossless in modular mode, a palette of up to 2,048
115
145
  colours weighed against direct coding by actual length, groups of 256, reversible YCoCg, a predictor chosen per
116
- channel; at effort 2 and 3 also the weighted predictor, its contexts split by its own error. Lossy through Squeeze
146
+ channel; at effort 2 and 3 also the weighted predictor, its contexts split by its own error; at 4 local modelling of
147
+ palette indices; at 6 local gradient-property splits. Effort 5 uses rung 4. Lossy through Squeeze
117
148
  with exact alpha. Carried JPEGs in VarDCT with the JPEG's own tables. The photo door
118
149
  writes DCT8 coefficients for the same writer.
119
150
 
package/admit.mjs CHANGED
@@ -29,8 +29,12 @@ export function admitPixels(data, width, height, limits) {
29
29
  if (data.length !== width * height * 4) throw fault('JXL_INPUT', 'Pixels are width * height * 4 bytes: straight (not premultiplied) RGBA, row by row.');
30
30
  }
31
31
 
32
+ export function admitOutputSize(length) {
33
+ if (length > LIMITS.bytes) throw fault('JXL_SIZE', 'The encoded picture exceeds 16 MiB.');
34
+ }
35
+
32
36
  export function answer(bytes) {
33
- if (bytes.length > LIMITS.bytes) throw fault('JXL_SIZE', 'The encoded picture exceeds 16 MiB.');
37
+ admitOutputSize(bytes.length);
34
38
  return bytes;
35
39
  }
36
40
 
package/ans.mjs ADDED
@@ -0,0 +1,157 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Optional JPEG XL ANS coding. The core imports none of this module.
3
+ // The normative alias construction follows ISO/IEC 18181-1; libjxl 0.11.2's
4
+ // ans_common.cc and enc_ans.cc were consulted for the wire layout.
5
+ import {BitWriter, ceilLog2, floorLog2} from './bits.mjs';
6
+ import {hybridToken, writeContextMap, writeUintConfig} from './prefix.mjs';
7
+ import {buildTokenCoding} from './entropy.mjs';
8
+
9
+ const LOG_LENGTHS = [5, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 6, 7];
10
+ const LOG_CODES = [17, 11, 15, 3, 9, 7, 4, 2, 5, 6, 0, 33, 1];
11
+ // A VarDCT group has at most three 32x32-block planes. Each block emits one
12
+ // nonzero-count token and at most 63 AC tokens; alpha uses its separate modular stream.
13
+ const GROUP_TOKENS = 3 * 32 * 32 * 64;
14
+
15
+ function varUint8(w, value) {
16
+ if (!value) { w.write(1, 0); return; }
17
+ const n = floorLog2(value);
18
+ w.write(1, 1); w.write(3, n); w.write(n, value - (1 << n));
19
+ }
20
+
21
+ // Correct the largest rounding error until the table totals exactly 4096.
22
+ // Every represented symbol keeps a positive count, including rare symbols.
23
+ function normalise(freqs) {
24
+ let total = 0, last = 0;
25
+ for (let i = 0; i < freqs.length; i++) {
26
+ total += freqs[i];
27
+ if (freqs[i]) last = i + 1;
28
+ }
29
+ const counts = new Uint16Array(last || 1);
30
+ if (!total) { counts[0] = 4096; return counts; }
31
+ let sum = 0;
32
+ for (let i = 0; i < last; i++) if (freqs[i]) sum += counts[i] = Math.max(1, Math.round(freqs[i] * 4096 / total));
33
+ while (sum !== 4096) {
34
+ const direction = sum < 4096 ? 1 : -1;
35
+ let chosen = -1, error = -Infinity;
36
+ for (let i = 0; i < last; i++) if (freqs[i] && (direction > 0 || counts[i] > 1)) {
37
+ const candidate = direction * (freqs[i] * 4096 - counts[i] * total);
38
+ if (candidate > error) { chosen = i; error = candidate; }
39
+ }
40
+ counts[chosen] += direction; sum += direction;
41
+ }
42
+ return counts;
43
+ }
44
+
45
+ function writeDistribution(w, counts) {
46
+ const used = [];
47
+ let omit = 0;
48
+ for (let i = 0; i < counts.length; i++) {
49
+ if (counts[i]) used.push(i);
50
+ if (counts[i] > counts[omit]) omit = i;
51
+ }
52
+ if (used.length <= 2) {
53
+ w.write(1, 1); w.write(1, used.length - 1);
54
+ for (const symbol of used) varUint8(w, symbol);
55
+ if (used.length === 2) w.write(12, counts[used[0]]);
56
+ return;
57
+ }
58
+ w.write(1, 0); w.write(1, 0);
59
+ // Full count precision: shift 12, encoded by the bounded gamma form.
60
+ w.write(3, 7); w.write(3, 5);
61
+ varUint8(w, counts.length - 3);
62
+ const logs = new Uint8Array(counts.length);
63
+ let omitLog = 0;
64
+ for (let i = 0; i < counts.length; i++) if (i !== omit && counts[i]) {
65
+ logs[i] = floorLog2(counts[i]) + 1;
66
+ omitLog = Math.max(omitLog, logs[i] + (i < omit ? 1 : 0));
67
+ }
68
+ logs[omit] = omitLog;
69
+ for (const log of logs) w.write(LOG_LENGTHS[log], LOG_CODES[log]);
70
+ for (let i = 0; i < counts.length; i++) if (i !== omit && logs[i] > 1) {
71
+ const bits = logs[i] - 1;
72
+ w.write(bits, counts[i] - (1 << bits));
73
+ }
74
+ }
75
+
76
+ // Invert the decoder's alias table once per histogram. State remainders then
77
+ // use one indexed load, with no search or approximation in the symbol loop.
78
+ function reverseAlias(counts, logAlphabet) {
79
+ const size = 1 << logAlphabet, entry = 4096 >> logAlphabet;
80
+ const starts = new Uint16Array(counts.length + 1), reverse = new Uint16Array(4096);
81
+ let single = -1;
82
+ for (let i = 0; i < counts.length; i++) {
83
+ starts[i + 1] = starts[i] + counts[i];
84
+ if (counts[i] === 4096) single = i;
85
+ }
86
+ if (single >= 0) {
87
+ for (let i = 0; i < 4096; i++) reverse[i] = i;
88
+ return {starts, reverse};
89
+ }
90
+ const cutoffs = new Int32Array(size), aliases = new Uint16Array(size), offsets = new Int32Array(size);
91
+ const under = [], over = [];
92
+ cutoffs.set(counts);
93
+ for (let i = 0; i < size; i++) {
94
+ if (cutoffs[i] < entry) under.push(i);
95
+ else if (cutoffs[i] > entry) over.push(i);
96
+ }
97
+ while (over.length) {
98
+ const from = over.pop(), to = under.pop(), taken = entry - cutoffs[to];
99
+ cutoffs[from] -= taken;
100
+ aliases[to] = from; offsets[to] = cutoffs[from] - cutoffs[to];
101
+ if (cutoffs[from] < entry) under.push(from);
102
+ else if (cutoffs[from] > entry) over.push(from);
103
+ }
104
+ for (let i = 0; i < size; i++) for (let j = 0; j < entry; j++) {
105
+ const own = j < cutoffs[i], symbol = own ? i : aliases[i], offset = own ? j : j + offsets[i];
106
+ reverse[starts[symbol] + offset] = i * entry + j;
107
+ }
108
+ return {starts, reverse};
109
+ }
110
+
111
+ export function buildAnsCoding(counts, options) {
112
+ const prefix = buildTokenCoding(counts, options);
113
+ const contexts = prefix.histograms.map(() => []);
114
+ for (let ctx = 0; ctx < counts.contexts; ctx++) if (counts.totals[ctx]) contexts[prefix.contextMap[ctx]].push(ctx);
115
+ const histograms = prefix.histograms.map(({config}, i) => ({config, counts: normalise(counts.tokens(contexts[i], config, 256))}));
116
+ const logAlphabet = Math.max(5, ceilLog2(Math.max(...histograms.map(h => h.counts.length))));
117
+ for (const histogram of histograms) Object.assign(histogram, reverseAlias(histogram.counts, logAlphabet));
118
+ const header = new BitWriter();
119
+ header.write(1, 0);
120
+ if (prefix.contextMap.length > 1) writeContextMap(header, prefix.contextMap);
121
+ header.write(1, 0); header.write(2, logAlphabet - 5);
122
+ for (const histogram of histograms) writeUintConfig(header, histogram.config, logAlphabet);
123
+ for (const histogram of histograms) writeDistribution(header, histogram.counts);
124
+
125
+ // One group's storage is reused for every group; image dimensions never
126
+ // multiply this reverse-order workspace. No input or coefficient is mutated.
127
+ // The shared cluster builder caps histogram IDs at 48, so metadata fits one byte.
128
+ const values = new Uint32Array(GROUP_TOKENS), metadata = new Uint8Array(GROUP_TOKENS), emitted = new Uint16Array(GROUP_TOKENS);
129
+ const slots = [0, 0, 0];
130
+ let length = 0;
131
+ const write = (_w, ctx, value) => {
132
+ values[length] = value; metadata[length++] = prefix.contextMap[ctx];
133
+ };
134
+ const flush = w => {
135
+ let state = 0x13 * 65536;
136
+ for (let i = length - 1; i >= 0; i--) {
137
+ const h = histograms[metadata[i]];
138
+ hybridToken(h.config, values[i], slots);
139
+ const symbol = slots[0], freq = h.counts[symbol];
140
+ values[i] = slots[2]; metadata[i] = slots[1];
141
+ if ((state >>> 20) >= freq) {
142
+ emitted[i] = state & 65535; metadata[i] |= 64; state >>>= 16;
143
+ }
144
+ const q = Math.floor(state / freq);
145
+ state = q * 4096 + h.reverse[h.starts[symbol] + state - q * freq];
146
+ }
147
+ w.write(32, state);
148
+ for (let i = 0; i < length; i++) {
149
+ if (metadata[i] & 64) w.write(16, emitted[i]);
150
+ const bits = metadata[i] & 63;
151
+ if (bits) w.write(bits, values[i]);
152
+ }
153
+ length = 0;
154
+ };
155
+ // Preserve the original bucket/context choice to isolate prefix versus ANS.
156
+ return {bits: prefix.bits, write, flush, writeHistograms: w => w.append(header)};
157
+ }
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // The optional doors add ANS at effort 2; earlier completed streams remain the
3
+ // answer on a tie, hurry, allocation failure or candidate above the size limit.
4
+ import {coefficientEffortSteps} from './coefficient-effort.mjs';
5
+ import {varDCTSteps} from './vardct.mjs';
6
+ import {part} from './bits.mjs';
7
+ import {buildAnsCoding} from './ans.mjs';
8
+
9
+ export function* coefficientAnsSteps(jpeg, effort, fallback) {
10
+ if (effort < 2) return yield* coefficientEffortSteps(jpeg, effort, fallback);
11
+ let best = yield* part(coefficientEffortSteps(jpeg, effort, fallback), 0, 2);
12
+ if (yield 0.5) return best;
13
+ try {
14
+ const candidate = varDCTSteps(jpeg, {coding: buildAnsCoding});
15
+ let step;
16
+ while (!(step = candidate.next()).done) {
17
+ // The final group has already been written at fraction 1. Let its bounded
18
+ // assembly finish before comparing; a hurry must not discard that work.
19
+ if ((yield 0.5 + step.value / 2) && step.value < 1) { candidate.return(); return best; }
20
+ }
21
+ if (step.value.length < best.length) best = step.value;
22
+ } catch (error) {
23
+ if (!(error instanceof RangeError && !error.code) && error.code !== 'JXL_SIZE') throw error;
24
+ }
25
+ return best;
26
+ }
@@ -0,0 +1,62 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Entropy search shared by the JPEG and photograph doors; coefficients and quantisation never change here.
3
+ import {varDCTSteps} from './vardct.mjs';
4
+ import {ZIGZAG} from './jfif.mjs';
5
+ import {complete} from './bits.mjs';
6
+
7
+ // Frequently nonzero positions first, counted in buckets of eight blocks. Ties keep the natural transposed
8
+ // zigzag, and DC stays first. Integer counts and an explicit tie rule make the permutation deterministic.
9
+ export function coefficientOrders(components) { return complete(coefficientOrderSteps(components)); }
10
+
11
+ export function* coefficientOrderSteps(components) {
12
+ const scan = ZIGZAG.map(n => ((n & 7) << 3) | (n >> 3));
13
+ const histograms = components.map(() => new Uint32Array(64)), total = components.reduce((n, c) => n + c.coeffs.length, 0);
14
+ let done = 0;
15
+ for (let c = 0; c < components.length; c++) {
16
+ const {coeffs} = components[c], counts = histograms[c];
17
+ // At most one 256-pixel group's coefficient count between yields, including JPEG padding blocks.
18
+ for (let from = 0; from < coeffs.length; from += 65536) {
19
+ const end = Math.min(from + 65536, coeffs.length);
20
+ for (let at = from; at < end; at += 64) for (let k = 1; k < 64; k++) if (coeffs[at + scan[k]]) counts[k]++;
21
+ done += end - from;
22
+ if (yield done / total) return null;
23
+ }
24
+ }
25
+ return histograms.map(counts => [0, ...Array.from({length: 63}, (_, k) => k + 1).sort((a, b) => Math.floor(counts[b] / 8) - Math.floor(counts[a] / 8) || a - b)]);
26
+ }
27
+
28
+ // Rung 3 tries a 32-cluster budget at cost 160; rung 4 also tries one learned order. Complete earlier streams
29
+ // remain available on a tie, hurry, memory failure or candidate above the stream limit. No input is mutated.
30
+ // A supplied fallback is already written; it also makes the first writer interruptible for a lossy candidate.
31
+ export function* coefficientEffortSteps(jpeg, effort, fallback) {
32
+ if (effort < 3 && !fallback) return yield* varDCTSteps(jpeg);
33
+ let best = fallback;
34
+ try {
35
+ const first = varDCTSteps(jpeg); let step, hurry;
36
+ while (!(step = first.next()).done) {
37
+ hurry = yield step.value / 2;
38
+ if (hurry && best && step.value < 1) { first.return(); return best; }
39
+ }
40
+ if (!best || step.value.length < best.length) best = step.value;
41
+ if (hurry || effort < 3) return best;
42
+ const parts = effort < 4 ? 1 : 3, clustered = varDCTSteps(jpeg, {clusters: {maxClusters: 32, newClusterCost: 160}});
43
+ while (!(step = clustered.next()).done) {
44
+ hurry = yield 0.5 + step.value / (2 * parts);
45
+ // The final group has already been written. Finish its stream before honoring a late hurry.
46
+ if (hurry && step.value < 1) { clustered.return(); return best; }
47
+ }
48
+ if (step.value.length < best.length) best = step.value;
49
+ if (hurry || effort < 4) return best;
50
+ const learning = coefficientOrderSteps(jpeg.components);
51
+ while (!(step = learning.next()).done) if (yield 0.5 + (1 + step.value) / 6) { learning.return(); return best; }
52
+ const candidate = varDCTSteps(jpeg, {orders: step.value});
53
+ while (!(step = candidate.next()).done) {
54
+ hurry = yield 0.5 + (2 + step.value) / 6;
55
+ if (hurry && step.value < 1) { candidate.return(); return best; }
56
+ }
57
+ return step.value.length < best.length ? step.value : best;
58
+ } catch (error) {
59
+ if (!best || !(error instanceof RangeError && !error.code) && error.code !== 'JXL_SIZE') throw error;
60
+ return best;
61
+ }
62
+ }
@@ -0,0 +1,10 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Only doors with a search read effort; keeping it here adds no work or bytes to the pixel core.
3
+ import {fault} from './admit.mjs';
4
+
5
+ export function admitEffort(options = {}) {
6
+ if (options === null || typeof options !== 'object') throw fault('JXL_INPUT', 'Options are an object.');
7
+ const effort = options.effort === undefined ? 1 : options.effort;
8
+ if (!Number.isInteger(effort) || effort < 1 || effort > 9) throw fault('JXL_INPUT', 'Effort is a whole number from 1 to 9.');
9
+ return effort;
10
+ }
package/effort.d.mts CHANGED
@@ -3,8 +3,9 @@ import type {Pixels, EncodeOptions, Job} from './index.mjs';
3
3
  export {LIMITS} from './index.mjs';
4
4
  export type {Pixels, Limits, EncodeOptions, ErrorCode, EncoderError, Job} from './index.mjs';
5
5
  /** The core's encode with a search above it for exact pictures: effort 1 (the default) writes the core's bytes; 2 tries
6
- * the weighted predictor on every channel, 3 also splits its contexts by the predictor's error. Never larger than the
7
- * effort below; slower. */
6
+ * the weighted predictor on every channel, 3 splits its contexts by that predictor's error, 4 models palette indices
7
+ * per group, and 6 also learns gradient-property splits. A level without another rung uses the preceding one.
8
+ * Never larger than the effort below; slower. */
8
9
  export function encode(data: Pixels, width: number, height: number, options?: EncodeOptions): Uint8Array;
9
10
  /** encode's work and bytes as steps. Above effort 1 an exact picture's first half (fractions up to 0.5) writes effort
10
11
  * 1's stream and the second searches; `hurry` ends the search with the smallest stream written so far. */
package/effort.min.mjs CHANGED
@@ -1,2 +1,2 @@
1
- /*! Rapier JXL 2.0.0 | MIT License Copyright (c) 2026 rapier.website Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2
- function*t(t,n,e){let o,r;for(;!(o=t.next(r)).done;)r=yield(n+o.value)/e;return o.value}function n(t){return t>=0?2*t:2*-t-1}function e(t){return 31-Math.clz32(t)}function o(t){return t<=1?0:32-Math.clz32(t-1)}function r(t,n){t.t([[9,1],[13,1],[18,1],[30,1]],n)}function s(t,n,e,o,s,{xyb:i=!1,orientation:c=1,colorSpace:l}={}){t.write(16,2815),t.write(1,0),r(t,e),t.write(3,0),r(t,n),t.write(1,0);const f=1!==c;t.write(1,f?1:0),f&&t.write(6,c-1),t.write(4,8),s?t.write(3,5):t.write(2,0),t.write(1,i?1:0),3===o&&"display-p3"===l?t.write(21,903568):3===o?t.write(1,1):t.write(15,14100),f&&t.write(1,1),t.write(2,0),t.write(1,1),t.o()}function i(t,{alpha:n,shift:e=1}){t.write(9,8),n&&t.write(2,0),t.write(2,e),function(t,n){t.write(n?7:5,0),t.write(11,1)}(t,n)}function c(t,n,e=256){const o=Math.ceil(t/e),r=Math.ceil(n/e);return{i:o,u:r,p:Math.ceil(t/(8*e)),M:Math.ceil(n/(8*e)),A:1===o&&1===r}}function l(t,n){const e=n.map(t=>t.length);!function(t,n){t.write(1,0),t.o();for(const e of n)t.t([[10,0],[14,1024],[22,17408],[30,4211712]],e);t.o()}(t,e);const o=t.finish(),r=new Uint8Array(o.length+e.reduce((t,n)=>t+n,0));r.set(o);let s=o.length;for(const t of n)r.set(t,s),s+=t.length;return r}function f(t,n){const e=new Uint8Array(t.length),o=[];for(let n=0;n<t.length;n++)t[n]>0&&o.push(n);if(!o.length)return e;if(1===o.length)return e[o[0]]=1,e;for(let r=1;;r*=2){const s=o.map(n=>({w:Math.max(t[n],r),m:n,l:null,r:null})).sort((t,n)=>t.w-n.w||t.m-n.m),i=[];let c=0,l=0;const f=()=>c<s.length&&(l>=i.length||s[c].w<=i[l].w)?s[c++]:i[l++];for(;s.length-c+(i.length-l)>1;){const t=f(),n=f();i.push({w:t.w+n.w,m:-1,l:t,r:n})}const a=[[f(),0]];let u=0;for(;a.length;){const[t,n]=a.pop();t.m>=0?(e[t.m]=n,n>u&&(u=n)):a.push([t.l,n+1],[t.r,n+1])}if(u<=n)return e}}function a(t,n,e,o,r,s){const i=[];for(;i.push(o&r),o>>=s;)o--;for(let o=i.length-1;o>=0;o--)t.push(e),n.push(i[o])}function u(t,n){let e=0;for(let o=0;o<n;o++)e=e<<1|1&t,t>>=1;return e}function h(t){const n=new Uint32Array(17),e=new Uint32Array(17),o=new Uint16Array(t.length);for(const e of t)n[e]++;n[0]=0;for(let t=1,o=0;t<=16;t++)o=o+n[t-1]<<1,e[t]=o;for(let n=0;n<t.length;n++)t[n]&&(o[n]=u(e[t[n]]++,t[n]));return o}function y(t){const n=[];for(let e=0;e<t.length;e++)t[e]>0&&n.push(e);const e=n.length,o=n[e-1]+1||1,r=e<=4?new Uint8Array(o):f(t,15).subarray(0,o);let s=0;if(e<=4){n.sort((n,e)=>t[e]-t[n]||n-e),s=4===e&&t[n[0]]>t[n[2]]+t[n[3]]?1:0;const o=e<2?[0]:2===e?[1,1]:3===e?[1,2,2]:s?[1,2,3,3]:[2,2,2,2];n.forEach((t,n)=>{r[t]=o[n]}),n.sort((t,n)=>r[t]-r[n]||t-n)}return{U:o,I:r,S:h(r),T:e&&e<=4?n:null,v:s}}function w(t,n){if(n.U<=1)return;if(n.T){const o=e(n.U-1)+1;t.write(2,1),t.write(2,n.T.length-1);for(const e of n.T)t.write(o,e);return void(4===n.T.length&&t.write(1,n.v))}const o=n.I,r=[],s=[];let i=o.length-1;for(;i>0&&!o[i];)i--;let c=8;for(let t=0;t<=i;){const n=o[t];let e=1;for(;t+e<=i&&o[t+e]===n;)e++;let l=e;if(n&&n!==c&&(r.push(n),s.push(0),l--,c=n),l<3)for(let t=0;t<l;t++)r.push(n),s.push(0);else a(r,s,n?16:17,l-3,n?3:7,n?2:3);t+=e}const l=new Uint32Array(18);for(const t of r)l[t]++;let u=0;for(const t of l)t&&u++;1===u&&(l[r[0]?0:1]=l[r[0]]);const y=f(l,5),w=h(y);let p=18;for(;p>0&&!y[D[p-1]];)p--;t.write(2,0);for(let n=0;n<p;n++){const e=y[D[n]];t.write(F[e],Q[e])}for(let n=0;n<r.length;n++){const e=r[n];t.write(y[e],w[e]),16===e?t.write(2,s[n]):17===e&&t.write(3,s[n])}}function p(t,n=0,e=0){return{split:t,C:n,q:e,L:1<<t}}function d(t,n,e=15){t.write(o(e+1),n.split),n.split!==e&&(t.write(o(n.split+1),n.C),t.write(o(n.split-n.C+1),n.q))}function M(t,n,o){if(n<t.L)return o[0]=n,o[1]=0,void(o[2]=0);const r=e(n),s=n-(1<<r),i=r-t.C-t.q;o[0]=t.L+(r-t.split<<t.C+t.q|s>>r-t.C<<t.q|s&(1<<t.q)-1),o[1]=i,o[2]=n>>t.q&(1<<i)-1}function A(t,n,e,o=0){M(t,n,H),e[o+H[0]]++}function g(t,n,e,o,r=0){M(e,o,H);const s=r+H[0];t.write(n.I[s],n.S[s]),H[1]&&t.write(H[1],H[2])}function m(t,{N:n=null,P:r,X:s}){t.write(1,n?1:0),n&&(t.t([[0,224],[0,512],[0,4096],[15,8]],n.J),t.t([[0,3],[0,4],[2,5],[8,9]],n.minLength),d(t,n._,8)),r.length>1&&function(t,n){let e=0;for(const t of n)e=Math.max(e,t);const r=e?o(e+1):0;if(r<=3){if(t.write(1,1),t.write(2,r),r)for(const e of n)t.write(r,e);return}t.write(1,0),t.write(1,0);const s=p(8),i=p(4),c=n.length>=64,l=new Uint32Array(c?257:e+1),f=[];for(let t=0;t<n.length;){let e=1;for(;c&&t+e<n.length&&n[t+e]===n[t];)e++;if(e>=8)f.push([n[t],e-1]),l[n[t]]++,A(i,e-1-7,l,224),t+=e;else{for(let o=0;o<e;o++)f.push([n[t],0]),l[n[t]]++;t+=e}}const a=y(l);if(!c){m(t,{P:new Uint8Array(1),X:[{config:s,code:a}]});for(const[n]of f)g(t,a,s,n);return}const u=new Uint32Array(1);u[0]=1,m(t,{N:{J:224,minLength:7,_:i},P:new Uint8Array([1,0]),X:[{config:p(0),code:y(u)},{config:s,code:a}]});for(const[n,e]of f)g(t,a,s,n),e&&g(t,a,i,e-7,224)}(t,r),t.write(1,1);for(const n of s)d(t,n.config,15);for(const n of s){const o=n.code.U-1;if(o){const n=e(o);t.write(1,1),t.write(4,n),t.write(n,o-(1<<n))}else t.write(1,0)}for(const n of s)w(t,n.code)}function b(t,n=0,e=1){return{G:t,offset:n,O:e,context:-1}}function U(t,n,e,o){return{j:t,R:n,left:e,right:o}}function I(t,n){const e=(o,r)=>{if(o===r)return n?t[o].B:t[o];const s=o+r>>1;return U(n,n?t[s].k:s,e(s+1,r),e(o,s))};return e(0,t.length-1)}function S(t){return I(t,0)}function x(t,e){const o=[e],r=[],s=[];for(const t of o){if(t.left){r.push(t.j+1,n(t.R)),o.push(t.left,t.right);continue}t.context=s.length,s.push(t);const e=1===t.O?0:31-Math.clz32(t.O&-t.O);r.push(0,t.G,n(t.offset),e,(t.O>>e)-1)}const i=new Uint32Array(64);for(const t of r)A(tt,t,i);const c=y(i);m(t,{P:new Uint8Array(6),X:[{config:tt,code:c}]});for(const n of r)g(t,c,tt,n);return s}function T(t,n){const e=[[3,0],[6,8],[10,72],[13,1096]];if("rct"===n.type)t.write(2,0),t.t(e,n.Y),t.t([[0,6],[2,0],[4,2],[6,10]],n.Z??6);else if("palette"===n.type)t.write(2,1),t.t(e,n.Y),t.t([[0,1],[0,3],[0,4],[13,1]],n.D),t.t([[8,0],[10,256],[12,1280],[16,5376]],n.F),t.t([[0,0],[8,1],[10,257],[16,1281]],n.H??0),t.write(4,n.G??0);else{if("squeeze"!==n.type)throw new Error("unknown transform "+n.type);{t.write(2,2);const o=n.K??[];t.t([[0,0],[4,1],[6,9],[8,41]],o.length);for(const n of o)t.write(1,n.V?1:0),t.write(1,n.W?1:0),t.t(e,n.Y),t.t([[0,1],[0,2],[0,3],[4,4]],n.D)}}}function v(t,{$:n=!0,tt:e=[]}={}){t.write(1,n?1:0),t.write(1,1),t.t([[0,0],[0,1],[4,2],[8,18]],e.length);for(const n of e)T(t,n)}function C(t,n,e,o=t=>t.context){const r=new Uint8Array(n.length+1);for(const t of n)r[t.context]=o(t)+1;const s=new Uint32Array(2);s[1]=1;const i=[{config:tt,code:y(s)}],c=Math.max(...r);for(let t=0;t<c;t++)i.push({config:tt,code:y(e[t])});return m(t,{N:$,P:r,X:i}),i}function q(t,e,o,r,s,i){const c=i.G,l=i.offset,f=i.O,a=tt,u=W;let h=0;const y=(n,o=a,r=0)=>{t?g(t,e,o,n,r):A(o,n,e,r)},w=()=>{if(h){if(h>=8)y(0),y(h-7-1,u,224);else for(let t=0;t<h;t++)y(0);h=0}},p=(t,e)=>{const r=o[t];let s;1===f?s=r-e-l:(s=Math.round((r-e-l)/f),o[t]=e+l+s*f),0!==s?(w(),y(n(s))):h++};for(let t=0,n=0;t<s;t++)for(let e=0;e<r;e++,n++){let s;if(0===c)s=0;else{const i=e?o[n-1]:t?o[n-r]:0,l=t?o[n-r]:i;if(1===c)s=i;else if(2===c)s=l;else if(3===c)s=(i+l)/2|0;else{const f=i+l-(e&&t?o[n-r-1]:i);if(5===c){const t=i<l?i:l,n=i<l?l:i;s=f<t?t:f>n?n:f}else{if(4!==c)throw new Error("predictor "+c+" is not coded here");s=Math.abs(f-i)<Math.abs(f-l)?i:l}}}p(n,s)}w()}function E(t,n,e,{palette:o=!0}={}){const r=n*e;let s=!0,i=!0;for(let n=0,e=0;e<r&&(255===t[n+3]||(s=!1,i))&&(t[n]===t[n+1]&&t[n]===t[n+2]||(i=!1,s));e++,n+=4);const c=i?1:3,l=!s,f=c+(l?1:0),a=n=>i?l?t[n]+256*t[n+3]:t[n]:t[n]+256*t[n+1]+65536*t[n+2]+(l?16777216*t[n+3]:0),u=new Map;let h=null;for(let t=0,n=0;o&&n<r;n++,t+=4){const n=a(t);if(0!==n&&!u.has(n)&&(u.set(n,1),u.size>=2048))break}if(o&&u.size<2048){const t=[...u.keys()],n=(t,n)=>t>>>8*n&255,e=t=>(.299*n(t,0)+.587*n(t,1)+.114*n(t,2)+.01)*(4===f?n(t,3):1);t.sort((t,n)=>e(t)-e(n));const o=new Map([[0,0]]);t.forEach((t,n)=>o.set(t,n+1)),h={colours:[0,...t],index:o,key:a,byte:n}}return{colour:c,alpha:l,channels:f,palette:h}}function*L(n,e,o,{shape:r=E(n,e,o),colorSpace:s}={}){let i,c;const l=r.palette?[r,{...r,palette:null}]:[r];for(let r=0;r<l.length;r++)try{const c=yield*t(N(n,e,o,l[r],s),r,l.length);(!i||c.length<i.length)&&(i=c)}catch(t){if("JXL_SIZE"!==t.code)throw t;c=t}if(!i)throw c;return i}function*N(t,n,e,o,r){const{channels:f,palette:a}=o,u=c(n,e),h=a?2:f,p=Array.from({length:h},()=>b(V)),d=S(p),M=Array.from({length:h},()=>new Int16Array(65536)),A=(e,o,r,s)=>{for(let i=0;i<s;i++){let s=4*((o+i)*n+e),c=i*r;for(let n=0;n<r;n++,s+=4,c++)if(a)M[0][c]=a.index.get(a.key(s));else if(f>=3){const n=t[s],e=t[s+1],o=t[s+2],r=n-o,i=o+(r>>1),l=e-i;M[0][c]=i+(l>>1),M[1][c]=r,M[2][c]=l,4===f&&(M[3][c]=t[s+3])}else M[0][c]=t[s],2===f&&(M[1][c]=t[s+3])}};let g=null;if(a){const t=a.colours.length;g=new Int16Array(t*f),a.colours.forEach((n,e)=>{for(let o=0;o<f;o++)g[o*t+e]=a.byte(n,o)})}const m=t=>p[a?u.A?1:0:t],U=a?1:f,I=u.i*u.u,T=2*I,E=(t,o)=>{const r=t%u.i*Z,s=(t/u.i|0)*Z,i=Math.min(Z,n-r),c=Math.min(Z,e-s);A(r,s,i,c),o(i,c)};let L=0;if(!a){const t=t=>{const n=y(t),e=new Y(128);w(e,n);let o=e.nt;for(let e=0;e<t.length;e++)t[e]&&(o+=t[e]*(n.I[e]+Math.max(0,e<224?e-1:e-236)));return o},o=Math.min(n,32),r=Math.min(e,32),s=[V,K].map(t=>({G:t,et:p.map(()=>new Uint32Array(nt))}));for(const t of[0,.5,1]){A(Math.floor((n-o)*t),Math.floor((e-r)*t),o,r);for(const t of s)for(let n=0;n<f;n++)q(null,t.et[n],M[n],o,r,b(t.G))}p.forEach((n,e)=>{const o=s.map(n=>t(n.et[e])),r=o[1]<o[0]?1:0;n.G=s[r].G})}const N=a?[{type:"palette",Y:0,D:f,F:a.colours.length}]:f>=3?[{type:"rct",Y:0,Z:6}]:[],P=p.map(()=>new Uint32Array(nt)),X=t=>P[p.indexOf(t)];g&&q(null,X(p[0]),g,a.colours.length,f,p[0]);for(let t=0;t<I;t++)E(t,(t,n)=>{for(let e=0;e<U;e++)q(null,X(m(e)),M[e],t,n,m(e))}),yield++L/T;const J=new Y(256);s(J,n,e,o.colour,o.alpha,{colorSpace:r}),i(J,{alpha:o.alpha});const _=new Y(4096);_.write(1,1),_.write(1,1);const z=x(_,d),G=C(_,z,P,t=>p.indexOf(t)),O=t=>G[p.indexOf(t)+1].code;v(_,{$:!0,tt:N}),g&&q(_,O(p[0]),g,a.colours.length,f,p[0]);const j=[];if(u.A)E(0,(t,n)=>{for(let e=0;e<U;e++)q(_,O(m(e)),M[e],t,n,m(e))}),yield 1,j.push(_.finish());else{j.push(_.finish());for(let t=0;t<u.p*u.M+1;t++)j.push(new Uint8Array(0));for(let t=0;t<I;t++)E(t,(t,n)=>{const e=new Y(t*n*U+64);v(e,{$:!0,tt:[]});for(let o=0;o<U;o++)q(e,O(m(o)),M[o],t,n,m(o));j.push(e.finish())}),yield++L/T}return l(J,j)}function P(t,n,e){const o=t>=n&&n>=e?1:t<=n&&n<=e?-1:0;if(!o)return 0;let r=(4*(t*=o)-3*(e*=o)-(n*=o)+6)/12|0;return r-(1&r)>2*(t-n)&&(r=2*(t-n)+1),r+(1&r)>2*(n-e)&&(r=2*(n-e)),o*r}function X(t,n){const{w:e,h:o,data:r}=t,s=n?e:o,i=s+1>>1,c=s-i,l=n?i:e,f=n?o:i,a=n?c:e,u=n?o:c,h=new Int16Array(l*f),y=new Int16Array(a*u),w=n?1:e;for(let t=0;t<f;t++)for(let o=0;o<l;o++){const i=n?o:t,f=n?t*e+2*o:2*t*e+o;if(i===c){h[t*l+o]=r[f];continue}const u=r[f],p=r[f+w],d=et(u,p),M=i+1<c?et(r[f+2*w],r[f+3*w]):1&s?r[f+2*w]:d;h[t*l+o]=d,y[t*a+o]=u-p-P(i?r[f-w]:d,d,M)}const p=(e,o,r)=>({w:o,h:r,ot:t.ot+ +n,rt:t.rt+!n,data:e});return[p(h,l,f),p(y,a,u)]}function J(t){const n=[],e=t.length;let o=t[0].w,r=t[0].h;for(e>2&&t[1].w===o&&t[1].h===r&&(n.push({V:!0,W:!1,Y:1,D:2}),n.push({V:!1,W:!1,Y:1,D:2})),!(o>r)&&r>8&&(n.push({V:!1,W:!0,Y:0,D:e}),r=r+1>>1);o>8||r>8;)o>8&&(n.push({V:!0,W:!0,Y:0,D:e}),o=o+1>>1),r>8&&(n.push({V:!1,W:!0,Y:0,D:e}),r=r+1>>1);return n}function*_(t,n,e,{quality:o=90,shape:r=E(t,n,e,{palette:!1}),colorSpace:f}={}){const a=function(t){return t>=100?0:t>=30?.1+.09*(100-t):53/3e3*t*t-1.15*t+25}(o);if(!(a>0))throw new Error("lossy encoding needs a quality below 100");const{colour:u,alpha:h,channels:y}=r,w=n*e,p=Array.from({length:y},()=>new Int16Array(w));for(let n=0,e=0;e<w;e++,n+=4){if(3===u){const o=t[n],r=t[n+1],s=t[n+2],i=o-s,c=s+(i>>1),l=r-c;p[0][e]=c+(l>>1),p[1][e]=i,p[2][e]=l}else p[0][e]=t[n];h&&(p[y-1][e]=t[n+3])}const d=p.map((t,o)=>({w:n,h:e,ot:0,rt:0,data:t,component:3===u?o:0===o?0:3})),M=1===n&&e>ot&&3===u,A=M?J(d).filter(t=>!t.V):1!==n&&1!==e||3!==u?[]:J(d),g=function(t,n=J(t)){const e=t.map(t=>({...t,level:0,st:!1}));for(const t of n){const n=t.Y+t.D-1,o=t.W?n+1:e.length;for(let r=t.Y;r<=n;r++){const[n,s]=X(e[r],t.V),i=e[r].level+1;e[r]={...n,level:i,st:e[r].st,component:e[r].component},e.splice(o+(r-t.Y),0,{...s,level:i,st:!0,component:e[r].component})}}return e}(d,A.length?A:void 0),m=t=>t.st?0:V,U=t=>function(t,n,e,o){let r=Math.min(16,n+e);if(r>0&&r--,3===t)return 1;const s=.25*function(t){let n=1;for(let e=0;e<24;e++)n=(4*n+t/(n*n*n*n))/5;return t*n}(o),i=1<<r,c=1===t||2===t?.35*s*Math.max(.5,1024/i):.35*s*1.1*(163.84/i);return Math.max(1,Math.floor(c))}(t.component,t.ot+(M&&t.component>0&&t.component<3?1:0),t.rt,a),T=[...3===u?[{type:"rct",Y:0,Z:6}]:[],{type:"squeeze",K:A}],L=c(n,e,ot),N=L.p*L.M,P=L.i*L.u;let _=0;for(;_<g.length&&g[_].w<=ot&&g[_].h<=ot;)_++;const z=(t,n,e,o)=>{const r=n>>t.ot,s=e>>t.rt;return{x:r,y:s,w:Math.min(t.w,r+(o>>t.ot))-r,h:Math.min(t.h,s+(o>>t.rt))-s}},G=[{index:0,k:0,it:[]}];for(let t=0;t<_;t++)G[0].it.push({c:t,rect:{x:0,y:0,w:g[t].w,h:g[t].h}});if(!L.A){for(let t=0;t<N;t++){const n=t%L.p,e=t/L.p|0,o={index:1+t,k:1+N+t,it:[]};for(let t=_;t<g.length;t++){const r=g[t];if(Math.min(r.ot,r.rt)<3)continue;const s=z(r,n*rt,e*rt,rt);s.w>0&&s.h>0&&o.it.push({c:t,rect:s})}G.push(o)}for(let t=0;t<P;t++){const n=t%L.i,e=t/L.i|0,o={index:2+N+t,k:1+3*N+17+t,it:[]};for(let t=_;t<g.length;t++){const r=g[t];if(Math.min(r.ot,r.rt)>2)continue;const s=z(r,n*ot,e*ot,ot);s.w>0&&s.h>0&&o.it.push({c:t,rect:s})}G.push(o)}}for(const t of G)for(const n of t.it){const t=g[n.c];n.ct=b(m(t),0,U(t)),n.ct.channel=n.c}const O=G.filter(t=>t.it.length),j=1===O.length?S(O[0].it.map(t=>t.ct)):function(t){return I(t,1)}(O.map(t=>({k:t.k,B:S(t.it.map(t=>t.ct))}))),R=new Int16Array(1048576),B=t=>{const n=g[t.c],e=t.rect;if(e.w===n.w&&e.h===n.h)return n.data;for(let t=0;t<e.h;t++)R.set(n.data.subarray((e.y+t)*n.w+e.x,(e.y+t)*n.w+e.x+e.w),t*e.w);return R},k=[...new Set(G.flatMap(t=>t.it.map(t=>t.c)))].sort((t,n)=>t-n),Z=new Map(k.map((t,n)=>[t,n])),D=k.map(()=>new Uint32Array(nt)),F=1+2*G.length;let Q=1;yield Q/F;for(const t of G){for(const n of t.it)q(null,D[Z.get(n.c)],B(n),n.rect.w,n.rect.h,n.ct);yield++Q/F}const H=new Y(256);s(H,n,e,u,h,{colorSpace:f}),i(H,{alpha:h,shift:n>256||e>256?3:1});const K=Array.from({length:L.A?1:2+N+P},()=>null),W=K[0]=new Y(65536);W.write(1,1),W.write(1,1);const $=C(W,x(W,j),D,t=>Z.get(t.channel));v(W,{$:!0,tt:T});for(const t of G){let n=K[t.index];n||(n=K[t.index]=new Y(4096),t.it.length&&v(n,{$:!0,tt:[]}));for(const e of t.it)q(n,$[Z.get(e.c)+1].code,B(e),e.rect.w,e.rect.h,e.ct);yield++Q/F}return l(H,function(t){return t.map(t=>t?t.finish():new Uint8Array(0))}(K))}function z(t,e,o,r,s,i=0,c=ft){const l=r+2,f=new Int32Array(2*l),a=new Int32Array(2*l),u=new Int32Array(2*l),h=new Int32Array(2*l),y=new Int32Array(2*l),w=new Int32Array(8);let p=0;const d=(n,o,r=tt,s=0)=>{t?g(t,e[n],r,o,s):A(r,o,e[n],s)},M=()=>{if(p){if(p>$.minLength)d(w[0],0),d(w[1],p-$.minLength-1,$._,$.J);else for(let t=0;t<p;t++)d(w[t],0);p=0}};for(let t=0,e=0;t<s;t++){const s=1&t?0:l,A=1&t?l:0;for(let l=0;l<r;l++,e++){const g=l?o[e-1]:t?o[e-r]:0,m=t?o[e-r]:g,b=l&&t?o[e-r-1]:g,U=l+1<r&&t?o[e-r+1]:m,I=t>1?o[e-2*r]:m,S=A+l,x=l<r-1?S+1:S,T=l?S-1:S;let v=lt(f[S]+f[x]+f[T],13),C=lt(a[S]+a[x]+a[T],12),q=lt(u[S]+u[x]+u[T],12),E=lt(h[S]+h[x]+h[T],12);const L=8*m,N=8*g,P=8*U,X=8*b,J=8*I,_=l?y[s+l-1]:0,z=y[S],G=y[T],O=y[x],j=z+_;let R=_;Math.abs(z)>Math.abs(R)&&(R=z),Math.abs(G)>Math.abs(R)&&(R=G),Math.abs(O)>Math.abs(R)&&(R=O);const B=c[it[R<-501?0:R>501?1002:R+501]],k=N+P-L,Y=L-(16*(j+O)>>5),Z=N-(10*(j+G)>>5),D=L-(7*G+7*z+7*O+0*(J-L)+0*(X-N)>>5),F=27-Math.clz32(v+C+q+E);v>>=F,C>>=F,q>>=F,E>>=F;const Q=v+C+q+E;let H=Math.floor(((Q>>1)-1+k*v+Y*C+Z*q+D*E)*ct[Q-1]/16777216);if((z^_|z^G)<=0){const t=Math.min(N,P,L),n=Math.max(N,P,L);H=H<t?t:H>n?n:H}const K=o[e],V=K-(H+3>>3)-i;0===V?(p<8&&(w[p]=B),p++):(M(),d(B,n(V)));const W=8*K,$=Math.abs(k-W)+3>>3,tt=Math.abs(Y-W)+3>>3,nt=Math.abs(Z-W)+3>>3,et=Math.abs(D-W)+3>>3;y[s+l]=H-W,f[s+l]=$,a[s+l]=tt,u[s+l]=nt,h[s+l]=et,f[A+l+1]+=$,a[A+l+1]+=tt,u[A+l+1]+=nt,h[A+l+1]+=et}}M()}function G(t){try{return t()}catch(t){if(t instanceof RangeError&&!t.code)throw at("JXL_MEMORY","Not enough memory for this picture.");throw t}}function O(t,n,e,o){return function(t){let n;for(;!(n=t.next()).done;);return n.value}(j(t,n,e,o))}function j(n,e,o,r){const{quality:f,colorSpace:a}=function(t={},n=100){if(null===t||"object"!=typeof t)throw at("JXL_INPUT","Options are an object: {quality, colorSpace}.");if(void 0!==t.quality&&(n=t.quality),"number"!=typeof n||!Number.isFinite(n)||n<1||n>100)throw at("JXL_INPUT","Quality is a number from 1 to 100.");const e=void 0===t.colorSpace?"srgb":t.colorSpace;if("srgb"!==e&&"display-p3"!==e)throw at("JXL_INPUT","The colour space is srgb or display-p3.");return{quality:n,colorSpace:e}}(r),u=void 0===r?.effort?1:r.effort;if(!Number.isInteger(u)||u<1||u>9)throw at("JXL_INPUT","Effort is a whole number from 1 to 9.");return function(t,n,e,o){if(function(t,n,e=B){if(!Number.isInteger(t)||!Number.isInteger(n)||t<1||n<1)throw at("JXL_INPUT","A picture is at least one pixel wide and high, in whole pixels.");if(t>e.edge||n>e.edge)throw at("JXL_DIMENSIONS","A picture is at most "+e.edge+" pixels on a side.");if(t*n>e.pixels)throw at("JXL_DIMENSIONS","A picture is at most "+e.pixels.toLocaleString("en-US")+" pixels.")}(n,e,o),!(t instanceof Uint8Array||t instanceof Uint8ClampedArray))throw at("JXL_INPUT","Pixels are a Uint8Array or Uint8ClampedArray of RGBA bytes.");if(t.length!==n*e*4)throw at("JXL_INPUT","Pixels are width * height * 4 bytes: straight (not premultiplied) RGBA, row by row.")}(n,e,o),function(t){const n=function*(){let e,o;for(;!(e=G(()=>t.next(n.hurry))).done;)yield o=e.value;return o<1&&(yield 1),n.bytes=function(t){if(t.length>B.bytes)throw at("JXL_SIZE","The encoded picture exceeds 16 MiB.");return t}(e.value)}();return n.bytes=null,n.hurry=!1,n}(function*(n,e,o,r,f,a){const u=E(n,e,o);if(r<100){if(!u.palette)return yield*_(n,e,o,{quality:r,shape:u,colorSpace:f});const s=yield*t(L(n,e,o,{shape:u,colorSpace:f}),0,2);let i;try{i=yield*t(_(n,e,o,{quality:r,shape:u,colorSpace:f}),1,2)}catch(t){if(!(t instanceof RangeError)||t.code)throw t;i=s}return s.length<=i.length?s:i}if(a<2)return yield*L(n,e,o,{shape:u,colorSpace:f});let h=yield*t(L(n,e,o,{shape:u,colorSpace:f}),0,2);try{const r=yield*t(function*(t,n,e,o,r,f){function*a(t){const{B:c,leaves:f,et:a}=_(t),p=u>=3?[{type:"rct",Y:0,Z:6}]:[],M=new Y(256);s(M,n,e,o.colour,o.alpha,{colorSpace:r}),i(M,{alpha:o.alpha});const A=new Y(4096);A.write(1,1),A.write(1,1);const g=C(A,x(A,c),a,t=>f.indexOf(t));v(A,{$:!0,tt:p});const m=t.map(t=>t.leaves.map(t=>g[f.indexOf(t)+1].code)),b=(n,e,o,r)=>{const s=t[e];6===s.leaves[0].G?z(n,m[e],w[e],o,r,0,s.lt):q(n,m[e][0],w[e],o,r,s.leaves[0])},U=[];if(h.A){if(d(0,(t,n)=>{for(let e=0;e<u;e++)b(A,e,t,n)}),yield B())return null;U.push(A.finish())}else{U.push(A.finish());for(let t=0;t<h.p*h.M+1;t++)U.push(new Uint8Array(0));for(let t=0;t<y;t++)if(d(t,(t,n)=>{const e=new Y(t*n*u+64);v(e,{$:!0,tt:[]});for(let o=0;o<u;o++)b(e,o,t,n);U.push(e.finish())}),yield B())return null}return l(M,U)}const{channels:u}=o,h=c(n,e),y=h.i*h.u,w=Array.from({length:u},()=>new Int16Array(65536)),p=(e,o,r,s)=>{for(let i=0;i<s;i++){let s=4*((o+i)*n+e),c=i*r;for(let n=0;n<r;n++,s+=4,c++)if(u>=3){const n=t[s],e=t[s+1],o=t[s+2],r=n-o,i=o+(r>>1),l=e-i;w[0][c]=i+(l>>1),w[1][c]=r,w[2][c]=l,4===u&&(w[3][c]=t[s+3])}else w[0][c]=t[s],2===u&&(w[1][c]=t[s+3])}},d=(t,o)=>{const r=t%h.i*Z,s=(t/h.i|0)*Z,i=Math.min(Z,n-r),c=Math.min(Z,e-s);p(r,s,i,c),o(i,c)},M=Math.min(n,32),A=Math.min(e,32),g=[V,K].map(t=>({G:t,et:w.map(()=>new Uint32Array(nt))}));for(const t of[0,.5,1]){p(Math.floor((n-M)*t),Math.floor((e-A)*t),M,A);for(const t of g)for(let n=0;n<u;n++)q(null,t.et[n],w[n],M,A,b(t.G))}const m=w.map((t,n)=>b(g[R(g[1].et[n])<R(g[0].et[n])?1:0].G)),I=st.length+1,T=Int32Array.from({length:I},(t,n)=>n),E=w.map(()=>new Uint32Array(nt)),L=w.map(()=>Array.from({length:I},()=>new Uint32Array(nt)));let N=0;for(let t=0;t<y;t++)if(d(t,(t,n)=>{for(let e=0;e<u;e++)q(null,E[e],w[e],t,n,m[e]),z(null,L[e],w[e],t,n,0,T)}),yield++N/(2*y))return null;const P=w.map((t,n)=>{const e={ft:R(E[n]),leaves:[m[n]],et:[E[n]],cuts:[]},o=ht(L[n]),r=R(o);return r<e.ft?{ft:r,leaves:[b(6)],et:[o],cuts:[]}:e}),X=f<3?P:P.map((t,n)=>{const e=L[n].map(t=>t.some(t=>t)),o=new Float64Array(I+1).fill(1/0),r=new Int32Array(I+1);o[0]=0;for(let t=1;t<=I;t++){const s=new Uint32Array(nt);let i=0;for(let c=t-1;c>=0;c--){if(e[c]){const t=L[n][c];for(let n=0;n<nt;n++)s[n]+=t[n];i=R(s)}const l=o[c]+i+24;l<o[t]&&(o[t]=l,r[t]=c)}}if(!(o[I]<t.ft))return t;const s=[];for(let t=I;t>0;t=r[t])s.unshift([r[t],t]);return{ft:o[I],leaves:s.map(()=>b(6)),et:s.map(([t,e])=>ht(L[n].slice(t,e))),cuts:s.slice(0,-1).map(([,t])=>st[t-1]),lt:Int32Array.from({length:I},(t,n)=>s.findIndex(([t,e])=>n>=t&&n<e))}}),J=[P,X].filter((t,n)=>n?t.some((t,n)=>t!==P[n]):t.some((t,n)=>t.leaves[0]!==m[n]));if(!J.length)return null;const _=t=>({B:S(t.map(t=>((t,n)=>{const e=(o,r)=>{if(o===r)return t[o];const s=o+r>>1;return U(15,n[s],e(s+1,r),e(o,s))};return e(0,t.length-1)})(t.leaves,t.cuts))),leaves:t.flatMap(t=>t.leaves),et:t.flatMap(t=>t.et)}),G=t=>{const{B:n,leaves:e,et:o}=_(t),r=new Y(4096),s=C(r,x(r,n),o,t=>e.indexOf(t));let i=r.nt;return o.forEach((t,n)=>{const{I:e}=s[n+1].code;for(let n=0;n<t.length;n++)t[n]&&(i+=t[n]*(e[n]+ut(n)))}),i};let O=J;if(J.length>1){const[t,n]=J.map(G),e=27*(h.A?1:y+1)+8;n+e<=t?O=[J[1]]:t+e<=n&&(O=[J[0]])}let j=0;const B=()=>.5+ ++j/(2*O.length*y);let k=null;for(const t of O){const n=yield*a(t);if(!n)return k;(!k||n.length<k.length)&&(k=n)}return k}(n,e,o,u.palette?{...u,palette:null}:u,f,a),1,2);r&&r.length<h.length&&(h=r)}catch(t){if(!(t instanceof RangeError)||t.code)throw t}return h}(n,e,o,f,a,u))}function R(t){const n=y(t),e=new Y(128);w(e,n);let o=e.nt;for(let e=0;e<t.length;e++)t[e]&&(o+=t[e]*(n.I[e]+ut(e)));return o}const B=Object.freeze({bytes:16777216,pixels:24e6,edge:16384}),k=[1];for(let t=1;t<=32;t++)k.push(2*k[t-1]);class Y{constructor(t=4096){this.bytes=new Uint8Array(t),this.at=0,this.ut=0,this.pending=0}write(t,n){if(!(n>=0&&n<k[t]))throw new Error("bit write out of range: "+t+" bits, "+n);let e=this.ut+n*(1<<this.pending),o=this.pending+t;this.at+5>=this.bytes.length&&this.grow();const r=this.bytes;for(;o>=8;)r[this.at++]=255&e,e=Math.floor(e/256),o-=8;this.ut=e,this.pending=o}t(t,n){for(let e=0;e<4;e++){const[o,r]=t[e];if(n>=r&&n-r<k[o])return this.write(2,e),void(o&&this.write(o,n-r))}throw new Error("U32 value out of range: "+n)}o(){this.pending&&(this.at+1>=this.bytes.length&&this.grow(),this.bytes[this.at++]=this.ut,this.ut=0,this.pending=0)}get nt(){return 8*this.at+this.pending}grow(t=0){const n=B.bytes+64;if(this.at+t+16>n)throw Object.assign(new Error("The encoded picture exceeds 16 MiB."),{code:"JXL_SIZE"});const e=new Uint8Array(Math.min(n,Math.max(2*this.bytes.length,this.at+t+16)));e.set(this.bytes.subarray(0,this.at)),this.bytes=e}append(t){if(this.at+t.at+8>=this.bytes.length&&this.grow(t.at+8),this.pending)for(let n=0;n<t.at;n++)this.write(8,t.bytes[n]);else this.bytes.set(t.bytes.subarray(0,t.at),this.at),this.at+=t.at;t.pending&&this.write(t.pending,t.ut)}finish(){const t=this.at+(this.pending?1:0),n=this.bytes.slice(0,t);return this.pending&&(n[this.at]=this.ut),n}}const Z=256,D=[1,2,3,4,0,5,17,6,16,7,8,9,10,11,12,13,14,15],F=[2,4,3,2,2,4],Q=[0,7,3,2,1,15],H=[0,0,0],K=3,V=5,W=p(4),$=Object.freeze({J:224,minLength:7,_:W}),tt=p(0),nt=257,et=(t,n)=>t+n+(t>n?1:0)>>1,ot=1024,rt=8192,st=[-500,-392,-255,-191,-127,-95,-63,-47,-31,-23,-15,-11,-7,-4,-3,-1,0,1,3,5,7,11,15,23,31,47,63,95,127,191,255,392,500],it=Int8Array.from({length:1003},(t,n)=>st.filter(t=>t<n-501).length),ct=Int32Array.from({length:64},(t,n)=>Math.floor(16777216/(n+1))),lt=(t,n)=>{const e=Math.max(0,26-Math.clz32(t+1));return 4+(n*ct[t>>e]>>e)},ft=new Int32Array(st.length+1),at=(t,n)=>Object.assign(new Error(n),{code:t}),ut=t=>Math.max(0,t<224?t-1:t-236),ht=t=>{const n=new Uint32Array(nt);for(const e of t)for(let t=0;t<nt;t++)n[t]+=e[t];return n};export{B as LIMITS,O as encode,j as encodeSteps};
1
+ /*! Rapier JXL 2.1.0 | MIT License Copyright (c) 2026 rapier.website Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
2
+ const t=Object.freeze({bytes:16777216,pixels:24e6,edge:16384}),n=[1];for(let t=1;t<=32;t++)n.push(2*n[t-1]);class e{constructor(t=4096){this.bytes=new Uint8Array(t),this.at=0,this.t=0,this.pending=0}write(t,e){if(!(e>=0&&e<n[t]))throw new Error("bit write out of range: "+t+" bits, "+e);let o=this.t+e*(1<<this.pending),r=this.pending+t;this.at+5>=this.bytes.length&&this.grow();const s=this.bytes;for(;r>=8;)s[this.at++]=255&o,o=Math.floor(o/256),r-=8;this.t=o,this.pending=r}o(t,e){for(let o=0;o<4;o++){const[r,s]=t[o];if(e>=s&&e-s<n[r])return this.write(2,o),void(r&&this.write(r,e-s))}throw new Error("U32 value out of range: "+e)}i(){this.pending&&(this.at+1>=this.bytes.length&&this.grow(),this.bytes[this.at++]=this.t,this.t=0,this.pending=0)}get u(){return 8*this.at+this.pending}grow(n=0){const e=t.bytes+64;if(this.at+n+16>e)throw Object.assign(new Error("The encoded picture exceeds 16 MiB."),{code:"JXL_SIZE"});const o=new Uint8Array(Math.min(e,Math.max(2*this.bytes.length,this.at+n+16)));o.set(this.bytes.subarray(0,this.at)),this.bytes=o}append(t){if(this.at+t.at+8>=this.bytes.length&&this.grow(t.at+8),this.pending)for(let n=0;n<t.at;n++)this.write(8,t.bytes[n]);else this.bytes.set(t.bytes.subarray(0,t.at),this.at),this.at+=t.at;t.pending&&this.write(t.pending,t.t)}finish(){const t=this.at+(this.pending?1:0),n=this.bytes.slice(0,t);return this.pending&&(n[this.at]=this.t),n}}function*o(t,n,e){let o,r;for(;!(o=t.next(r)).done;)r=yield(n+o.value)/e;return o.value}function r(t){return t>=0?2*t:2*-t-1}function s(t){return 31-Math.clz32(t)}function c(t){return t<=1?0:32-Math.clz32(t-1)}const i=(t,n)=>Object.assign(new Error(n),{code:t});function l(n){if(n>t.bytes)throw i("JXL_SIZE","The encoded picture exceeds 16 MiB.")}function f(t){try{return t()}catch(t){if(t instanceof RangeError&&!t.code)throw i("JXL_MEMORY","Not enough memory for this picture.");throw t}}const a=256;function u(t,n){t.o([[9,1],[13,1],[18,1],[30,1]],n)}function h(t,n,e,o,r,{xyb:s=!1,orientation:c=1,colorSpace:i}={}){t.write(16,2815),t.write(1,0),u(t,e),t.write(3,0),u(t,n),t.write(1,0);const l=1!==c;t.write(1,l?1:0),l&&t.write(6,c-1),t.write(4,8),r?t.write(3,5):t.write(2,0),t.write(1,s?1:0),3===o&&"display-p3"===i?t.write(21,903568):3===o?t.write(1,1):t.write(15,14100),l&&t.write(1,1),t.write(2,0),t.write(1,1),t.i()}function y(t,{alpha:n,shift:e=1}){t.write(9,8),n&&t.write(2,0),t.write(2,e),function(t,n){t.write(n?7:5,0),t.write(11,1)}(t,n)}function w(t,n,e=256){const o=Math.ceil(t/e),r=Math.ceil(n/e);return{p:o,M:r,A:Math.ceil(t/(8*e)),m:Math.ceil(n/(8*e)),U:1===o&&1===r}}function p(t,n){const e=n.map(t=>t.length);!function(t,n){t.write(1,0),t.i();for(const e of n)t.o([[10,0],[14,1024],[22,17408],[30,4211712]],e);t.i()}(t,e);const o=t.finish(),r=o.length+e.reduce((t,n)=>t+n,0);l(r);const s=new Uint8Array(r);s.set(o);let c=o.length;for(const t of n)s.set(t,c),c+=t.length;return s}const d=[1,2,3,4,0,5,17,6,16,7,8,9,10,11,12,13,14,15],M=[2,4,3,2,2,4],A=[0,7,3,2,1,15];function g(t,n){const e=new Uint8Array(t.length),o=[];for(let n=0;n<t.length;n++)t[n]>0&&o.push(n);if(!o.length)return e;if(1===o.length)return e[o[0]]=1,e;for(let r=1;;r*=2){const s=o.map(n=>({w:Math.max(t[n],r),I:n,l:null,r:null})).sort((t,n)=>t.w-n.w||t.I-n.I),c=[];let i=0,l=0;const f=()=>i<s.length&&(l>=c.length||s[i].w<=c[l].w)?s[i++]:c[l++];for(;s.length-i+(c.length-l)>1;){const t=f(),n=f();c.push({w:t.w+n.w,I:-1,l:t,r:n})}const a=[[f(),0]];let u=0;for(;a.length;){const[t,n]=a.pop();t.I>=0?(e[t.I]=n,n>u&&(u=n)):a.push([t.l,n+1],[t.r,n+1])}if(u<=n)return e}}function m(t,n,e,o,r,s){const c=[];for(;c.push(o&r),o>>=s;)o--;for(let o=c.length-1;o>=0;o--)t.push(e),n.push(c[o])}function b(t,n){let e=0;for(let o=0;o<n;o++)e=e<<1|1&t,t>>=1;return e}function U(t){const n=new Uint32Array(17),e=new Uint32Array(17),o=new Uint16Array(t.length);for(const e of t)n[e]++;n[0]=0;for(let t=1,o=0;t<=16;t++)o=o+n[t-1]<<1,e[t]=o;for(let n=0;n<t.length;n++)t[n]&&(o[n]=b(e[t[n]]++,t[n]));return o}function I(t){const n=[];for(let e=0;e<t.length;e++)t[e]>0&&n.push(e);const e=n.length,o=n[e-1]+1||1,r=e<=4?new Uint8Array(o):g(t,15).subarray(0,o);let s=0;if(e<=4){n.sort((n,e)=>t[e]-t[n]||n-e),s=4===e&&t[n[0]]>t[n[2]]+t[n[3]]?1:0;const o=e<2?[0]:2===e?[1,1]:3===e?[1,2,2]:s?[1,2,3,3]:[2,2,2,2];n.forEach((t,n)=>{r[t]=o[n]}),n.sort((t,n)=>r[t]-r[n]||t-n)}return{S:o,C:r,T:U(r),v:e&&e<=4?n:null,q:s}}function S(t,n){if(n.S<=1)return;if(n.v){const e=s(n.S-1)+1;t.write(2,1),t.write(2,n.v.length-1);for(const o of n.v)t.write(e,o);return void(4===n.v.length&&t.write(1,n.q))}const e=n.C,o=[],r=[];let c=e.length-1;for(;c>0&&!e[c];)c--;let i=8;for(let t=0;t<=c;){const n=e[t];let s=1;for(;t+s<=c&&e[t+s]===n;)s++;let l=s;if(n&&n!==i&&(o.push(n),r.push(0),l--,i=n),l<3)for(let t=0;t<l;t++)o.push(n),r.push(0);else m(o,r,n?16:17,l-3,n?3:7,n?2:3);t+=s}const l=new Uint32Array(18);for(const t of o)l[t]++;let f=0;for(const t of l)t&&f++;1===f&&(l[o[0]?0:1]=l[o[0]]);const a=g(l,5),u=U(a);let h=18;for(;h>0&&!a[d[h-1]];)h--;t.write(2,0);for(let n=0;n<h;n++){const e=a[d[n]];t.write(M[e],A[e])}for(let n=0;n<o.length;n++){const e=o[n];t.write(a[e],u[e]),16===e?t.write(2,r[n]):17===e&&t.write(3,r[n])}}function x(t,n=0,e=0){return{split:t,L:n,X:e,J:1<<t}}function C(t,n,e=15){t.write(c(e+1),n.split),n.split!==e&&(t.write(c(n.split+1),n.L),t.write(c(n.split-n.L+1),n.X))}function T(t,n,e){if(n<t.J)return e[0]=n,e[1]=0,void(e[2]=0);const o=s(n),r=n-(1<<o),c=o-t.L-t.X;e[0]=t.J+(o-t.split<<t.L+t.X|r>>o-t.L<<t.X|r&(1<<t.X)-1),e[1]=c,e[2]=n>>t.X&(1<<c)-1}function v(t,n,e,o=0){T(t,n,E),e[o+E[0]]++}const E=[0,0,0];function q(t,n,e,o,r=0){T(e,o,E);const s=r+E[0];t.write(n.C[s],n.T[s]),E[1]&&t.write(E[1],E[2])}function L(t,{N:n=null,_:e,P:o}){t.write(1,n?1:0),n&&(t.o([[0,224],[0,512],[0,4096],[15,8]],n.G),t.o([[0,3],[0,4],[2,5],[8,9]],n.minLength),C(t,n.O,8)),e.length>1&&function(t,n){let e=0;for(const t of n)e=Math.max(e,t);const o=e?c(e+1):0;if(o<=3){if(t.write(1,1),t.write(2,o),o)for(const e of n)t.write(o,e);return}t.write(1,0),t.write(1,0);const r=x(8),s=x(4),i=n.length>=64,l=new Uint32Array(i?257:e+1),f=[];for(let t=0;t<n.length;){let e=1;for(;i&&t+e<n.length&&n[t+e]===n[t];)e++;if(e>=8)f.push([n[t],e-1]),l[n[t]]++,v(s,e-1-7,l,224),t+=e;else{for(let o=0;o<e;o++)f.push([n[t],0]),l[n[t]]++;t+=e}}const a=I(l);if(!i){L(t,{_:new Uint8Array(1),P:[{config:r,code:a}]});for(const[n]of f)q(t,a,r,n);return}const u=new Uint32Array(1);u[0]=1,L(t,{N:{G:224,minLength:7,O:s},_:new Uint8Array([1,0]),P:[{config:x(0),code:I(u)},{config:r,code:a}]});for(const[n,e]of f)q(t,a,r,n),e&&q(t,a,s,e-7,224)}(t,e),t.write(1,1);for(const n of o)C(t,n.config,15);for(const n of o){const e=n.code.S-1;if(e){const n=s(e);t.write(1,1),t.write(4,n),t.write(n,e-(1<<n))}else t.write(1,0)}for(const n of o)S(t,n.code)}const X=3,J=5,N=x(4),_=Object.freeze({G:224,minLength:7,O:N}),P=x(0),z=257;function G(t,n=0,e=1){return{R:t,offset:n,j:e,context:-1}}function O(t,n,e,o){return{Z:t,B:n,left:e,right:o}}function R(t,n){const e=(o,r)=>{if(o===r)return n?t[o].k:t[o];const s=o+r>>1;return O(n,n?t[s].Y:s,e(s+1,r),e(o,s))};return e(0,t.length-1)}function j(t){return R(t,0)}function Z(t,n){const e=[n],o=[],s=[];for(const t of e){if(t.left){o.push(t.Z+1,r(t.B)),e.push(t.left,t.right);continue}t.context=s.length,s.push(t);const n=1===t.j?0:31-Math.clz32(t.j&-t.j);o.push(0,t.R,r(t.offset),n,(t.j>>n)-1)}const c=new Uint32Array(64);for(const t of o)v(P,t,c);const i=I(c);L(t,{_:new Uint8Array(6),P:[{config:P,code:i}]});for(const n of o)q(t,i,P,n);return s}function B(t,n){const e=[[3,0],[6,8],[10,72],[13,1096]];if("rct"===n.type)t.write(2,0),t.o(e,n.D),t.o([[0,6],[2,0],[4,2],[6,10]],n.F??6);else if("palette"===n.type)t.write(2,1),t.o(e,n.D),t.o([[0,1],[0,3],[0,4],[13,1]],n.H),t.o([[8,0],[10,256],[12,1280],[16,5376]],n.K),t.o([[0,0],[8,1],[10,257],[16,1281]],n.V??0),t.write(4,n.R??0);else{if("squeeze"!==n.type)throw new Error("unknown transform "+n.type);{t.write(2,2);const o=n.W??[];t.o([[0,0],[4,1],[6,9],[8,41]],o.length);for(const n of o)t.write(1,n.$?1:0),t.write(1,n.tt?1:0),t.o(e,n.D),t.o([[0,1],[0,2],[0,3],[4,4]],n.H)}}}function k(t,{nt:n=!0,et:e=[]}={}){t.write(1,n?1:0),t.write(1,1),t.o([[0,0],[0,1],[4,2],[8,18]],e.length);for(const n of e)B(t,n)}function Y(t,n,e,o=t=>t.context){const r=new Uint8Array(n.length+1);for(const t of n)r[t.context]=o(t)+1;const s=new Uint32Array(2);s[1]=1;const c=[{config:P,code:I(s)}],i=Math.max(...r);for(let t=0;t<i;t++)c.push({config:P,code:I(e[t])});return L(t,{N:_,_:r,P:c}),c}function D(t,n,e,o,s,c){const i=c.R,l=c.offset,f=c.j,a=P,u=N;let h=0;const y=(e,o=a,r=0)=>{t?q(t,n,o,e,r):v(o,e,n,r)},w=()=>{if(h){if(h>=8)y(0),y(h-7-1,u,224);else for(let t=0;t<h;t++)y(0);h=0}},p=(t,n)=>{const o=e[t];let s;1===f?s=o-n-l:(s=Math.round((o-n-l)/f),e[t]=n+l+s*f),0!==s?(w(),y(r(s))):h++};for(let t=0,n=0;t<s;t++)for(let r=0;r<o;r++,n++){let s;if(0===i)s=0;else{const c=r?e[n-1]:t?e[n-o]:0,l=t?e[n-o]:c;if(1===i)s=c;else if(2===i)s=l;else if(3===i)s=(c+l)/2|0;else{const f=c+l-(r&&t?e[n-o-1]:c);if(5===i){const t=c<l?c:l,n=c<l?l:c;s=f<t?t:f>n?n:f}else{if(4!==i)throw new Error("predictor "+i+" is not coded here");s=Math.abs(f-c)<Math.abs(f-l)?c:l}}}p(n,s)}w()}function F(t,n,e,{palette:o=!0}={}){const r=n*e;let s=!0,c=!0;for(let n=0,e=0;e<r&&(255===t[n+3]||(s=!1,c))&&(t[n]===t[n+1]&&t[n]===t[n+2]||(c=!1,s));e++,n+=4);const i=c?1:3,l=!s,f=i+(l?1:0),a=n=>c?l?t[n]+256*t[n+3]:t[n]:t[n]+256*t[n+1]+65536*t[n+2]+(l?16777216*t[n+3]:0),u=new Map;let h=null;for(let t=0,n=0;o&&n<r;n++,t+=4){const n=a(t);if(0!==n&&!u.has(n)&&(u.set(n,1),u.size>=2048))break}if(o&&u.size<2048){const t=[...u.keys()],n=(t,n)=>t>>>8*n&255,e=t=>(.299*n(t,0)+.587*n(t,1)+.114*n(t,2)+.01)*(4===f?n(t,3):1);t.sort((t,n)=>e(t)-e(n));const o=new Map([[0,0]]);t.forEach((t,n)=>o.set(t,n+1)),h={colours:[0,...t],index:o,key:a,byte:n}}return{colour:i,alpha:l,channels:f,palette:h}}function*Q(t,n,e,{shape:r=F(t,n,e),colorSpace:s}={}){let c,i;const l=r.palette?[r,{...r,palette:null}]:[r];for(let r=0;r<l.length;r++)try{const i=yield*o(H(t,n,e,l[r],s),r,l.length);(!c||i.length<c.length)&&(c=i)}catch(t){if("JXL_SIZE"!==t.code)throw t;i=t}if(!c)throw i;return c}function*H(t,n,o,r,s){const{channels:c,palette:i}=r,l=w(n,o),f=i?2:c,u=Array.from({length:f},()=>G(J)),d=j(u),M=Array.from({length:f},()=>new Int16Array(65536)),A=(e,o,r,s)=>{for(let l=0;l<s;l++){let s=4*((o+l)*n+e),f=l*r;for(let n=0;n<r;n++,s+=4,f++)if(i)M[0][f]=i.index.get(i.key(s));else if(c>=3){const n=t[s],e=t[s+1],o=t[s+2],r=n-o,i=o+(r>>1),l=e-i;M[0][f]=i+(l>>1),M[1][f]=r,M[2][f]=l,4===c&&(M[3][f]=t[s+3])}else M[0][f]=t[s],2===c&&(M[1][f]=t[s+3])}};let g=null;if(i){const t=i.colours.length;g=new Int16Array(t*c),i.colours.forEach((n,e)=>{for(let o=0;o<c;o++)g[o*t+e]=i.byte(n,o)})}const m=t=>u[i?l.U?1:0:t],b=i?1:c,U=l.p*l.M,x=2*U,C=(t,e)=>{const r=t%l.p*a,s=(t/l.p|0)*a,c=Math.min(a,n-r),i=Math.min(a,o-s);A(r,s,c,i),e(c,i)};let T=0;if(!i){const t=t=>{const n=I(t),o=new e(128);S(o,n);let r=o.u;for(let e=0;e<t.length;e++)t[e]&&(r+=t[e]*(n.C[e]+Math.max(0,e<224?e-1:e-236)));return r},r=Math.min(n,32),s=Math.min(o,32),i=[J,X].map(t=>({R:t,ot:u.map(()=>new Uint32Array(z))}));for(const t of[0,.5,1]){A(Math.floor((n-r)*t),Math.floor((o-s)*t),r,s);for(const t of i)for(let n=0;n<c;n++)D(null,t.ot[n],M[n],r,s,G(t.R))}u.forEach((n,e)=>{const o=i.map(n=>t(n.ot[e])),r=o[1]<o[0]?1:0;n.R=i[r].R})}const v=i?[{type:"palette",D:0,H:c,K:i.colours.length}]:c>=3?[{type:"rct",D:0,F:6}]:[],E=u.map(()=>new Uint32Array(z)),q=t=>E[u.indexOf(t)];g&&D(null,q(u[0]),g,i.colours.length,c,u[0]);for(let t=0;t<U;t++)C(t,(t,n)=>{for(let e=0;e<b;e++)D(null,q(m(e)),M[e],t,n,m(e))}),yield++T/x;const L=new e(256);h(L,n,o,r.colour,r.alpha,{colorSpace:s}),y(L,{alpha:r.alpha});const N=new e(4096);N.write(1,1),N.write(1,1);const _=Z(N,d),P=Y(N,_,E,t=>u.indexOf(t)),O=t=>P[u.indexOf(t)+1].code;k(N,{nt:!0,et:v}),g&&D(N,O(u[0]),g,i.colours.length,c,u[0]);const R=[];if(l.U)C(0,(t,n)=>{for(let e=0;e<b;e++)D(N,O(m(e)),M[e],t,n,m(e))}),yield 1,R.push(N.finish());else{R.push(N.finish());for(let t=0;t<l.A*l.m+1;t++)R.push(new Uint8Array(0));for(let t=0;t<U;t++)C(t,(t,n)=>{const o=new e(t*n*b+64);k(o,{nt:!0,et:[]});for(let e=0;e<b;e++)D(o,O(m(e)),M[e],t,n,m(e));R.push(o.finish())}),yield++T/x}return p(L,R)}const K=(t,n)=>t+n+(t>n?1:0)>>1;function V(t,n,e){const o=t>=n&&n>=e?1:t<=n&&n<=e?-1:0;if(!o)return 0;let r=(4*(t*=o)-3*(e*=o)-(n*=o)+6)/12|0;return r-(1&r)>2*(t-n)&&(r=2*(t-n)+1),r+(1&r)>2*(n-e)&&(r=2*(n-e)),o*r}function W(t,n){const{w:e,h:o,data:r}=t,s=n?e:o,c=s+1>>1,i=s-c,l=n?c:e,f=n?o:c,a=n?i:e,u=n?o:i,h=new Int16Array(l*f),y=new Int16Array(a*u),w=n?1:e;for(let t=0;t<f;t++)for(let o=0;o<l;o++){const c=n?o:t,f=n?t*e+2*o:2*t*e+o;if(c===i){h[t*l+o]=r[f];continue}const u=r[f],p=r[f+w],d=K(u,p),M=c+1<i?K(r[f+2*w],r[f+3*w]):1&s?r[f+2*w]:d;h[t*l+o]=d,y[t*a+o]=u-p-V(c?r[f-w]:d,d,M)}const p=(e,o,r)=>({w:o,h:r,rt:t.rt+ +n,st:t.st+!n,data:e});return[p(h,l,f),p(y,a,u)]}function $(t){const n=[],e=t.length;let o=t[0].w,r=t[0].h;for(e>2&&t[1].w===o&&t[1].h===r&&(n.push({$:!0,tt:!1,D:1,H:2}),n.push({$:!1,tt:!1,D:1,H:2})),!(o>r)&&r>8&&(n.push({$:!1,tt:!0,D:0,H:e}),r=r+1>>1);o>8||r>8;)o>8&&(n.push({$:!0,tt:!0,D:0,H:e}),o=o+1>>1),r>8&&(n.push({$:!1,tt:!0,D:0,H:e}),r=r+1>>1);return n}const tt=1024,nt=8192;function*et(t,n,o,{quality:r=90,shape:s=F(t,n,o,{palette:!1}),colorSpace:c}={}){const i=function(t){return t>=100?0:t>=30?.1+.09*(100-t):53/3e3*t*t-1.15*t+25}(r);if(!(i>0))throw new Error("lossy encoding needs a quality below 100");const{colour:l,alpha:f,channels:a}=s,u=n*o,d=Array.from({length:a},()=>new Int16Array(u));for(let n=0,e=0;e<u;e++,n+=4){if(3===l){const o=t[n],r=t[n+1],s=t[n+2],c=o-s,i=s+(c>>1),l=r-i;d[0][e]=i+(l>>1),d[1][e]=c,d[2][e]=l}else d[0][e]=t[n];f&&(d[a-1][e]=t[n+3])}const M=d.map((t,e)=>({w:n,h:o,rt:0,st:0,data:t,component:3===l?e:0===e?0:3})),A=1===n&&o>tt&&3===l,g=A?$(M).filter(t=>!t.$):1!==n&&1!==o||3!==l?[]:$(M),m=function(t,n=$(t)){const e=t.map(t=>({...t,level:0,ct:!1}));for(const t of n){const n=t.D+t.H-1,o=t.tt?n+1:e.length;for(let r=t.D;r<=n;r++){const[n,s]=W(e[r],t.$),c=e[r].level+1;e[r]={...n,level:c,ct:e[r].ct,component:e[r].component},e.splice(o+(r-t.D),0,{...s,level:c,ct:!0,component:e[r].component})}}return e}(M,g.length?g:void 0),b=t=>t.ct?0:J,U=t=>function(t,n,e,o){let r=Math.min(16,n+e);if(r>0&&r--,3===t)return 1;const s=.25*function(t){let n=1;for(let e=0;e<24;e++)n=(4*n+t/(n*n*n*n))/5;return t*n}(o),c=1<<r,i=1===t||2===t?.35*s*Math.max(.5,1024/c):.35*s*1.1*(163.84/c);return Math.max(1,Math.floor(i))}(t.component,t.rt+(A&&t.component>0&&t.component<3?1:0),t.st,i),I=[...3===l?[{type:"rct",D:0,F:6}]:[],{type:"squeeze",W:g}],S=w(n,o,tt),x=S.A*S.m,C=S.p*S.M;let T=0;for(;T<m.length&&m[T].w<=tt&&m[T].h<=tt;)T++;const v=(t,n,e,o)=>{const r=n>>t.rt,s=e>>t.st;return{x:r,y:s,w:Math.min(t.w,r+(o>>t.rt))-r,h:Math.min(t.h,s+(o>>t.st))-s}},E=[{index:0,Y:0,it:[]}];for(let t=0;t<T;t++)E[0].it.push({c:t,rect:{x:0,y:0,w:m[t].w,h:m[t].h}});if(!S.U){for(let t=0;t<x;t++){const n=t%S.A,e=t/S.A|0,o={index:1+t,Y:1+x+t,it:[]};for(let t=T;t<m.length;t++){const r=m[t];if(Math.min(r.rt,r.st)<3)continue;const s=v(r,n*nt,e*nt,nt);s.w>0&&s.h>0&&o.it.push({c:t,rect:s})}E.push(o)}for(let t=0;t<C;t++){const n=t%S.p,e=t/S.p|0,o={index:2+x+t,Y:1+3*x+17+t,it:[]};for(let t=T;t<m.length;t++){const r=m[t];if(Math.min(r.rt,r.st)>2)continue;const s=v(r,n*tt,e*tt,tt);s.w>0&&s.h>0&&o.it.push({c:t,rect:s})}E.push(o)}}for(const t of E)for(const n of t.it){const t=m[n.c];n.lt=G(b(t),0,U(t)),n.lt.channel=n.c}const q=E.filter(t=>t.it.length),L=1===q.length?j(q[0].it.map(t=>t.lt)):function(t){return R(t,1)}(q.map(t=>({Y:t.Y,k:j(t.it.map(t=>t.lt))}))),X=new Int16Array(1048576),N=t=>{const n=m[t.c],e=t.rect;if(e.w===n.w&&e.h===n.h)return n.data;for(let t=0;t<e.h;t++)X.set(n.data.subarray((e.y+t)*n.w+e.x,(e.y+t)*n.w+e.x+e.w),t*e.w);return X},_=[...new Set(E.flatMap(t=>t.it.map(t=>t.c)))].sort((t,n)=>t-n),P=new Map(_.map((t,n)=>[t,n])),O=_.map(()=>new Uint32Array(z)),B=1+2*E.length;let Q=1;yield Q/B;for(const t of E){for(const n of t.it)D(null,O[P.get(n.c)],N(n),n.rect.w,n.rect.h,n.lt);yield++Q/B}const H=new e(256);h(H,n,o,l,f,{colorSpace:c}),y(H,{alpha:f,shift:n>256||o>256?3:1});const K=Array.from({length:S.U?1:2+x+C},()=>null),V=K[0]=new e(65536);V.write(1,1),V.write(1,1);const et=Y(V,Z(V,L),O,t=>P.get(t.channel));k(V,{nt:!0,et:I});for(const t of E){let n=K[t.index];n||(n=K[t.index]=new e(4096),t.it.length&&k(n,{nt:!0,et:[]}));for(const e of t.it)D(n,et[P.get(e.c)+1].code,N(e),e.rect.w,e.rect.h,e.lt);yield++Q/B}return p(H,function(t){return t.map(t=>t?t.finish():new Uint8Array(0))}(K))}const ot=[-500,-392,-255,-191,-127,-95,-63,-47,-31,-23,-15,-11,-7,-4,-3,-1,0,1,3,5,7,11,15,23,31,47,63,95,127,191,255,392,500],rt=Int8Array.from({length:1003},(t,n)=>ot.filter(t=>t<n-501).length),st=Int32Array.from({length:64},(t,n)=>Math.floor(16777216/(n+1))),ct=(t,n)=>{const e=Math.max(0,26-Math.clz32(t+1));return 4+(n*st[t>>e]>>e)},it=[12,13].map(t=>Int32Array.from({length:2048},(n,e)=>ct(e,t))),lt=(t,n)=>t<2048?it[n-12][t]:ct(t,n),ft=new Int32Array(ot.length+1);let at;function ut(t,n,e,o,s,c=0,i=ft,l,f){const a=o+2,u=at&&at[0].length>=2*a?at:Array.from({length:6},(t,n)=>new Int32Array(n<5?2*a:8));at=null;for(const t of u)t.fill(0);const[h,y,w,p,d,M]=u;let A=0;const g=(e,o,r=P,s=0)=>{t?q(t,n[e],r,o,s):v(r,o,n[e],s)},m=()=>{if(A){if(A>_.minLength)g(M[0],0),g(M[1],A-_.minLength-1,_.O,_.G);else for(let t=0;t<A;t++)g(M[t],0);A=0}};for(let t=0,n=0;t<s;t++){const s=1&t?0:a,u=1&t?a:0;for(let a=0;a<o;a++,n++){const b=a?e[n-1]:t?e[n-o]:0,U=t?e[n-o]:b,I=a+1<o&&t?e[n-o+1]:U,S=u+a,x=a<o-1?S+1:S,C=a?S-1:S;let T=lt(h[S]+h[x]+h[C],13),v=lt(y[S]+y[x]+y[C],12),E=lt(w[S]+w[x]+w[C],12),q=lt(p[S]+p[x]+p[C],12);const L=8*U,X=8*b,J=8*I,N=a?d[s+a-1]:0,_=d[S],P=d[C],z=d[x],G=_+N;let O=N;Math.abs(_)>Math.abs(O)&&(O=_),Math.abs(P)>Math.abs(O)&&(O=P),Math.abs(z)>Math.abs(O)&&(O=z);const R=i[rt[O<-501?0:O>501?1002:O+501]];f&&(f[n]=O);const j=X+J-L,Z=L-(16*(G+z)>>5),B=X-(10*(G+P)>>5),k=L-(7*(P+_+z)>>5),Y=27-Math.clz32(T+v+E+q);T>>=Y,v>>=Y,E>>=Y,q>>=Y;const D=T+v+E+q;let F=Math.floor(((D>>1)-1+j*T+Z*v+B*E+k*q)*st[D-1]/16777216);if((_^N|_^P)<=0){const t=Math.min(X,J,L),n=Math.max(X,J,L);F=F<t?t:F>n?n:F}const Q=e[n],H=Q-(F+3>>3)-c;l?l[n]=r(H):0===H?(A<8&&(M[A]=R),A++):(m(),g(R,r(H)));const K=8*Q,V=Math.abs(j-K)+3>>3,W=Math.abs(Z-K)+3>>3,$=Math.abs(B-K)+3>>3,tt=Math.abs(k-K)+3>>3;d[s+a]=F-K,h[s+a]=V,y[s+a]=W,w[s+a]=$,p[s+a]=tt,h[u+a+1]+=V,y[u+a+1]+=W,w[u+a+1]+=$,p[u+a+1]+=tt}}m(),at=u}const ht=t=>Math.max(0,t<224?t-1:t-236),yt=t=>{const n=I(t),o=new e(128);S(o,n);let r=o.u;for(let e=0;e<t.length;e++)t[e]&&(r+=t[e]*(n.C[e]+ht(e)));return r};function wt(t,n,e,o,s){const c=new Uint32Array(n*e);if(6===o)return ut(null,null,t,n,e,0,void 0,c,s),c;for(let s=0,i=0;s<e;s++)for(let e=0;e<n;e++,i++){const l=e?t[i-1]:s?t[i-n]:0,f=s?t[i-n]:l,a=e&&s?t[i-n-1]:l,u=3===o?(l+f)/2|0:Math.max(Math.min(l,f),Math.min(Math.max(l,f),l+f-a));c[i]=r(t[i]-u)}return c}function pt(t,n,e=1){const o=Array.from({length:e},()=>new Uint32Array(z)),r=[],s=(t,e,s=0)=>{const c=n?n[t]:0;r.push(e,s,c),v(s?_.O:P,e,o[c],s)};for(let n=0;n<t.length;){let e=1;if(!t[n])for(;n+e<t.length&&!t[n+e];)e++;if(s(n,t[n]),e>_.minLength)s(n+1,e-1-_.minLength,_.G);else for(let t=1;t<e;t++)s(n+t,0);n+=e}return{ot:o,it:r}}function dt(t,n,e,o,r){const s=pt(t,Uint8Array.from(n,t=>{let n=0,e=r.length;for(;n<e;){const o=n+e>>1;t>r[o]?n=o+1:e=o}return n}),r.length+1),c=s.ot.length,i=s.ot.map(t=>t.some(t=>t)),l=new Float64Array(c+1).fill(1/0),f=new Uint8Array(c+1);l[0]=0;for(let t=1;t<=c;t++){const n=new Uint32Array(z);let e=0;for(let o=t-1;o>=0;o--){if(i[o]){for(let t=0;t<z;t++)n[t]+=s.ot[o][t];e=yt(n)}const r=l[o]+e+24;r<l[t]&&(l[t]=r,f[t]=o)}}const a=[];for(let t=c;t;t=f[t])a.unshift([f[t],t]);const u=a.map(()=>G(e)),h=new Uint8Array(c),y=a.map(([t,n],e)=>{const o=new Uint32Array(z);for(let r=t;r<n;r++){h[r]=e;for(let t=0;t<z;t++)o[t]+=s.ot[r][t]}return o});for(let t=2;t<s.it.length;t+=3)s.it[t]=h[s.it[t]];const w=(t,n)=>{if(t===n)return u[t];const e=t+n>>1;return O(o,r[a[e][1]-1],w(e+1,n),w(t,e))};return{leaves:u,k:w(0,a.length-1),ot:y,it:s.it}}const Mt=[-127,-31,-7,-1,0,1,7,31,127],At=[-191,-127,-63,-31,-7,-1,0,7,31,63,127,191,255];function gt(t,n,e,o){const r=new Int32Array(n*e);for(let s=0,c=0;s<e;s++)for(let e=0;e<n;e++,c++){const i=e?t[c-1]:s?t[c-n]:0,l=s?t[c-n]:i,f=e&&s?t[c-n-1]:i;r[c]=9===o?i+l-f:i-f}return r}function mt(t){const n=new e(512),o=Y(n,Z(n,t.k),t.ot,n=>t.leaves.indexOf(n));let r=n.u;return t.ot.forEach((t,n)=>{const{C:e}=o[n+1].code;for(let n=0;n<t.length;n++)r+=t[n]*((e[n]||0)+ht(n))}),r}function bt(t,n,e,o){return t.map(t=>{let r;for(const s of[5,3,6]){const c=6===s?new Int32Array(n*e):null,i=wt(t,n,e,s,c),l=G(s),f=[{...pt(i),leaves:[l],k:l}];if(c&&f.push(dt(i,c,s,15,Mt)),o>=6&&5===s)for(const o of[9,10]){const r=gt(t,n,e,o),c=9===o?At:Mt;f.push(dt(i,r,s,o,c))}for(const t of f){const n=mt(t);(!r||n<r.ft)&&(r={...t,ft:n})}}return r})}function Ut(t,n){const e=n.flatMap(t=>t.leaves),o=Y(t,Z(t,j(n.map(t=>t.k))),n.flatMap(t=>t.ot),t=>e.indexOf(t));return()=>{for(let r=0;r<n.length;r++){const{it:s}=n[r],c=n[r].leaves.map(t=>o[e.indexOf(t)+1].code);for(let n=0;n<s.length;n+=3){const e=s[n+1];q(t,c[s[n+2]],e?_.O:P,s[n],e)}}}}function*It(t,n,o,r,s,c=4,i=!1){const{channels:f}=r,u=w(n,o),d=u.p*u.M,M=i?r.palette:null;if(i&&!M)return null;const A=Array.from({length:M?1:f},()=>new Int16Array(65536)),g=new e(256);h(g,n,o,r.colour,r.alpha,{colorSpace:s}),y(g,{alpha:r.alpha});const m=M?[{type:"palette",D:0,H:f,K:M.colours.length}]:f>=3?[{type:"rct",D:0,F:6}]:[];let b;if(M){const t=M.colours.length,n=new Int16Array(t*f);M.colours.forEach((e,o)=>{for(let r=0;r<f;r++)n[r*t+o]=M.byte(e,r)}),b=bt([n],t,f,c)}const U=new e(4096),I=[];let S=0;const x=t=>{S+=Math.ceil(t.u/8),l(S),I.push(t.finish())};if(U.write(1,1),U.write(1,1),!u.U){let t;if(b)t=Ut(U,b);else{const t=A.map(()=>G(5));Y(U,Z(U,j(t)),A.map(()=>new Uint32Array(z)),n=>t.indexOf(n))}k(U,{et:m}),t&&t(),x(U);for(let t=0;t<u.A*u.m+1;t++)I.push(new Uint8Array(0))}for(let r=0;r<d;r++){const s=r%u.p*a,i=(r/u.p|0)*a,l=Math.min(a,n-s),h=Math.min(a,o-i);for(let e=0;e<h;e++)for(let o=0,r=e*l,c=4*((i+e)*n+s);o<l;o++,r++,c+=4)if(M)A[0][r]=M.index.get(M.key(c));else if(f>=3){const n=t[c]-t[c+2],e=t[c+2]+(n>>1),o=t[c+1]-e;A[0][r]=e+(o>>1),A[1][r]=n,A[2][r]=o,4===f&&(A[3][r]=t[c+3])}else A[0][r]=t[c],2===f&&(A[1][r]=t[c+3]);const y=bt(A,l,h,c),w=M&&u.U?[...b,...y]:y,p=u.U?U:new e(l*h*A.length+256);u.U||k(p,{nt:!1});const g=Ut(p,w);if(u.U&&k(p,{et:m}),g(),x(p),yield(r+1)/d)return null}return p(g,I)}function St(t,n,e,o){return function(t){let n;for(;!(n=t.next()).done;);return n.value}(xt(t,n,e,o))}function xt(n,e,r,s){const{quality:c,colorSpace:a}=function(t={},n=100){if(null===t||"object"!=typeof t)throw i("JXL_INPUT","Options are an object: {quality, colorSpace}.");if(void 0!==t.quality&&(n=t.quality),"number"!=typeof n||!Number.isFinite(n)||n<1||n>100)throw i("JXL_INPUT","Quality is a number from 1 to 100.");const e=void 0===t.colorSpace?"srgb":t.colorSpace;if("srgb"!==e&&"display-p3"!==e)throw i("JXL_INPUT","The colour space is srgb or display-p3.");return{quality:n,colorSpace:e}}(s),u=void 0===s?.effort?1:s.effort;if(!Number.isInteger(u)||u<1||u>9)throw i("JXL_INPUT","Effort is a whole number from 1 to 9.");return function(n,e,o,r){if(function(n,e,o=t){if(!Number.isInteger(n)||!Number.isInteger(e)||n<1||e<1)throw i("JXL_INPUT","A picture is at least one pixel wide and high, in whole pixels.");if(n>o.edge||e>o.edge)throw i("JXL_DIMENSIONS","A picture is at most "+o.edge+" pixels on a side.");if(n*e>o.pixels)throw i("JXL_DIMENSIONS","A picture is at most "+o.pixels.toLocaleString("en-US")+" pixels.")}(e,o,r),!(n instanceof Uint8Array||n instanceof Uint8ClampedArray))throw i("JXL_INPUT","Pixels are a Uint8Array or Uint8ClampedArray of RGBA bytes.");if(n.length!==e*o*4)throw i("JXL_INPUT","Pixels are width * height * 4 bytes: straight (not premultiplied) RGBA, row by row.")}(n,e,r),function(t){const n=function*(){let e,o;for(;!(e=f(()=>t.next(n.hurry))).done;)yield o=e.value;return o<1&&(yield 1),n.bytes=function(t){return l(t.length),t}(e.value)}();return n.bytes=null,n.hurry=!1,n}(function*(t,n,e,r,s,c){const i=F(t,n,e);if(r<100){if(!i.palette)return yield*et(t,n,e,{quality:r,shape:i,colorSpace:s});const c=yield*o(Q(t,n,e,{shape:i,colorSpace:s}),0,2);let l;try{l=yield*o(et(t,n,e,{quality:r,shape:i,colorSpace:s}),1,2)}catch(t){if("JXL_SIZE"!==t.code&&(!(t instanceof RangeError)||t.code))throw t;l=c}return c.length<=l.length?c:l}if(c<2)return yield*Q(t,n,e,{shape:i,colorSpace:s});let l=yield*o(Q(t,n,e,{shape:i,colorSpace:s}),0,2);if(c>=4){const o=[Et(t,n,e,i.palette?{...i,palette:null}:i,s,3)];i.palette&&o.push(It(t,n,e,i,s,4,!0)),c>=6&&(o.push(It(t,n,e,i,s,6)),i.palette&&o.push(It(t,n,e,i,s,6,!0)));for(let t=0;t<o.length;t++)try{let n,e=!1;for(;!(n=o[t].next(e)).done;)e=yield.5+(t+n.value)/(2*o.length);if(n.value&&n.value.length<l.length&&(l=n.value),e)return l}catch(t){if("JXL_SIZE"!==t.code&&(!(t instanceof RangeError)||t.code))throw t}return l}try{const r=yield*o(Et(t,n,e,i.palette?{...i,palette:null}:i,s,c),1,2);r&&r.length<l.length&&(l=r)}catch(t){if("JXL_SIZE"!==t.code&&(!(t instanceof RangeError)||t.code))throw t}return l}(n,e,r,c,a,u))}const Ct=t=>Math.max(0,t<224?t-1:t-236);function Tt(t){const n=I(t),o=new e(128);S(o,n);let r=o.u;for(let e=0;e<t.length;e++)t[e]&&(r+=t[e]*(n.C[e]+Ct(e)));return r}const vt=t=>{const n=new Uint32Array(z);for(const e of t)for(let t=0;t<z;t++)n[t]+=e[t];return n};function*Et(t,n,o,r,s,c){const{channels:i}=r,l=w(n,o),f=l.p*l.M,u=Array.from({length:i},()=>new Int16Array(65536)),d=(e,o,r,s)=>{for(let c=0;c<s;c++){let s=4*((o+c)*n+e),l=c*r;for(let n=0;n<r;n++,s+=4,l++)if(i>=3){const n=t[s],e=t[s+1],o=t[s+2],r=n-o,c=o+(r>>1),f=e-c;u[0][l]=c+(f>>1),u[1][l]=r,u[2][l]=f,4===i&&(u[3][l]=t[s+3])}else u[0][l]=t[s],2===i&&(u[1][l]=t[s+3])}},M=(t,e)=>{const r=t%l.p*a,s=(t/l.p|0)*a,c=Math.min(a,n-r),i=Math.min(a,o-s);d(r,s,c,i),e(c,i)},A=Math.min(n,32),g=Math.min(o,32),m=[J,X].map(t=>({R:t,ot:u.map(()=>new Uint32Array(z))}));for(const t of[0,.5,1]){d(Math.floor((n-A)*t),Math.floor((o-g)*t),A,g);for(const t of m)for(let n=0;n<i;n++)D(null,t.ot[n],u[n],A,g,G(t.R))}const b=u.map((t,n)=>G(m[Tt(m[1].ot[n])<Tt(m[0].ot[n])?1:0].R)),U=ot.length+1,I=Int32Array.from({length:U},(t,n)=>n),S=u.map(()=>new Uint32Array(z)),x=u.map(()=>Array.from({length:U},()=>new Uint32Array(z)));let C=0;for(let t=0;t<f;t++)if(M(t,(t,n)=>{for(let e=0;e<i;e++)D(null,S[e],u[e],t,n,b[e]),ut(null,x[e],u[e],t,n,0,I)}),yield++C/(2*f))return null;const T=u.map((t,n)=>{const e={ut:Tt(S[n]),leaves:[b[n]],ot:[S[n]],cuts:[]},o=vt(x[n]),r=Tt(o);return r<e.ut?{ut:r,leaves:[G(6)],ot:[o],cuts:[]}:e}),v=c<3?T:T.map((t,n)=>{const e=x[n].map(t=>t.some(t=>t)),o=new Float64Array(U+1).fill(1/0),r=new Int32Array(U+1);o[0]=0;for(let t=1;t<=U;t++){const s=new Uint32Array(z);let c=0;for(let i=t-1;i>=0;i--){if(e[i]){const t=x[n][i];for(let n=0;n<z;n++)s[n]+=t[n];c=Tt(s)}const l=o[i]+c+24;l<o[t]&&(o[t]=l,r[t]=i)}}if(!(o[U]<t.ut))return t;const s=[];for(let t=U;t>0;t=r[t])s.unshift([r[t],t]);return{ut:o[U],leaves:s.map(()=>G(6)),ot:s.map(([t,e])=>vt(x[n].slice(t,e))),cuts:s.slice(0,-1).map(([,t])=>ot[t-1]),ht:Int32Array.from({length:U},(t,n)=>s.findIndex(([t,e])=>n>=t&&n<e))}}),E=[T,v].filter((t,n)=>n?t.some((t,n)=>t!==T[n]):t.some((t,n)=>t.leaves[0]!==b[n]));if(!E.length)return null;const q=t=>({k:j(t.map(t=>((t,n)=>{const e=(o,r)=>{if(o===r)return t[o];const s=o+r>>1;return O(15,n[s],e(s+1,r),e(o,s))};return e(0,t.length-1)})(t.leaves,t.cuts))),leaves:t.flatMap(t=>t.leaves),ot:t.flatMap(t=>t.ot)}),L=t=>{const{k:n,leaves:o,ot:r}=q(t),s=new e(4096),c=Y(s,Z(s,n),r,t=>o.indexOf(t));let i=s.u;return r.forEach((t,n)=>{const{C:e}=c[n+1].code;for(let n=0;n<t.length;n++)t[n]&&(i+=t[n]*(e[n]+Ct(n)))}),i};let N=E;if(E.length>1){const[t,n]=E.map(L),e=27*(l.U?1:f+1)+8;n+e<=t?N=[E[1]]:t+e<=n?N=[E[0]]:n<t&&(N=[E[1],E[0]])}let _=0,P=!1;const R=()=>.5+ ++_/(2*N.length*f);let B=null;for(const t of N){const n=yield*F(t);if(!n)return B;if((!B||n.length<B.length||n.length===B.length&&t===E[0])&&(B=n),P)return B}return B;function*F(t){const{k:c,leaves:a,ot:w}=q(t),d=i>=3?[{type:"rct",D:0,F:6}]:[],A=new e(256);h(A,n,o,r.colour,r.alpha,{colorSpace:s}),y(A,{alpha:r.alpha});const g=new e(4096);g.write(1,1),g.write(1,1);const m=Y(g,Z(g,c),w,t=>a.indexOf(t));k(g,{nt:!0,et:d});const b=t.map(t=>t.leaves.map(t=>m[a.indexOf(t)+1].code)),U=(n,e,o,r)=>{const s=t[e];6===s.leaves[0].R?ut(n,b[e],u[e],o,r,0,s.ht):D(n,b[e][0],u[e],o,r,s.leaves[0])},I=[];if(l.U)M(0,(t,n)=>{for(let e=0;e<i;e++)U(g,e,t,n)}),P=yield R(),I.push(g.finish());else{I.push(g.finish());for(let t=0;t<l.A*l.m+1;t++)I.push(new Uint8Array(0));for(let t=0;t<f;t++)if(M(t,(t,n)=>{const o=new e(t*n*i+64);k(o,{nt:!0,et:[]});for(let e=0;e<i;e++)U(o,e,t,n);I.push(o.finish())}),(P=yield R())&&t+1<f)return null}return p(A,I)}}export{t as LIMITS,St as encode,xt as encodeSteps};