imagescript 1.3.1 → 3.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.
Files changed (132) hide show
  1. package/LICENSE +4 -1
  2. package/README.md +76 -26
  3. package/THIRD_PARTY_NOTICES.md +156 -0
  4. package/dist/animation.d.ts +55 -0
  5. package/dist/animation.js +167 -0
  6. package/dist/codecs/crc.d.ts +9 -0
  7. package/dist/codecs/crc.js +29 -0
  8. package/dist/codecs/exif.d.ts +11 -0
  9. package/dist/codecs/exif.js +27 -0
  10. package/dist/codecs/gif.d.ts +44 -0
  11. package/dist/codecs/gif.js +401 -0
  12. package/dist/codecs/jpeg.d.ts +35 -0
  13. package/dist/codecs/jpeg.js +980 -0
  14. package/dist/codecs/png.d.ts +97 -0
  15. package/dist/codecs/png.js +664 -0
  16. package/dist/codecs/quantize.d.ts +25 -0
  17. package/dist/codecs/quantize.js +302 -0
  18. package/dist/codecs/tga.d.ts +16 -0
  19. package/dist/codecs/tga.js +203 -0
  20. package/dist/codecs/tiff.d.ts +6 -0
  21. package/dist/codecs/tiff.js +546 -0
  22. package/dist/codecs/vp8-tables.d.ts +10 -0
  23. package/dist/codecs/vp8-tables.js +17 -0
  24. package/dist/codecs/vp8.d.ts +8 -0
  25. package/dist/codecs/vp8.js +711 -0
  26. package/dist/codecs/vp8l.d.ts +62 -0
  27. package/dist/codecs/vp8l.js +909 -0
  28. package/dist/codecs/webp.d.ts +67 -0
  29. package/dist/codecs/webp.js +280 -0
  30. package/dist/codecs/zlib.d.ts +22 -0
  31. package/dist/codecs/zlib.js +607 -0
  32. package/dist/frame.d.ts +57 -0
  33. package/dist/frame.js +65 -0
  34. package/dist/gif.d.ts +31 -0
  35. package/dist/gif.js +20 -0
  36. package/dist/image-type.d.ts +24 -0
  37. package/dist/image-type.js +64 -0
  38. package/dist/image.d.ts +553 -0
  39. package/dist/image.js +1156 -0
  40. package/dist/index.d.ts +23 -0
  41. package/dist/index.js +20 -0
  42. package/dist/package.json +1 -0
  43. package/dist/render/font.d.ts +92 -0
  44. package/dist/render/font.js +954 -0
  45. package/dist/render/hinting.d.ts +110 -0
  46. package/dist/render/hinting.js +1236 -0
  47. package/dist/render/svg.d.ts +11 -0
  48. package/dist/render/svg.js +1717 -0
  49. package/dist/render/text.d.ts +63 -0
  50. package/dist/render/text.js +342 -0
  51. package/dist/text-layout.d.ts +46 -0
  52. package/dist/text-layout.js +35 -0
  53. package/dist/util/blur.d.ts +13 -0
  54. package/dist/util/blur.js +146 -0
  55. package/dist/util/mem.d.ts +10 -0
  56. package/dist/util/mem.js +23 -0
  57. package/dist/util/resample.d.ts +12 -0
  58. package/dist/util/resample.js +99 -0
  59. package/dist/util/utf8.d.ts +5 -0
  60. package/dist/util/utf8.js +55 -0
  61. package/dist/version.d.ts +1 -0
  62. package/dist/version.js +1 -0
  63. package/licenses/Apache-2.0.txt +202 -0
  64. package/licenses/FTL.txt +169 -0
  65. package/licenses/README.ijg +260 -0
  66. package/package.json +31 -7
  67. package/ImageScript.d.ts +0 -954
  68. package/ImageScript.js +0 -1669
  69. package/bench/_.mjs +0 -166
  70. package/bench/all.mjs +0 -4
  71. package/bench/blur.mjs +0 -59
  72. package/bench/flip.mjs +0 -63
  73. package/bench/overlay.mjs +0 -35
  74. package/bench/package.json +0 -7
  75. package/bench/readme.md +0 -64
  76. package/bench/resize.mjs +0 -52
  77. package/codecs/LICENSE +0 -21
  78. package/codecs/lib.d.ts +0 -50
  79. package/codecs/lib.js +0 -6
  80. package/codecs/lib.mjs +0 -1
  81. package/codecs/node/bin/arm64-darwin.node +0 -0
  82. package/codecs/node/bin/arm64-linux.node +0 -0
  83. package/codecs/node/bin/x64-darwin.node +0 -0
  84. package/codecs/node/bin/x64-linux.node +0 -0
  85. package/codecs/node/bin/x64-win32.node +0 -0
  86. package/codecs/node/index.js +0 -3
  87. package/codecs/node/index.mjs +0 -6
  88. package/codecs/package.json +0 -14
  89. package/codecs/readme.md +0 -38
  90. package/codecs/wasm/bin/codecs.wasm +0 -0
  91. package/codecs/wasm/bin/simd.wasm +0 -0
  92. package/codecs/wasm/bundle/browser.js +0 -1
  93. package/codecs/wasm/index.js +0 -1
  94. package/codecs/wasm/index.mjs +0 -1
  95. package/png/README.md +0 -1
  96. package/png/node.js +0 -1137
  97. package/png/src/crc.mjs +0 -49
  98. package/png/src/mem.mjs +0 -24
  99. package/png/src/png.mjs +0 -254
  100. package/png/src/zlib.mjs +0 -618
  101. package/tsconfig.json +0 -21
  102. package/utils/mem.js +0 -26
  103. package/v2/codecs/magic.js +0 -25
  104. package/v2/framebuffer.d.ts +0 -67
  105. package/v2/framebuffer.js +0 -2352
  106. package/v2/framebuffer.mjs +0 -126
  107. package/v2/framebuffer.rs +0 -1264
  108. package/v2/index.d.ts +0 -84
  109. package/v2/index.js +0 -261
  110. package/v2/ops/blur.mjs +0 -303
  111. package/v2/ops/color.mjs +0 -277
  112. package/v2/ops/crop.mjs +0 -64
  113. package/v2/ops/fill.mjs +0 -33
  114. package/v2/ops/flip.mjs +0 -33
  115. package/v2/ops/index.mjs +0 -9
  116. package/v2/ops/iterator.mjs +0 -34
  117. package/v2/ops/overlay.mjs +0 -63
  118. package/v2/ops/resize.mjs +0 -166
  119. package/v2/ops/rotate.mjs +0 -117
  120. package/v2/util/mem.mjs +0 -24
  121. package/wasm/any/font.wasm +0 -0
  122. package/wasm/any/gif.wasm +0 -0
  123. package/wasm/any/jpeg.wasm +0 -0
  124. package/wasm/any/png.wasm +0 -0
  125. package/wasm/any/svg.wasm +0 -0
  126. package/wasm/any/tiff.wasm +0 -0
  127. package/wasm/node/font.js +0 -142
  128. package/wasm/node/gif.js +0 -76
  129. package/wasm/node/jpeg.js +0 -92
  130. package/wasm/node/png.js +0 -49
  131. package/wasm/node/svg.js +0 -56
  132. package/wasm/node/tiff.js +0 -47
