imagescript 3.2.1 → 3.4.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.
Files changed (101) hide show
  1. package/README.md +35 -10
  2. package/THIRD_PARTY_NOTICES.md +298 -2
  3. package/dist/animation.d.ts +25 -8
  4. package/dist/animation.js +44 -13
  5. package/dist/codecs/av1/cdef.js +197 -0
  6. package/dist/codecs/av1/data.js +141 -0
  7. package/dist/codecs/av1/decode.js +1769 -0
  8. package/dist/codecs/av1/filmgrain.js +219 -0
  9. package/dist/codecs/av1/frame.js +114 -0
  10. package/dist/codecs/av1/ipred.js +491 -0
  11. package/dist/codecs/av1/itx.js +950 -0
  12. package/dist/codecs/av1/loopfilter.js +149 -0
  13. package/dist/codecs/av1/msac.js +161 -0
  14. package/dist/codecs/av1/obu.js +516 -0
  15. package/dist/codecs/av1/postfilter.js +28 -0
  16. package/dist/codecs/av1/restoration.js +193 -0
  17. package/dist/codecs/av1/tables.js +160 -0
  18. package/dist/codecs/avif.js +581 -0
  19. package/dist/codecs/bmp.js +317 -0
  20. package/dist/codecs/crc.js +5 -0
  21. package/dist/codecs/gif.js +10 -35
  22. package/dist/codecs/hdr.d.ts +25 -0
  23. package/dist/codecs/hdr.js +201 -0
  24. package/dist/codecs/ico.js +48 -0
  25. package/dist/codecs/jpeg.js +11 -28
  26. package/dist/codecs/jxl/bits.js +126 -0
  27. package/dist/codecs/jxl/blend.js +117 -0
  28. package/dist/codecs/jxl/color.js +116 -0
  29. package/dist/codecs/jxl/dct.js +404 -0
  30. package/dist/codecs/jxl/entropy.js +556 -0
  31. package/dist/codecs/jxl/features.js +325 -0
  32. package/dist/codecs/jxl/filters.js +119 -0
  33. package/dist/codecs/jxl/frame-header.js +195 -0
  34. package/dist/codecs/jxl/frame.js +319 -0
  35. package/dist/codecs/jxl/headers.js +249 -0
  36. package/dist/codecs/jxl/idct.js +484 -0
  37. package/dist/codecs/jxl/modular.js +688 -0
  38. package/dist/codecs/jxl/quant.js +219 -0
  39. package/dist/codecs/jxl/upsample.js +52 -0
  40. package/dist/codecs/jxl/vardct.js +472 -0
  41. package/dist/codecs/jxl.js +89 -0
  42. package/dist/codecs/netpbm.js +239 -0
  43. package/dist/codecs/png.js +22 -10
  44. package/dist/codecs/qoi.js +150 -0
  45. package/dist/codecs/tga.js +3 -1
  46. package/dist/codecs/tiff.js +7 -2
  47. package/dist/codecs/vp8-enc-dsp.js +932 -0
  48. package/dist/codecs/vp8-enc-tables.js +78 -0
  49. package/dist/codecs/vp8-enc.js +1930 -0
  50. package/dist/codecs/vp8.js +3 -1
  51. package/dist/codecs/vp8l.js +126 -58
  52. package/dist/codecs/webp.js +47 -11
  53. package/dist/codecs/zlib.js +81 -69
  54. package/dist/frame.d.ts +1 -0
  55. package/dist/frame.js +4 -2
  56. package/dist/gif.d.ts +1 -0
  57. package/dist/gif.js +2 -2
  58. package/dist/image-type.d.ts +15 -1
  59. package/dist/image-type.js +45 -2
  60. package/dist/image.d.ts +89 -13
  61. package/dist/image.js +266 -113
  62. package/dist/index.d.ts +3 -2
  63. package/dist/index.js +4 -4
  64. package/dist/render/bidi.js +350 -0
  65. package/dist/render/buffer.js +362 -0
  66. package/dist/render/color.js +164 -0
  67. package/dist/render/colr.js +523 -0
  68. package/dist/render/font.js +173 -241
  69. package/dist/render/hinting.js +38 -22
  70. package/dist/render/layout.js +1553 -0
  71. package/dist/render/linebreak.js +210 -0
  72. package/dist/render/segment.js +106 -0
  73. package/dist/render/shape.js +984 -0
  74. package/dist/render/shapers/arabic.js +284 -0
  75. package/dist/render/shapers/hangul.js +142 -0
  76. package/dist/render/shapers/hebrew.js +49 -0
  77. package/dist/render/shapers/index.js +52 -0
  78. package/dist/render/shapers/indic.js +579 -0
  79. package/dist/render/shapers/khmer.js +104 -0
  80. package/dist/render/shapers/machine.js +129 -0
  81. package/dist/render/shapers/myanmar.js +121 -0
  82. package/dist/render/shapers/syllabic.js +100 -0
  83. package/dist/render/shapers/thai.js +125 -0
  84. package/dist/render/shapers/use.js +235 -0
  85. package/dist/render/svg.js +102 -23
  86. package/dist/render/text.js +373 -103
  87. package/dist/render/unicode-data.js +63 -0
  88. package/dist/render/unicode.js +50 -0
  89. package/dist/text-layout.d.ts +4 -1
  90. package/dist/text-layout.js +2 -2
  91. package/dist/util/alpha.js +43 -0
  92. package/dist/util/blur.js +20 -33
  93. package/dist/util/bytes.js +40 -0
  94. package/dist/util/limits.js +34 -0
  95. package/dist/util/options.js +7 -0
  96. package/dist/util/resample.js +126 -7
  97. package/dist/util/rotate.js +43 -0
  98. package/dist/version.js +1 -1
  99. package/licenses/HarfBuzz.txt +42 -0
  100. package/licenses/Unicode-3.0.txt +39 -0
  101. package/package.json +25 -2