@@ -0,0 +1,711 @@
1
+ import { KF_BMODE_PROBS, COEFF_UPDATE_PROBS, DEFAULT_COEFF_PROBS, DC_QLOOKUP, AC_QLOOKUP, PCAT } from "./vp8-tables.js";
2
+ class BoolDecoder {
3
+ data;
4
+ pos;
5
+ end;
6
+ value;
7
+ range = 255;
8
+ bitCount = 0;
9
+ constructor(data, start, end) {
10
+ this.data = data;
11
+ this.end = Math.min(end, data.length);
12
+ this.pos = start;
13
+ this.value = this.next() << 8 | this.next();
14
+ }
15
+ next() {
16
+ return this.pos < this.end ? this.data[this.pos++] : (this.pos++, 0);
17
+ }
18
+ read(probability) {
19
+ const split = 1 + ((this.range - 1) * probability >> 8);
20
+ const bigSplit = split << 8;
21
+ let bit;
22
+ if (this.value >= bigSplit) {
23
+ bit = 1;
24
+ this.range -= split;
25
+ this.value -= bigSplit;
26
+ }
27
+ else {
28
+ bit = 0;
29
+ this.range = split;
30
+ }
31
+ if (this.range < 128) {
32
+ const shift = Math.clz32(this.range) - 24;
33
+ this.range <<= shift;
34
+ this.value <<= shift;
35
+ this.bitCount += shift;
36
+ if (this.bitCount >= 8) {
37
+ this.bitCount -= 8;
38
+ this.value |= this.next() << this.bitCount;
39
+ }
40
+ }
41
+ return bit;
42
+ }
43
+ literal(bits) {
44
+ let v = 0;
45
+ while (bits-- > 0)
46
+ v = v << 1 | this.read(128);
47
+ return v;
48
+ }
49
+ optionalSigned(bits) {
50
+ if (!this.read(128))
51
+ return 0;
52
+ const v = this.literal(bits);
53
+ return this.read(128) ? -v : v;
54
+ }
55
+ tree(tree, probs, offset = 0) {
56
+ let i = 0;
57
+ while ((i = tree[i + this.read(probs[offset + (i >> 1)])]) > 0)
58
+ ;
59
+ return -i;
60
+ }
61
+ get exhausted() {
62
+ return this.pos > this.end + 2;
63
+ }
64
+ }
65
+ const DC_PRED = 0, V_PRED = 1, H_PRED = 2, TM_PRED = 3, B_PRED = 4;
66
+ const B_DC_PRED = 0, B_TM_PRED = 1, B_VE_PRED = 2, B_HE_PRED = 3, B_LD_PRED = 4, B_RD_PRED = 5, B_VR_PRED = 6, B_VL_PRED = 7, B_HD_PRED = 8, B_HU_PRED = 9;
67
+ const KF_YMODE_TREE = Int8Array.of(-B_PRED, 2, 4, 6, -DC_PRED, -V_PRED, -H_PRED, -TM_PRED);
68
+ const KF_YMODE_PROBS = Uint8Array.of(145, 156, 163, 128);
69
+ const UV_MODE_TREE = Int8Array.of(-DC_PRED, 2, -V_PRED, 4, -H_PRED, -TM_PRED);
70
+ const KF_UV_MODE_PROBS = Uint8Array.of(142, 114, 183);
71
+ const BMODE_TREE = Int8Array.of(-B_DC_PRED, 2, -B_TM_PRED, 4, -B_VE_PRED, 6, 8, 12, -B_HE_PRED, 10, -B_RD_PRED, -B_VR_PRED, -B_LD_PRED, 14, -B_VL_PRED, 16, -B_HD_PRED, -B_HU_PRED);
72
+ const SEGMENT_TREE = Int8Array.of(2, 4, -0, -1, -2, -3);
73
+ const IMPLIED_BMODE = [B_DC_PRED, B_VE_PRED, B_HE_PRED, B_TM_PRED];
74
+ const ZIGZAG = Uint8Array.of(0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15);
75
+ const BANDS = Uint8Array.of(0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 0);
76
+ const CATEGORY_BASE = [5, 7, 11, 19, 35, 67];
77
+ const TYPE_Y_AC = 0, TYPE_Y2 = 1, TYPE_UV = 2, TYPE_Y = 3;
78
+ const clampQ = (q) => q < 0 ? 0 : q > 127 ? 127 : q;
79
+ function readHeader(data) {
80
+ if (data.length < 10)
81
+ throw new Error('VP8: truncated header');
82
+ const tag = data[0] | data[1] << 8 | data[2] << 16;
83
+ if (tag & 1)
84
+ throw new Error('VP8: not a key frame');
85
+ if ((tag >> 1 & 7) > 3)
86
+ throw new Error('VP8: unknown version');
87
+ const firstSize = tag >>> 5;
88
+ if (data[3] !== 0x9d || data[4] !== 0x01 || data[5] !== 0x2a)
89
+ throw new Error('VP8: invalid start code');
90
+ const width = (data[6] | data[7] << 8) & 0x3fff;
91
+ const height = (data[8] | data[9] << 8) & 0x3fff;
92
+ if (!width || !height)
93
+ throw new Error('VP8: invalid dimensions');
94
+ if (10 + firstSize > data.length)
95
+ throw new Error('VP8: truncated first partition');
96
+ const d = new BoolDecoder(data, 10, 10 + firstSize);
97
+ d.literal(1);
98
+ d.literal(1);
99
+ const segmentation = { enabled: false, updateMap: false, absolute: false, quant: new Int32Array(4), filter: new Int32Array(4), probs: Uint8Array.of(255, 255, 255) };
100
+ if (d.literal(1)) {
101
+ segmentation.enabled = true;
102
+ segmentation.updateMap = d.literal(1) === 1;
103
+ if (d.literal(1)) {
104
+ segmentation.absolute = d.literal(1) === 1;
105
+ for (let i = 0; i < 4; i++)
106
+ segmentation.quant[i] = d.optionalSigned(7);
107
+ for (let i = 0; i < 4; i++)
108
+ segmentation.filter[i] = d.optionalSigned(6);
109
+ }
110
+ if (segmentation.updateMap)
111
+ for (let i = 0; i < 3; i++)
112
+ segmentation.probs[i] = d.literal(1) ? d.literal(8) : 255;
113
+ }
114
+ const filterType = d.literal(1);
115
+ const filterLevel = d.literal(6);
116
+ const sharpness = d.literal(3);
117
+ const lfDeltas = { enabled: false, ref: new Int32Array(4), mode: new Int32Array(4) };
118
+ if (d.literal(1)) {
119
+ lfDeltas.enabled = true;
120
+ if (d.literal(1)) {
121
+ for (let i = 0; i < 4; i++)
122
+ if (d.literal(1))
123
+ lfDeltas.ref[i] = d.literal(6) * (d.literal(1) ? -1 : 1);
124
+ for (let i = 0; i < 4; i++)
125
+ if (d.literal(1))
126
+ lfDeltas.mode[i] = d.literal(6) * (d.literal(1) ? -1 : 1);
127
+ }
128
+ }
129
+ const count = 1 << d.literal(2);
130
+ let offset = 10 + firstSize;
131
+ const sizesStart = offset;
132
+ offset += 3 * (count - 1);
133
+ if (offset > data.length)
134
+ throw new Error('VP8: truncated partitions');
135
+ const partitions = [];
136
+ for (let i = 0; i < count; i++) {
137
+ const s = sizesStart + 3 * i;
138
+ const size = i < count - 1 ? data[s] | data[s + 1] << 8 | data[s + 2] << 16 : data.length - offset;
139
+ partitions.push(new BoolDecoder(data, offset, offset + size));
140
+ offset += size;
141
+ }
142
+ const base = d.literal(7);
143
+ const y1dc = d.optionalSigned(4), y2dc = d.optionalSigned(4), y2ac = d.optionalSigned(4), uvdc = d.optionalSigned(4), uvac = d.optionalSigned(4);
144
+ const quant = [];
145
+ for (let s = 0; s < 4; s++) {
146
+ let q = base;
147
+ if (segmentation.enabled)
148
+ q = segmentation.absolute ? segmentation.quant[s] : q + segmentation.quant[s];
149
+ const y2acFactor = AC_QLOOKUP[clampQ(q + y2ac)] * 155 / 100 | 0;
150
+ quant.push(Int32Array.of(DC_QLOOKUP[clampQ(q + y1dc)], AC_QLOOKUP[clampQ(q)], DC_QLOOKUP[clampQ(q + y2dc)] * 2, y2acFactor < 8 ? 8 : y2acFactor, Math.min(132, DC_QLOOKUP[clampQ(q + uvdc)]), AC_QLOOKUP[clampQ(q + uvac)]));
151
+ }
152
+ d.literal(1);
153
+ const coeffProbs = DEFAULT_COEFF_PROBS.slice();
154
+ for (let i = 0; i < coeffProbs.length; i++)
155
+ if (d.read(COEFF_UPDATE_PROBS[i]))
156
+ coeffProbs[i] = d.literal(8);
157
+ const skipProb = d.literal(1) ? d.literal(8) : -1;
158
+ return {
159
+ header: { width, height, filterType, filterLevel, sharpness, lfDeltas, segmentation, partitions, coeffProbs, skipProb, quant },
160
+ first: d
161
+ };
162
+ }
163
+ const clamp255 = (v) => v < 0 ? 0 : v > 255 ? 255 : v;
164
+ export function decode(data) {
165
+ const { header: h, first: d } = readHeader(data);
166
+ const { width, height } = h;
167
+ const mbw = (width + 15) >> 4, mbh = (height + 15) >> 4;
168
+ const ys = mbw * 16 + 1, cs = mbw * 8 + 1;
169
+ const Y = new Uint8Array(ys * (mbh * 16 + 1));
170
+ const U = new Uint8Array(cs * (mbh * 8 + 1));
171
+ const V = new Uint8Array(cs * (mbh * 8 + 1));
172
+ for (const [plane, stride] of [[Y, ys], [U, cs], [V, cs]]) {
173
+ plane.fill(127, 0, stride);
174
+ for (let i = stride; i < plane.length; i += stride)
175
+ plane[i] = 129;
176
+ }
177
+ const mbCount = mbw * mbh;
178
+ const mbSegment = new Uint8Array(mbCount);
179
+ const mbInner = new Uint8Array(mbCount);
180
+ const mbBpred = new Uint8Array(mbCount);
181
+ const aboveModes = new Uint8Array(mbw * 4);
182
+ const leftModes = new Uint8Array(4);
183
+ const aboveNz = new Uint8Array(mbw * 9);
184
+ const leftNz = new Uint8Array(9);
185
+ const coeffs = new Int16Array(25 * 16);
186
+ const bmodes = new Uint8Array(16);
187
+ const edge = new Uint8Array(21);
188
+ const left = new Uint8Array(16);
189
+ for (let mby = 0; mby < mbh; mby++) {
190
+ const tokens = h.partitions[mby % h.partitions.length];
191
+ leftModes.fill(B_DC_PRED);
192
+ leftNz.fill(0);
193
+ for (let mbx = 0; mbx < mbw; mbx++) {
194
+ const mb = mby * mbw + mbx;
195
+ const segment = h.segmentation.updateMap ? d.tree(SEGMENT_TREE, h.segmentation.probs) : 0;
196
+ mbSegment[mb] = segment;
197
+ const skip = h.skipProb >= 0 ? d.read(h.skipProb) : 0;
198
+ const ymode = d.tree(KF_YMODE_TREE, KF_YMODE_PROBS);
199
+ if (ymode === B_PRED) {
200
+ for (let b = 0; b < 16; b++) {
201
+ const above = b < 4 ? aboveModes[mbx * 4 + b] : bmodes[b - 4];
202
+ const l = (b & 3) === 0 ? leftModes[b >> 2] : bmodes[b - 1];
203
+ bmodes[b] = d.tree(BMODE_TREE, KF_BMODE_PROBS, (above * 10 + l) * 9);
204
+ }
205
+ }
206
+ else
207
+ bmodes.fill(IMPLIED_BMODE[ymode]);
208
+ for (let i = 0; i < 4; i++) {
209
+ aboveModes[mbx * 4 + i] = bmodes[12 + i];
210
+ leftModes[i] = bmodes[i * 4 + 3];
211
+ }
212
+ const uvmode = d.tree(UV_MODE_TREE, KF_UV_MODE_PROBS);
213
+ const hasY2 = ymode !== B_PRED;
214
+ const an = mbx * 9;
215
+ coeffs.fill(0);
216
+ let nonZero = 0;
217
+ if (!skip) {
218
+ const q = h.quant[segment];
219
+ if (hasY2) {
220
+ const ctx = aboveNz[an + 8] + leftNz[8];
221
+ const n = readCoefficients(tokens, h.coeffProbs, TYPE_Y2, ctx, 0, q[2], q[3], coeffs, 384);
222
+ aboveNz[an + 8] = leftNz[8] = n > 0 ? 1 : 0;
223
+ inverseWHT(coeffs, 384, n);
224
+ }
225
+ const type = hasY2 ? TYPE_Y_AC : TYPE_Y, first = hasY2 ? 1 : 0;
226
+ for (let b = 0; b < 16; b++) {
227
+ const x = b & 3, y = b >> 2;
228
+ const ctx = aboveNz[an + x] + leftNz[y];
229
+ const n = readCoefficients(tokens, h.coeffProbs, type, ctx, first, q[0], q[1], coeffs, b * 16);
230
+ aboveNz[an + x] = leftNz[y] = n > first ? 1 : 0;
231
+ if (n > first || coeffs[b * 16] !== 0)
232
+ nonZero |= 1 << b;
233
+ }
234
+ for (let b = 16; b < 24; b++) {
235
+ const plane = b < 20 ? 4 : 6, x = b & 1, y = (b >> 1) & 1;
236
+ const ctx = aboveNz[an + plane + x] + leftNz[plane + y];
237
+ const n = readCoefficients(tokens, h.coeffProbs, TYPE_UV, ctx, 0, q[4], q[5], coeffs, b * 16);
238
+ aboveNz[an + plane + x] = leftNz[plane + y] = n > 0 ? 1 : 0;
239
+ if (n > 0)
240
+ nonZero |= 1 << b;
241
+ }
242
+ }
243
+ else {
244
+ aboveNz.fill(0, an, an + 8);
245
+ leftNz.fill(0, 0, 8);
246
+ if (hasY2)
247
+ aboveNz[an + 8] = leftNz[8] = 0;
248
+ }
249
+ mbBpred[mb] = ymode === B_PRED ? 1 : 0;
250
+ mbInner[mb] = ymode === B_PRED || nonZero !== 0 ? 1 : 0;
251
+ const yBase = (mby * 16 + 1) * ys + mbx * 16 + 1;
252
+ if (ymode === B_PRED) {
253
+ for (let b = 0; b < 16; b++) {
254
+ const bx = b & 3, by = b >> 2;
255
+ const base = yBase + by * 4 * ys + bx * 4;
256
+ for (let i = 0; i < 5; i++)
257
+ edge[i] = Y[base - ys - 1 + i];
258
+ if (bx < 3)
259
+ for (let i = 5; i < 9; i++)
260
+ edge[i] = Y[base - ys - 1 + i];
261
+ else {
262
+ const top = yBase - ys + 16;
263
+ for (let i = 5; i < 9; i++)
264
+ edge[i] = mby === 0 ? 127 : mbx === mbw - 1 ? Y[yBase - ys + 15] : Y[top + i - 5];
265
+ }
266
+ for (let i = 0; i < 4; i++)
267
+ left[i] = Y[base + i * ys - 1];
268
+ predictSubblock(bmodes[b], edge, left, Y, base, ys);
269
+ if (nonZero >> b & 1)
270
+ inverseDCT(coeffs, b * 16, Y, base, ys);
271
+ }
272
+ }
273
+ else {
274
+ predictBlock(ymode, Y, yBase, ys, 16, mbx, mby);
275
+ for (let b = 0; b < 16; b++)
276
+ if (nonZero >> b & 1)
277
+ inverseDCT(coeffs, b * 16, Y, yBase + (b >> 2) * 4 * ys + (b & 3) * 4, ys);
278
+ }
279
+ const cBase = (mby * 8 + 1) * cs + mbx * 8 + 1;
280
+ predictBlock(uvmode, U, cBase, cs, 8, mbx, mby);
281
+ predictBlock(uvmode, V, cBase, cs, 8, mbx, mby);
282
+ for (let b = 16; b < 24; b++) {
283
+ if (!(nonZero >> b & 1))
284
+ continue;
285
+ const plane = b < 20 ? U : V, i = b & 3;
286
+ inverseDCT(coeffs, b * 16, plane, cBase + (i >> 1) * 4 * cs + (i & 1) * 4, cs);
287
+ }
288
+ }
289
+ if (tokens.exhausted && d.exhausted)
290
+ throw new Error('VP8: unexpected end of data');
291
+ }
292
+ if (h.filterLevel)
293
+ loopFilter(h, Y, U, V, ys, cs, mbw, mbh, mbSegment, mbInner, mbBpred);
294
+ return { width, height, pixels: toRGBA(Y, U, V, ys, cs, width, height) };
295
+ }
296
+ function readCoefficients(d, probs, type, ctx, first, dcFactor, acFactor, out, offset) {
297
+ let i = first;
298
+ let p = ((type * 8 + BANDS[i]) * 3 + ctx) * 11;
299
+ let previousZero = false;
300
+ for (; i < 16; i++) {
301
+ if (!previousZero && !d.read(probs[p]))
302
+ return i;
303
+ if (!d.read(probs[p + 1])) {
304
+ previousZero = true;
305
+ p = ((type * 8 + BANDS[i + 1]) * 3) * 11;
306
+ continue;
307
+ }
308
+ let v;
309
+ if (!d.read(probs[p + 2]))
310
+ v = 1;
311
+ else if (!d.read(probs[p + 3]))
312
+ v = d.read(probs[p + 4]) ? 3 + d.read(probs[p + 5]) : 2;
313
+ else {
314
+ let category;
315
+ if (!d.read(probs[p + 6]))
316
+ category = d.read(probs[p + 7]);
317
+ else if (!d.read(probs[p + 8]))
318
+ category = 2 + d.read(probs[p + 9]);
319
+ else
320
+ category = 4 + d.read(probs[p + 10]);
321
+ const extra = PCAT[category];
322
+ let e = 0;
323
+ for (let k = 0; k < extra.length; k++)
324
+ e = e << 1 | d.read(extra[k]);
325
+ v = CATEGORY_BASE[category] + e;
326
+ }
327
+ if (d.read(128))
328
+ v = -v;
329
+ out[offset + ZIGZAG[i]] = v * (i > 0 ? acFactor : dcFactor);
330
+ previousZero = false;
331
+ p = ((type * 8 + BANDS[i + 1]) * 3 + (v === 1 || v === -1 ? 1 : 2)) * 11;
332
+ }
333
+ return 16;
334
+ }
335
+ function inverseWHT(c, offset, count) {
336
+ const out = new Int32Array(16);
337
+ if (count > 1) {
338
+ for (let i = 0; i < 4; i++) {
339
+ const a1 = c[offset + i] + c[offset + 12 + i];
340
+ const b1 = c[offset + 4 + i] + c[offset + 8 + i];
341
+ const c1 = c[offset + 4 + i] - c[offset + 8 + i];
342
+ const d1 = c[offset + i] - c[offset + 12 + i];
343
+ out[i] = a1 + b1;
344
+ out[4 + i] = c1 + d1;
345
+ out[8 + i] = a1 - b1;
346
+ out[12 + i] = d1 - c1;
347
+ }
348
+ for (let i = 0; i < 4; i++) {
349
+ const r = i * 4;
350
+ const a1 = out[r] + out[r + 3];
351
+ const b1 = out[r + 1] + out[r + 2];
352
+ const c1 = out[r + 1] - out[r + 2];
353
+ const d1 = out[r] - out[r + 3];
354
+ out[r] = a1 + b1 + 3 >> 3;
355
+ out[r + 1] = c1 + d1 + 3 >> 3;
356
+ out[r + 2] = a1 - b1 + 3 >> 3;
357
+ out[r + 3] = d1 - c1 + 3 >> 3;
358
+ }
359
+ }
360
+ else
361
+ out.fill(c[offset] + 3 >> 3);
362
+ for (let b = 0; b < 16; b++)
363
+ c[b * 16] = out[b];
364
+ }
365
+ const tmp = new Int32Array(16);
366
+ function inverseDCT(c, offset, dst, base, stride) {
367
+ for (let i = 0; i < 4; i++) {
368
+ const i0 = c[offset + i], i4 = c[offset + 4 + i], i8 = c[offset + 8 + i], i12 = c[offset + 12 + i];
369
+ const a1 = i0 + i8, b1 = i0 - i8;
370
+ let t1 = i4 * 35468 >> 16, t2 = i12 + (i12 * 20091 >> 16);
371
+ const c1 = t1 - t2;
372
+ t1 = i4 + (i4 * 20091 >> 16);
373
+ t2 = i12 * 35468 >> 16;
374
+ const d1 = t1 + t2;
375
+ tmp[i] = a1 + d1;
376
+ tmp[12 + i] = a1 - d1;
377
+ tmp[4 + i] = b1 + c1;
378
+ tmp[8 + i] = b1 - c1;
379
+ }
380
+ for (let i = 0; i < 4; i++) {
381
+ const r = i * 4;
382
+ const i0 = tmp[r], i1 = tmp[r + 1], i2 = tmp[r + 2], i3 = tmp[r + 3];
383
+ const a1 = i0 + i2, b1 = i0 - i2;
384
+ let t1 = i1 * 35468 >> 16, t2 = i3 + (i3 * 20091 >> 16);
385
+ const c1 = t1 - t2;
386
+ t1 = i1 + (i1 * 20091 >> 16);
387
+ t2 = i3 * 35468 >> 16;
388
+ const d1 = t1 + t2;
389
+ const o = base + i * stride;
390
+ dst[o] = clamp255(dst[o] + (a1 + d1 + 4 >> 3));
391
+ dst[o + 3] = clamp255(dst[o + 3] + (a1 - d1 + 4 >> 3));
392
+ dst[o + 1] = clamp255(dst[o + 1] + (b1 + c1 + 4 >> 3));
393
+ dst[o + 2] = clamp255(dst[o + 2] + (b1 - c1 + 4 >> 3));
394
+ }
395
+ }
396
+ function predictBlock(mode, p, base, stride, size, mbx, mby) {
397
+ const above = base - stride;
398
+ if (mode === DC_PRED) {
399
+ const shift = size === 16 ? 3 : 2;
400
+ let sum = 0, count = 0;
401
+ if (mby > 0) {
402
+ for (let i = 0; i < size; i++)
403
+ sum += p[above + i];
404
+ count++;
405
+ }
406
+ if (mbx > 0) {
407
+ for (let i = 0; i < size; i++)
408
+ sum += p[base + i * stride - 1];
409
+ count++;
410
+ }
411
+ const v = count === 0 ? 128 : sum + (1 << shift + count - 1) >> shift + count;
412
+ for (let y = 0; y < size; y++)
413
+ p.fill(v, base + y * stride, base + y * stride + size);
414
+ }
415
+ else if (mode === V_PRED) {
416
+ for (let y = 0; y < size; y++)
417
+ p.copyWithin(base + y * stride, above, above + size);
418
+ }
419
+ else if (mode === H_PRED) {
420
+ for (let y = 0; y < size; y++) {
421
+ const row = base + y * stride;
422
+ p.fill(p[row - 1], row, row + size);
423
+ }
424
+ }
425
+ else {
426
+ const corner = p[above - 1];
427
+ for (let y = 0; y < size; y++) {
428
+ const row = base + y * stride, l = p[row - 1] - corner;
429
+ for (let x = 0; x < size; x++)
430
+ p[row + x] = clamp255(l + p[above + x]);
431
+ }
432
+ }
433
+ }
434
+ const avg3 = (x, y, z) => x + 2 * y + z + 2 >> 2;
435
+ const avg2 = (x, y) => x + y + 1 >> 1;
436
+ const B = new Uint8Array(16);
437
+ function predictSubblock(mode, edge, L, p, base, stride) {
438
+ const P = edge[0];
439
+ const A0 = edge[1], A1 = edge[2], A2 = edge[3], A3 = edge[4], A4 = edge[5], A5 = edge[6], A6 = edge[7], A7 = edge[8];
440
+ const L0 = L[0], L1 = L[1], L2 = L[2], L3 = L[3];
441
+ switch (mode) {
442
+ case B_DC_PRED:
443
+ B.fill(A0 + A1 + A2 + A3 + L0 + L1 + L2 + L3 + 4 >> 3);
444
+ break;
445
+ case B_TM_PRED:
446
+ for (let r = 0; r < 4; r++) {
447
+ const l = L[r] - P;
448
+ B[r * 4] = clamp255(l + A0);
449
+ B[r * 4 + 1] = clamp255(l + A1);
450
+ B[r * 4 + 2] = clamp255(l + A2);
451
+ B[r * 4 + 3] = clamp255(l + A3);
452
+ }
453
+ break;
454
+ case B_VE_PRED: {
455
+ const v0 = avg3(P, A0, A1), v1 = avg3(A0, A1, A2), v2 = avg3(A1, A2, A3), v3 = avg3(A2, A3, A4);
456
+ for (let r = 0; r < 16; r += 4) {
457
+ B[r] = v0;
458
+ B[r + 1] = v1;
459
+ B[r + 2] = v2;
460
+ B[r + 3] = v3;
461
+ }
462
+ break;
463
+ }
464
+ case B_HE_PRED:
465
+ B.fill(avg3(P, L0, L1), 0, 4);
466
+ B.fill(avg3(L0, L1, L2), 4, 8);
467
+ B.fill(avg3(L1, L2, L3), 8, 12);
468
+ B.fill(avg3(L2, L3, L3), 12, 16);
469
+ break;
470
+ case B_LD_PRED:
471
+ B[0] = avg3(A0, A1, A2);
472
+ B[1] = B[4] = avg3(A1, A2, A3);
473
+ B[2] = B[5] = B[8] = avg3(A2, A3, A4);
474
+ B[3] = B[6] = B[9] = B[12] = avg3(A3, A4, A5);
475
+ B[7] = B[10] = B[13] = avg3(A4, A5, A6);
476
+ B[11] = B[14] = avg3(A5, A6, A7);
477
+ B[15] = avg3(A6, A7, A7);
478
+ break;
479
+ case B_RD_PRED:
480
+ B[12] = avg3(L3, L2, L1);
481
+ B[13] = B[8] = avg3(L2, L1, L0);
482
+ B[14] = B[9] = B[4] = avg3(L1, L0, P);
483
+ B[15] = B[10] = B[5] = B[0] = avg3(L0, P, A0);
484
+ B[11] = B[6] = B[1] = avg3(P, A0, A1);
485
+ B[7] = B[2] = avg3(A0, A1, A2);
486
+ B[3] = avg3(A1, A2, A3);
487
+ break;
488
+ case B_VR_PRED:
489
+ B[12] = avg3(L2, L1, L0);
490
+ B[8] = avg3(L1, L0, P);
491
+ B[13] = B[4] = avg3(L0, P, A0);
492
+ B[9] = B[0] = avg2(P, A0);
493
+ B[14] = B[5] = avg3(P, A0, A1);
494
+ B[10] = B[1] = avg2(A0, A1);
495
+ B[15] = B[6] = avg3(A0, A1, A2);
496
+ B[11] = B[2] = avg2(A1, A2);
497
+ B[7] = avg3(A1, A2, A3);
498
+ B[3] = avg2(A2, A3);
499
+ break;
500
+ case B_VL_PRED:
501
+ B[0] = avg2(A0, A1);
502
+ B[4] = avg3(A0, A1, A2);
503
+ B[8] = B[1] = avg2(A1, A2);
504
+ B[5] = B[12] = avg3(A1, A2, A3);
505
+ B[9] = B[2] = avg2(A2, A3);
506
+ B[13] = B[6] = avg3(A2, A3, A4);
507
+ B[10] = B[3] = avg2(A3, A4);
508
+ B[14] = B[7] = avg3(A3, A4, A5);
509
+ B[11] = avg3(A4, A5, A6);
510
+ B[15] = avg3(A5, A6, A7);
511
+ break;
512
+ case B_HD_PRED:
513
+ B[12] = avg2(L3, L2);
514
+ B[13] = avg3(L3, L2, L1);
515
+ B[8] = B[14] = avg2(L2, L1);
516
+ B[9] = B[15] = avg3(L2, L1, L0);
517
+ B[10] = B[4] = avg2(L1, L0);
518
+ B[11] = B[5] = avg3(L1, L0, P);
519
+ B[6] = B[0] = avg2(L0, P);
520
+ B[7] = B[1] = avg3(L0, P, A0);
521
+ B[2] = avg3(P, A0, A1);
522
+ B[3] = avg3(A0, A1, A2);
523
+ break;
524
+ case B_HU_PRED:
525
+ B[0] = avg2(L0, L1);
526
+ B[1] = avg3(L0, L1, L2);
527
+ B[2] = B[4] = avg2(L1, L2);
528
+ B[3] = B[5] = avg3(L1, L2, L3);
529
+ B[6] = B[8] = avg2(L2, L3);
530
+ B[7] = B[9] = avg3(L2, L3, L3);
531
+ B[10] = B[11] = B[12] = B[13] = B[14] = B[15] = L3;
532
+ break;
533
+ }
534
+ for (let r = 0; r < 4; r++) {
535
+ const o = base + r * stride, b = r * 4;
536
+ p[o] = B[b];
537
+ p[o + 1] = B[b + 1];
538
+ p[o + 2] = B[b + 2];
539
+ p[o + 3] = B[b + 3];
540
+ }
541
+ }
542
+ const s8 = (v) => v < -128 ? -128 : v > 127 ? 127 : v;
543
+ function commonAdjust(p, i, step, outerTaps) {
544
+ const p1 = p[i - 2 * step] - 128, p0 = p[i - step] - 128, q0 = p[i] - 128, q1 = p[i + step] - 128;
545
+ let a = s8((outerTaps ? s8(p1 - q1) : 0) + 3 * (q0 - p0));
546
+ const b = s8(a + 3) >> 3;
547
+ a = s8(a + 4) >> 3;
548
+ p[i] = s8(q0 - a) + 128;
549
+ p[i - step] = s8(p0 + b) + 128;
550
+ return a;
551
+ }
552
+ const edgeOk = (p, i, step, limit) => Math.abs(p[i - step] - p[i]) * 2 + (Math.abs(p[i - 2 * step] - p[i + step]) >> 1) <= limit;
553
+ function filterEdge(p, i, along, step, count, macroblock, edgeLimit, interior, hevThreshold) {
554
+ for (let k = 0; k < count; k++, i += along) {
555
+ const p3 = p[i - 4 * step], p2 = p[i - 3 * step], p1 = p[i - 2 * step], p0 = p[i - step];
556
+ const q0 = p[i], q1 = p[i + step], q2 = p[i + 2 * step], q3 = p[i + 3 * step];
557
+ if (Math.abs(p0 - q0) * 2 + (Math.abs(p1 - q1) >> 1) > edgeLimit
558
+ || Math.abs(p3 - p2) > interior || Math.abs(p2 - p1) > interior || Math.abs(p1 - p0) > interior
559
+ || Math.abs(q3 - q2) > interior || Math.abs(q2 - q1) > interior || Math.abs(q1 - q0) > interior)
560
+ continue;
561
+ const hev = Math.abs(p1 - p0) > hevThreshold || Math.abs(q1 - q0) > hevThreshold;
562
+ if (macroblock) {
563
+ if (hev) {
564
+ commonAdjust(p, i, step, true);
565
+ continue;
566
+ }
567
+ const w = s8(s8(p1 - q1) + 3 * (q0 - p0));
568
+ let a = s8(27 * w + 63 >> 7);
569
+ p[i] = s8(q0 - 128 - a) + 128;
570
+ p[i - step] = s8(p0 - 128 + a) + 128;
571
+ a = s8(18 * w + 63 >> 7);
572
+ p[i + step] = s8(q1 - 128 - a) + 128;
573
+ p[i - 2 * step] = s8(p1 - 128 + a) + 128;
574
+ a = s8(9 * w + 63 >> 7);
575
+ p[i + 2 * step] = s8(q2 - 128 - a) + 128;
576
+ p[i - 3 * step] = s8(p2 - 128 + a) + 128;
577
+ }
578
+ else {
579
+ const a = commonAdjust(p, i, step, hev) + 1 >> 1;
580
+ if (!hev) {
581
+ p[i + step] = s8(q1 - 128 - a) + 128;
582
+ p[i - 2 * step] = s8(p1 - 128 + a) + 128;
583
+ }
584
+ }
585
+ }
586
+ }
587
+ function filterEdgeSimple(p, i, along, step, count, limit) {
588
+ for (let k = 0; k < count; k++, i += along)
589
+ if (edgeOk(p, i, step, limit))
590
+ commonAdjust(p, i, step, true);
591
+ }
592
+ function loopFilter(h, Y, U, V, ys, cs, mbw, mbh, segments, inner, bpred) {
593
+ for (let mby = 0; mby < mbh; mby++)
594
+ for (let mbx = 0; mbx < mbw; mbx++) {
595
+ const mb = mby * mbw + mbx;
596
+ let level = h.filterLevel;
597
+ if (h.segmentation.enabled) {
598
+ level = h.segmentation.filter[segments[mb]];
599
+ if (!h.segmentation.absolute)
600
+ level += h.filterLevel;
601
+ }
602
+ if (h.lfDeltas.enabled) {
603
+ level += h.lfDeltas.ref[0];
604
+ if (bpred[mb])
605
+ level += h.lfDeltas.mode[0];
606
+ }
607
+ level = level < 0 ? 0 : level > 63 ? 63 : level;
608
+ if (level === 0)
609
+ continue;
610
+ let interior = level;
611
+ if (h.sharpness) {
612
+ interior >>= h.sharpness > 4 ? 2 : 1;
613
+ if (interior > 9 - h.sharpness)
614
+ interior = 9 - h.sharpness;
615
+ }
616
+ if (!interior)
617
+ interior = 1;
618
+ const hevThreshold = level >= 40 ? 2 : level >= 15 ? 1 : 0;
619
+ const mbLimit = (level + 2) * 2 + interior, subLimit = level * 2 + interior;
620
+ const filterInner = inner[mb] === 1;
621
+ const y0 = (mby * 16 + 1) * ys + mbx * 16 + 1;
622
+ if (h.filterType === 1) {
623
+ if (mbx > 0)
624
+ filterEdgeSimple(Y, y0, ys, 1, 16, mbLimit);
625
+ if (filterInner)
626
+ for (let x = 4; x < 16; x += 4)
627
+ filterEdgeSimple(Y, y0 + x, ys, 1, 16, subLimit);
628
+ if (mby > 0)
629
+ filterEdgeSimple(Y, y0, 1, ys, 16, mbLimit);
630
+ if (filterInner)
631
+ for (let y = 4; y < 16; y += 4)
632
+ filterEdgeSimple(Y, y0 + y * ys, 1, ys, 16, subLimit);
633
+ continue;
634
+ }
635
+ const c0 = (mby * 8 + 1) * cs + mbx * 8 + 1;
636
+ if (mbx > 0) {
637
+ filterEdge(Y, y0, ys, 1, 16, true, mbLimit, interior, hevThreshold);
638
+ filterEdge(U, c0, cs, 1, 8, true, mbLimit, interior, hevThreshold);
639
+ filterEdge(V, c0, cs, 1, 8, true, mbLimit, interior, hevThreshold);
640
+ }
641
+ if (filterInner) {
642
+ for (let x = 4; x < 16; x += 4)
643
+ filterEdge(Y, y0 + x, ys, 1, 16, false, subLimit, interior, hevThreshold);
644
+ filterEdge(U, c0 + 4, cs, 1, 8, false, subLimit, interior, hevThreshold);
645
+ filterEdge(V, c0 + 4, cs, 1, 8, false, subLimit, interior, hevThreshold);
646
+ }
647
+ if (mby > 0) {
648
+ filterEdge(Y, y0, 1, ys, 16, true, mbLimit, interior, hevThreshold);
649
+ filterEdge(U, c0, 1, cs, 8, true, mbLimit, interior, hevThreshold);
650
+ filterEdge(V, c0, 1, cs, 8, true, mbLimit, interior, hevThreshold);
651
+ }
652
+ if (filterInner) {
653
+ for (let y = 4; y < 16; y += 4)
654
+ filterEdge(Y, y0 + y * ys, 1, ys, 16, false, subLimit, interior, hevThreshold);
655
+ filterEdge(U, c0 + 4 * cs, 1, cs, 8, false, subLimit, interior, hevThreshold);
656
+ filterEdge(V, c0 + 4 * cs, 1, cs, 8, false, subLimit, interior, hevThreshold);
657
+ }
658
+ }
659
+ }
660
+ const multHi = (v, coeff) => v * coeff >> 8;
661
+ const clip8 = (v) => (v & ~16383) === 0 ? v >> 6 : v < 0 ? 0 : 255;
662
+ function yuvToRGBA(y, u, v, out, o) {
663
+ const yy = multHi(y, 19077);
664
+ out[o] = clip8(yy + multHi(v, 26149) - 14234);
665
+ out[o + 1] = clip8(yy - multHi(u, 6419) - multHi(v, 13320) + 8708);
666
+ out[o + 2] = clip8(yy + multHi(u, 33050) - 17685);
667
+ out[o + 3] = 255;
668
+ }
669
+ function toRGBA(Y, U, V, ys, cs, width, height) {
670
+ const out = new Uint8Array(width * height * 4);
671
+ const yRow = (y) => (y + 1) * ys + 1;
672
+ const cRow = (y) => (y + 1) * cs + 1;
673
+ const lastChroma = (height + 1 >> 1) - 1;
674
+ upsamplePair(Y, U, V, yRow(0), -1, cRow(0), cRow(0), out, 0, -1, width);
675
+ for (let y = 1; y + 1 < height; y += 2) {
676
+ const k = y + 1 >> 1;
677
+ upsamplePair(Y, U, V, yRow(y), yRow(y + 1), cRow(k - 1), cRow(k), out, y * width * 4, (y + 1) * width * 4, width);
678
+ }
679
+ if (!(height & 1))
680
+ upsamplePair(Y, U, V, yRow(height - 1), -1, cRow(lastChroma), cRow(lastChroma), out, (height - 1) * width * 4, -1, width);
681
+ return out;
682
+ }
683
+ function upsamplePair(Y, U, V, topY, bottomY, topC, curC, out, topOut, bottomOut, width) {
684
+ let tlu = U[topC], tlv = V[topC], lu = U[curC], lv = V[curC];
685
+ yuvToRGBA(Y[topY], 3 * tlu + lu + 2 >> 2, 3 * tlv + lv + 2 >> 2, out, topOut);
686
+ if (bottomY >= 0)
687
+ yuvToRGBA(Y[bottomY], 3 * lu + tlu + 2 >> 2, 3 * lv + tlv + 2 >> 2, out, bottomOut);
688
+ const pairs = width - 1 >> 1;
689
+ for (let x = 1; x <= pairs; x++) {
690
+ const tu = U[topC + x], tv = V[topC + x], u = U[curC + x], v = V[curC + x];
691
+ const avgU = tlu + tu + lu + u + 8, avgV = tlv + tv + lv + v + 8;
692
+ const d12u = avgU + 2 * (tu + lu) >> 3, d03u = avgU + 2 * (tlu + u) >> 3;
693
+ const d12v = avgV + 2 * (tv + lv) >> 3, d03v = avgV + 2 * (tlv + v) >> 3;
694
+ yuvToRGBA(Y[topY + 2 * x - 1], d12u + tlu >> 1, d12v + tlv >> 1, out, topOut + (2 * x - 1) * 4);
695
+ yuvToRGBA(Y[topY + 2 * x], d03u + tu >> 1, d03v + tv >> 1, out, topOut + 2 * x * 4);
696
+ if (bottomY >= 0) {
697
+ yuvToRGBA(Y[bottomY + 2 * x - 1], d03u + lu >> 1, d03v + lv >> 1, out, bottomOut + (2 * x - 1) * 4);
698
+ yuvToRGBA(Y[bottomY + 2 * x], d12u + u >> 1, d12v + v >> 1, out, bottomOut + 2 * x * 4);
699
+ }
700
+ tlu = tu;
701
+ tlv = tv;
702
+ lu = u;
703
+ lv = v;
704
+ }
705
+ if (!(width & 1)) {
706
+ const x = width - 1;
707
+ yuvToRGBA(Y[topY + x], 3 * tlu + lu + 2 >> 2, 3 * tlv + lv + 2 >> 2, out, topOut + x * 4);
708
+ if (bottomY >= 0)
709
+ yuvToRGBA(Y[bottomY + x], 3 * lu + tlu + 2 >> 2, 3 * lv + tlv + 2 >> 2, out, bottomOut + x * 4);
710
+ }
711
+ }