@@ -0,0 +1,556 @@
1
+ const log2Ceil1 = (x) => x >= 0x80000000 ? 32 : 32 - Math.clz32(x);
2
+ function integerConfig(r, logAlphabetSize) {
3
+ const splitExponent = r.bits(log2Ceil1(logAlphabetSize));
4
+ let msb = 0, lsb = 0;
5
+ if (splitExponent !== logAlphabetSize) {
6
+ msb = r.bits(log2Ceil1(splitExponent));
7
+ if (msb > splitExponent)
8
+ throw new Error('JPEG XL: invalid hybrid integer configuration');
9
+ lsb = r.bits(log2Ceil1(splitExponent - msb));
10
+ }
11
+ if (msb + lsb > splitExponent)
12
+ throw new Error('JPEG XL: invalid hybrid integer configuration');
13
+ return { splitExponent, split: 1 << splitExponent, msb, lsb };
14
+ }
15
+ class AnsHistogram {
16
+ symbol;
17
+ cutoff;
18
+ freq;
19
+ offset;
20
+ aliasFreq;
21
+ logBucketSize;
22
+ single;
23
+ constructor(r, logAlphabetSize) {
24
+ const tableSize = 1 << logAlphabetSize, logBucketSize = 12 - logAlphabetSize, bucketSize = 1 << logBucketSize;
25
+ this.logBucketSize = logBucketSize;
26
+ const dist = new Uint16Array(tableSize);
27
+ let alphabetSize;
28
+ const small = r.bool(), even = !small && r.bool();
29
+ if (small) {
30
+ const two = r.bool();
31
+ if (two) {
32
+ const v0 = readU8(r), v1 = readU8(r);
33
+ if (v0 === v1)
34
+ throw new Error('JPEG XL: invalid ANS histogram');
35
+ alphabetSize = Math.max(v0, v1) + 1;
36
+ if (alphabetSize > tableSize)
37
+ throw new Error('JPEG XL: invalid ANS histogram');
38
+ const p = r.bits(12);
39
+ dist[v0] = p;
40
+ dist[v1] = 4096 - p;
41
+ }
42
+ else {
43
+ const v = readU8(r);
44
+ alphabetSize = v + 1;
45
+ if (alphabetSize > tableSize)
46
+ throw new Error('JPEG XL: invalid ANS histogram');
47
+ dist[v] = 4096;
48
+ }
49
+ }
50
+ else if (even) {
51
+ alphabetSize = readU8(r) + 1;
52
+ if (alphabetSize > tableSize)
53
+ throw new Error('JPEG XL: invalid ANS histogram');
54
+ const base = Math.floor(4096 / alphabetSize), leftover = 4096 % alphabetSize;
55
+ dist.fill(base + 1, 0, leftover);
56
+ dist.fill(base, leftover, alphabetSize);
57
+ }
58
+ else {
59
+ let len = 0;
60
+ while (len < 3 && r.bool())
61
+ len++;
62
+ const shift = r.bits(len) + (1 << len) - 1;
63
+ if (shift > 13)
64
+ throw new Error('JPEG XL: invalid ANS histogram');
65
+ alphabetSize = readU8(r) + 3;
66
+ if (alphabetSize > tableSize)
67
+ throw new Error('JPEG XL: invalid ANS histogram');
68
+ const repeats = [];
69
+ let omitLog = -1, omitPos = -1;
70
+ for (let i = 0; i < alphabetSize;) {
71
+ dist[i] = readLogCount(r);
72
+ if (dist[i] === 13) {
73
+ const count = readU8(r) + 4;
74
+ if (i + count > alphabetSize)
75
+ throw new Error('JPEG XL: invalid ANS histogram');
76
+ repeats.push(i, i + count);
77
+ i += count;
78
+ continue;
79
+ }
80
+ if (dist[i] > omitLog) {
81
+ omitLog = dist[i];
82
+ omitPos = i;
83
+ }
84
+ i++;
85
+ }
86
+ if (omitPos < 0 || (omitPos + 1 < tableSize && dist[omitPos + 1] === 13))
87
+ throw new Error('JPEG XL: invalid ANS histogram');
88
+ let repeat = 0, total = 0, prev = 0;
89
+ for (let i = 0; i < tableSize; i++) {
90
+ if (repeat < repeats.length && repeats[repeat] <= i) {
91
+ if (repeats[repeat + 1] === i)
92
+ repeat += 2;
93
+ else {
94
+ dist[i] = prev;
95
+ total += prev;
96
+ if (total > 4096)
97
+ throw new Error('JPEG XL: invalid ANS histogram');
98
+ continue;
99
+ }
100
+ }
101
+ if (dist[i] === 0 || i === omitPos) {
102
+ prev = 0;
103
+ continue;
104
+ }
105
+ if (dist[i] > 1) {
106
+ const zeros = dist[i] - 1;
107
+ const bitcount = Math.min(Math.max(shift - ((12 - zeros) >> 1), 0), zeros);
108
+ dist[i] = (1 << zeros) + (r.bits(bitcount) << (zeros - bitcount));
109
+ }
110
+ prev = dist[i];
111
+ total += dist[i];
112
+ if (total > 4096)
113
+ throw new Error('JPEG XL: invalid ANS histogram');
114
+ }
115
+ dist[omitPos] = 4096 - total;
116
+ }
117
+ this.symbol = new Uint8Array(tableSize);
118
+ this.cutoff = new Uint16Array(tableSize);
119
+ this.freq = dist;
120
+ this.offset = new Uint16Array(tableSize);
121
+ this.aliasFreq = new Uint16Array(tableSize);
122
+ const single = dist.indexOf(4096);
123
+ this.single = single;
124
+ if (single >= 0) {
125
+ for (let i = 0; i < tableSize; i++) {
126
+ this.symbol[i] = single;
127
+ this.offset[i] = bucketSize * i;
128
+ this.aliasFreq[i] = 4096;
129
+ }
130
+ return;
131
+ }
132
+ const cutoff = new Int32Array(tableSize), alias = new Int32Array(tableSize), aliasOffset = new Int32Array(tableSize);
133
+ const under = [], over = [];
134
+ for (let i = 0; i < tableSize; i++) {
135
+ cutoff[i] = dist[i];
136
+ alias[i] = i < alphabetSize ? i : 0;
137
+ if (dist[i] < bucketSize)
138
+ under.push(i);
139
+ else if (dist[i] > bucketSize)
140
+ over.push(i);
141
+ }
142
+ while (over.length && under.length) {
143
+ const o = over.pop(), u = under.pop();
144
+ const by = bucketSize - cutoff[u];
145
+ cutoff[o] -= by;
146
+ alias[u] = o;
147
+ aliasOffset[u] = cutoff[o];
148
+ if (cutoff[o] < bucketSize)
149
+ under.push(o);
150
+ else if (cutoff[o] > bucketSize)
151
+ over.push(o);
152
+ }
153
+ for (let i = 0; i < tableSize; i++) {
154
+ if (cutoff[i] === bucketSize) {
155
+ this.symbol[i] = i;
156
+ this.cutoff[i] = bucketSize;
157
+ }
158
+ else {
159
+ this.symbol[i] = alias[i];
160
+ this.cutoff[i] = cutoff[i];
161
+ this.offset[i] = aliasOffset[i] - cutoff[i];
162
+ this.aliasFreq[i] = dist[alias[i]];
163
+ }
164
+ }
165
+ }
166
+ }
167
+ function readU8(r) {
168
+ if (!r.bool())
169
+ return 0;
170
+ const n = r.bits(3);
171
+ return (1 << n) + r.bits(n);
172
+ }
173
+ function readLogCount(r) {
174
+ switch (r.bits(3)) {
175
+ case 0: return 10;
176
+ case 1:
177
+ for (const v of [4, 0, 11, 13])
178
+ if (r.bool())
179
+ return v;
180
+ return 12;
181
+ case 2: return 7;
182
+ case 3: return r.bool() ? 1 : 3;
183
+ case 4: return 6;
184
+ case 5: return 8;
185
+ case 6: return 9;
186
+ default: return r.bool() ? 2 : 5;
187
+ }
188
+ }
189
+ const MAX_PREFIX_BITS = 15;
190
+ class PrefixHistogram {
191
+ table;
192
+ bits;
193
+ single;
194
+ constructor(table, bits, single) {
195
+ this.table = table;
196
+ this.bits = bits;
197
+ this.single = single;
198
+ }
199
+ static singleSymbol(symbol) {
200
+ return new PrefixHistogram(Uint32Array.of(symbol << 4), 0, symbol);
201
+ }
202
+ static fromLengths(lengths) {
203
+ let maxLen = 0;
204
+ for (const l of lengths)
205
+ if (l > maxLen)
206
+ maxLen = l;
207
+ const counts = new Int32Array(maxLen + 1);
208
+ for (const l of lengths)
209
+ if (l)
210
+ counts[l]++;
211
+ const next = new Int32Array(maxLen + 1);
212
+ for (let len = 1, code = 0; len <= maxLen; len++) {
213
+ code = (code + counts[len - 1]) << 1;
214
+ next[len] = code;
215
+ }
216
+ const size = 1 << maxLen, table = new Uint32Array(size);
217
+ let filled = 0;
218
+ for (let sym = 0; sym < lengths.length; sym++) {
219
+ const len = lengths[sym];
220
+ if (!len)
221
+ continue;
222
+ const code = next[len]++;
223
+ if (code >= 1 << len)
224
+ throw new Error('JPEG XL: invalid prefix code');
225
+ let rev = 0;
226
+ for (let i = 0; i < len; i++)
227
+ rev |= (code >> i & 1) << (len - 1 - i);
228
+ for (let i = rev; i < size; i += 1 << len)
229
+ table[i] = sym << 4 | len;
230
+ filled += size >> len;
231
+ }
232
+ if (filled !== size)
233
+ throw new Error('JPEG XL: invalid prefix code');
234
+ return new PrefixHistogram(table, maxLen, -1);
235
+ }
236
+ static parse(r, alphabetSize) {
237
+ if (alphabetSize === 1)
238
+ return PrefixHistogram.singleSymbol(0);
239
+ const hskip = r.bits(2);
240
+ return hskip === 1 ? PrefixHistogram.parseSimple(r, alphabetSize) : PrefixHistogram.parseComplex(r, alphabetSize, hskip);
241
+ }
242
+ static parseSimple(r, alphabetSize) {
243
+ const alphabetBits = alphabetSize <= 1 ? 0 : 32 - Math.clz32(alphabetSize - 1);
244
+ const nsym = r.bits(2) + 1;
245
+ const syms = [];
246
+ for (let i = 0; i < nsym; i++)
247
+ syms.push(r.bits(alphabetBits));
248
+ for (const s of syms)
249
+ if (s >= alphabetSize)
250
+ throw new Error('JPEG XL: invalid prefix code');
251
+ if (nsym === 1)
252
+ return PrefixHistogram.singleSymbol(syms[0]);
253
+ const lengths = new Uint8Array(alphabetSize);
254
+ const lens = nsym === 2 ? [1, 1] : nsym === 3 ? [1, 2, 2] : r.bool() ? [1, 2, 3, 3] : [2, 2, 2, 2];
255
+ for (let i = 0; i < nsym; i++) {
256
+ if (lengths[syms[i]])
257
+ throw new Error('JPEG XL: invalid prefix code');
258
+ lengths[syms[i]] = lens[i];
259
+ }
260
+ return PrefixHistogram.fromLengths(lengths);
261
+ }
262
+ static parseComplex(r, alphabetSize, hskip) {
263
+ const ORDER = [1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15];
264
+ const clLengths = new Uint8Array(18);
265
+ let space = 0, nonZero = 0, nonZeroSym = 0;
266
+ for (let i = hskip; i < 18; i++) {
267
+ const base = r.u32(0, 4, 3, 8);
268
+ const len = base === 8 ? r.bool() ? r.bool() ? 5 : 1 : 2 : base;
269
+ clLengths[ORDER[i]] = len;
270
+ if (len) {
271
+ nonZero++;
272
+ nonZeroSym = ORDER[i];
273
+ space += 32 >> len;
274
+ if (space === 32)
275
+ break;
276
+ if (space > 32)
277
+ throw new Error('JPEG XL: invalid prefix code');
278
+ }
279
+ }
280
+ let clCode;
281
+ if (nonZero === 1)
282
+ clCode = PrefixHistogram.singleSymbol(nonZeroSym);
283
+ else if (space !== 32)
284
+ throw new Error('JPEG XL: invalid prefix code');
285
+ else
286
+ clCode = PrefixHistogram.fromLengths(clLengths);
287
+ const lengths = new Uint8Array(alphabetSize);
288
+ let total = 0, prevSym = 8, lastNonZero = 8, lastRepeat = 0, repeat = 0, repeatSym = 0;
289
+ for (let i = 0; i < alphabetSize; i++) {
290
+ if (repeat > 0) {
291
+ lengths[i] = repeatSym;
292
+ repeat--;
293
+ }
294
+ else {
295
+ const sym = clCode.read(r);
296
+ if (sym < 16) {
297
+ if (sym) {
298
+ lengths[i] = sym;
299
+ lastNonZero = sym;
300
+ }
301
+ }
302
+ else {
303
+ const extra = sym === 16 ? 2 : 3;
304
+ repeat = r.bits(extra) + 3;
305
+ if (prevSym === sym) {
306
+ repeat += lastRepeat * (sym === 16 ? 3 : 7) - (sym === 16 ? 8 : 16);
307
+ lastRepeat += repeat;
308
+ }
309
+ else
310
+ lastRepeat = repeat;
311
+ repeatSym = sym === 16 ? lastNonZero : 0;
312
+ lengths[i] = repeatSym;
313
+ repeat--;
314
+ }
315
+ prevSym = sym;
316
+ }
317
+ if (lengths[i]) {
318
+ total += 1 << (MAX_PREFIX_BITS - lengths[i]);
319
+ if (total > 1 << MAX_PREFIX_BITS)
320
+ throw new Error('JPEG XL: invalid prefix code');
321
+ if (total === 1 << MAX_PREFIX_BITS && repeat === 0)
322
+ break;
323
+ }
324
+ }
325
+ if (total !== 1 << MAX_PREFIX_BITS || repeat > 0)
326
+ throw new Error('JPEG XL: invalid prefix code');
327
+ return PrefixHistogram.fromLengths(lengths);
328
+ }
329
+ read(r) {
330
+ const e = this.table[this.bits ? r.peek(this.bits) : 0];
331
+ r.skip(e & 15);
332
+ return e >>> 4;
333
+ }
334
+ }
335
+ const SPECIAL_DISTANCES = [
336
+ 0, 1, 1, 0, 1, 1, -1, 1, 0, 2, 2, 0, 1, 2, -1, 2, 2, 1, -2, 1, 2, 2, -2, 2, 0, 3, 3, 0, 1, 3, -1, 3, 3, 1, -3, 1, 2, 3,
337
+ -2, 3, 3, 2, -3, 2, 0, 4, 4, 0, 1, 4, -1, 4, 4, 1, -4, 1, 3, 3, -3, 3, 2, 4, -2, 4, 4, 2, -4, 2, 0, 5, 3, 4, -3, 4, 4,
338
+ 3, -4, 3, 5, 0, 1, 5, -1, 5, 5, 1, -5, 1, 2, 5, -2, 5, 5, 2, -5, 2, 4, 4, -4, 4, 3, 5, -3, 5, 5, 3, -5, 3, 0, 6, 6, 0,
339
+ 1, 6, -1, 6, 6, 1, -6, 1, 2, 6, -2, 6, 6, 2, -6, 2, 4, 5, -4, 5, 5, 4, -5, 4, 3, 6, -3, 6, 6, 3, -6, 3, 0, 7, 7, 0, 1,
340
+ 7, -1, 7, 5, 5, -5, 5, 7, 1, -7, 1, 4, 6, -4, 6, 6, 4, -6, 4, 2, 7, -2, 7, 7, 2, -7, 2, 3, 7, -3, 7, 7, 3, -7, 3, 5, 6,
341
+ -5, 6, 6, 5, -6, 5, 8, 0, 4, 7, -4, 7, 7, 4, -7, 4, 8, 1, 8, 2, 6, 6, -6, 6, 8, 3, 5, 7, -5, 7, 7, 5, -7, 5, 8, 4, 6,
342
+ 7, -6, 7, 7, 6, -7, 6, 8, 5, 7, 7, -7, 7, 8, 6, 8, 7
343
+ ];
344
+ const WINDOW_MASK = (1 << 20) - 1;
345
+ export class EntropyDecoder {
346
+ clusters;
347
+ configs;
348
+ ans = null;
349
+ prefix = null;
350
+ state = 0;
351
+ initial = true;
352
+ lz77 = false;
353
+ minSymbol = 0;
354
+ minLength = 0;
355
+ lenConfig = null;
356
+ window = null;
357
+ toCopy = 0;
358
+ copyPos = 0;
359
+ decoded = 0;
360
+ constructor(r, numDist, allowLz77 = true) {
361
+ this.lz77 = r.bool();
362
+ if (this.lz77) {
363
+ if (!allowLz77)
364
+ throw new Error('JPEG XL: LZ77 is not allowed here');
365
+ this.minSymbol = r.u32(224, 512, 4096, [8, 15]);
366
+ this.minLength = r.u32(3, 4, [5, 2], [9, 8]);
367
+ this.lenConfig = integerConfig(r, 8);
368
+ numDist++;
369
+ }
370
+ const [numClusters, clusters] = readClusters(r, numDist);
371
+ this.clusters = clusters;
372
+ const usePrefix = r.bool();
373
+ const logAlphabetSize = usePrefix ? 15 : r.bits(2) + 5;
374
+ this.configs = [];
375
+ for (let i = 0; i < numClusters; i++)
376
+ this.configs.push(integerConfig(r, logAlphabetSize));
377
+ if (usePrefix) {
378
+ const counts = [];
379
+ for (let i = 0; i < numClusters; i++) {
380
+ let count = 1;
381
+ if (r.bool()) {
382
+ const n = r.bits(4);
383
+ count = 1 + (1 << n) + r.bits(n);
384
+ }
385
+ if (count > 1 << 15)
386
+ throw new Error('JPEG XL: invalid prefix code');
387
+ counts.push(count);
388
+ }
389
+ this.prefix = counts.map(count => PrefixHistogram.parse(r, count));
390
+ }
391
+ else {
392
+ this.ans = [];
393
+ for (let i = 0; i < numClusters; i++)
394
+ this.ans.push(new AnsHistogram(r, logAlphabetSize));
395
+ }
396
+ }
397
+ fork() {
398
+ const d = Object.create(EntropyDecoder.prototype);
399
+ Object.assign(d, this, { state: 0, initial: true, window: null, toCopy: 0, copyPos: 0, decoded: 0 });
400
+ return d;
401
+ }
402
+ begin(r) {
403
+ if (this.ans) {
404
+ this.state = r.bits(32);
405
+ this.initial = false;
406
+ }
407
+ }
408
+ finish() {
409
+ if (this.ans && this.state !== 0x130000)
410
+ throw new Error('JPEG XL: invalid ANS stream');
411
+ }
412
+ singleToken(cluster) {
413
+ if (this.lz77)
414
+ return -1;
415
+ const s = this.ans ? this.ans[cluster].single : this.prefix[cluster].single;
416
+ return s >= 0 && s < this.configs[cluster].split ? s : -1;
417
+ }
418
+ symbol(r, cluster) {
419
+ if (this.prefix)
420
+ return this.prefix[cluster].read(r);
421
+ if (this.initial) {
422
+ this.state = r.bits(32);
423
+ this.initial = false;
424
+ }
425
+ const h = this.ans[cluster];
426
+ const state = this.state, index = state & 0xfff;
427
+ const i = index >> h.logBucketSize, pos = index & ((1 << h.logBucketSize) - 1);
428
+ let symbol, freq, offset;
429
+ if (pos < h.cutoff[i]) {
430
+ symbol = i;
431
+ freq = h.freq[i];
432
+ offset = pos;
433
+ }
434
+ else {
435
+ symbol = h.symbol[i];
436
+ freq = h.aliasFreq[i];
437
+ offset = h.offset[i] + pos;
438
+ }
439
+ let next = (state >>> 12) * freq + offset;
440
+ if (next < 65536)
441
+ next = (next * 65536 + r.bits(16)) >>> 0;
442
+ this.state = next;
443
+ return symbol;
444
+ }
445
+ uint(r, config, token) {
446
+ if (token < config.split)
447
+ return token;
448
+ const inToken = config.msb + config.lsb;
449
+ const n = (config.splitExponent - inToken + ((token - config.split) >>> inToken)) & 31;
450
+ const low = token & ((1 << config.lsb) - 1);
451
+ const high = (token >>> config.lsb) & ((1 << config.msb) - 1) | 1 << config.msb;
452
+ return ((high * 2 ** n + r.bits(n)) * 2 ** config.lsb + low) >>> 0;
453
+ }
454
+ read(r, ctx, distMultiplier = 0) {
455
+ return this.readClustered(r, this.clusters[ctx], distMultiplier);
456
+ }
457
+ readClustered(r, cluster, distMultiplier = 0) {
458
+ if (!this.lz77)
459
+ return this.uint(r, this.configs[cluster], this.symbol(r, cluster));
460
+ const window = this.window ??= new Uint32Array(1 << 20);
461
+ let v;
462
+ if (this.toCopy > 0) {
463
+ v = window[this.copyPos++ & WINDOW_MASK];
464
+ this.toCopy--;
465
+ }
466
+ else {
467
+ const token = this.symbol(r, cluster);
468
+ if (token >= this.minSymbol) {
469
+ if (this.decoded === 0)
470
+ throw new Error('JPEG XL: LZ77 copy before any value');
471
+ const distCluster = this.clusters[this.clusters.length - 1];
472
+ this.toCopy = this.uint(r, this.lenConfig, token - this.minSymbol) + this.minLength;
473
+ let distance = this.uint(r, this.configs[distCluster], this.symbol(r, distCluster));
474
+ if (distMultiplier) {
475
+ if (distance < 120)
476
+ distance = Math.max(SPECIAL_DISTANCES[distance * 2] + distMultiplier * SPECIAL_DISTANCES[distance * 2 + 1] - 1, 0);
477
+ else
478
+ distance -= 120;
479
+ }
480
+ distance = Math.min(Math.min(distance, WINDOW_MASK) + 1, this.decoded);
481
+ this.copyPos = this.decoded - distance;
482
+ v = window[this.copyPos++ & WINDOW_MASK];
483
+ this.toCopy--;
484
+ }
485
+ else
486
+ v = this.uint(r, this.configs[cluster], token);
487
+ }
488
+ window[this.decoded++ & WINDOW_MASK] = v;
489
+ return v;
490
+ }
491
+ }
492
+ export function readClusters(r, numDist) {
493
+ if (numDist === 1)
494
+ return [1, new Uint8Array(1)];
495
+ const clusters = new Uint8Array(numDist);
496
+ if (r.bool()) {
497
+ const bits = r.bits(2);
498
+ for (let i = 0; i < numDist; i++)
499
+ clusters[i] = r.bits(bits);
500
+ }
501
+ else {
502
+ const mtf = r.bool();
503
+ const dec = new EntropyDecoder(r, 1, numDist > 2);
504
+ dec.begin(r);
505
+ for (let i = 0; i < numDist; i++) {
506
+ const v = dec.read(r, 0);
507
+ if (v > 255)
508
+ throw new Error('JPEG XL: invalid cluster');
509
+ clusters[i] = v;
510
+ }
511
+ dec.finish();
512
+ if (mtf) {
513
+ const map = new Uint8Array(256).map((_, i) => i);
514
+ for (let i = 0; i < numDist; i++) {
515
+ const index = clusters[i], v = map[index];
516
+ clusters[i] = v;
517
+ map.copyWithin(1, 0, index);
518
+ map[0] = v;
519
+ }
520
+ }
521
+ }
522
+ let max = 0;
523
+ for (const c of clusters)
524
+ if (c > max)
525
+ max = c;
526
+ const used = new Uint8Array(max + 1);
527
+ for (const c of clusters)
528
+ used[c] = 1;
529
+ if (used.includes(0))
530
+ throw new Error('JPEG XL: clusters with a hole');
531
+ return [max + 1, clusters];
532
+ }
533
+ export function readPermutation(r, dec, size, skip) {
534
+ const ctx = (x) => Math.min(log2Ceil1(x), 7);
535
+ const end = dec.read(r, ctx(size));
536
+ if (end > size - skip)
537
+ throw new Error('JPEG XL: invalid permutation');
538
+ const lehmer = [];
539
+ let prev = 0;
540
+ for (let i = 0; i < end; i++) {
541
+ const v = dec.read(r, ctx(prev));
542
+ if (v >= size - skip - i)
543
+ throw new Error('JPEG XL: invalid permutation');
544
+ lehmer.push(v);
545
+ prev = v;
546
+ }
547
+ const rest = [];
548
+ for (let i = skip; i < size; i++)
549
+ rest.push(i);
550
+ const out = [];
551
+ for (let i = 0; i < skip; i++)
552
+ out.push(i);
553
+ for (const v of lehmer)
554
+ out.push(rest.splice(v, 1)[0]);
555
+ return out.concat(rest);
556
+ }