imagescript 3.3.0 → 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 (59) hide show
  1. package/README.md +28 -8
  2. package/THIRD_PARTY_NOTICES.md +167 -2
  3. package/dist/animation.d.ts +18 -8
  4. package/dist/animation.js +23 -2
  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/hdr.d.ts +25 -0
  21. package/dist/codecs/hdr.js +201 -0
  22. package/dist/codecs/ico.js +48 -0
  23. package/dist/codecs/jpeg.js +2 -1
  24. package/dist/codecs/jxl/bits.js +126 -0
  25. package/dist/codecs/jxl/blend.js +117 -0
  26. package/dist/codecs/jxl/color.js +116 -0
  27. package/dist/codecs/jxl/dct.js +404 -0
  28. package/dist/codecs/jxl/entropy.js +556 -0
  29. package/dist/codecs/jxl/features.js +325 -0
  30. package/dist/codecs/jxl/filters.js +119 -0
  31. package/dist/codecs/jxl/frame-header.js +195 -0
  32. package/dist/codecs/jxl/frame.js +319 -0
  33. package/dist/codecs/jxl/headers.js +249 -0
  34. package/dist/codecs/jxl/idct.js +484 -0
  35. package/dist/codecs/jxl/modular.js +688 -0
  36. package/dist/codecs/jxl/quant.js +219 -0
  37. package/dist/codecs/jxl/upsample.js +52 -0
  38. package/dist/codecs/jxl/vardct.js +472 -0
  39. package/dist/codecs/jxl.js +89 -0
  40. package/dist/codecs/netpbm.js +239 -0
  41. package/dist/codecs/qoi.js +150 -0
  42. package/dist/codecs/vp8-enc-dsp.js +932 -0
  43. package/dist/codecs/vp8-enc-tables.js +78 -0
  44. package/dist/codecs/vp8-enc.js +1930 -0
  45. package/dist/codecs/webp.js +36 -2
  46. package/dist/image-type.d.ts +15 -1
  47. package/dist/image-type.js +45 -2
  48. package/dist/image.d.ts +47 -6
  49. package/dist/image.js +49 -3
  50. package/dist/index.d.ts +3 -2
  51. package/dist/index.js +2 -2
  52. package/dist/render/hinting.js +26 -18
  53. package/dist/render/layout.js +1 -1
  54. package/dist/render/svg.js +1 -1
  55. package/dist/render/unicode.js +1 -9
  56. package/dist/util/bytes.js +9 -0
  57. package/dist/util/resample.js +4 -2
  58. package/dist/version.js +1 -1
  59. package/package.json +25 -2
@@ -0,0 +1,219 @@
1
+ import { ModularImage, channel, decodeModular } from "./modular.js";
2
+ const f32 = Math.fround;
3
+ export const MATRIX_SIZES = [[8, 8], [8, 8], [8, 8], [8, 8], [16, 16], [32, 32], [16, 8], [32, 8], [32, 16], [8, 8], [8, 8], [64, 64], [64, 32], [128, 128], [128, 64], [256, 256], [256, 128]];
4
+ export const MATRIX_INDEX = [0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 10, 11, 12, 12, 13, 14, 14, 15, 16, 16];
5
+ const SEQ_A = [-1.025, -0.78, -0.65012, -0.19041574, -0.20819396, -0.421064, -0.32733846];
6
+ const SEQ_B = [-0.30419582, -0.36330363, -0.3566038, -0.34430745, -0.33699593, -0.30180866, -0.27321684];
7
+ const SEQ_C = [-1.2, -1.2, -0.8, -0.7, -0.7, -0.4, -0.5];
8
+ const DCT4X8_PARAMS = [[2198.0505, -0.96269625, -0.7619425, -0.65511405], [764.36554, -0.926302, -0.967523, -0.2784529], [527.10754, -1.4594386, -1.4500821, -1.5843723]];
9
+ const DCT4_PARAMS = [[2200.0, 0.0, 0.0, 0.0], [392.0, 0.0, 0.0, 0.0], [112.0, -0.25, -0.25, -0.5]];
10
+ const common = (a, b, c) => ({ mode: 'dct', dct: [[a, ...SEQ_A], [b, ...SEQ_B], [c, ...SEQ_C]] });
11
+ function defaultEncoding(index) {
12
+ switch (index) {
13
+ case 0: return { mode: 'dct', dct: [[3150.0, 0.0, -0.4, -0.4, -0.4, -2.0], [560.0, 0.0, -0.3, -0.3, -0.3, -0.3], [512.0, -2.0, -1.0, 0.0, -1.0, -2.0]] };
14
+ case 1: return { mode: 'hornuss', params: [[280.0, 3160.0, 3160.0], [60.0, 864.0, 864.0], [18.0, 200.0, 200.0]] };
15
+ case 2: return { mode: 'dct2', params: [[3840.0, 2560.0, 1280.0, 640.0, 480.0, 300.0], [960.0, 640.0, 320.0, 180.0, 140.0, 120.0], [640.0, 320.0, 128.0, 64.0, 32.0, 16.0]] };
16
+ case 3: return { mode: 'dct4', params: [[1, 1], [1, 1], [1, 1]], dct: DCT4_PARAMS };
17
+ case 4: return { mode: 'dct', dct: [[8996.873, -1.3000778, -0.4942453, -0.43909377, -0.6350102, -0.9017726, -1.6162099], [3191.4836, -0.67424583, -0.80745816, -0.4492584, -0.3586544, -0.3132239, -0.37615025], [1157.504, -2.0531423, -1.4, -0.5068713, -0.4270873, -1.4856834, -4.920914]] };
18
+ case 5: return { mode: 'dct', dct: [[15718.408, -1.025, -0.98, -0.9012, -0.4, -0.48819396, -0.421064, -0.27], [7305.7637, -0.8041958, -0.76330364, -0.5566038, -0.49785304, -0.43699592, -0.40180868, -0.27321684], [3803.5317, -3.0607336, -2.041327, -2.023565, -0.54953897, -0.4, -0.4, -0.3]] };
19
+ case 6: return { mode: 'dct', dct: [[7240.7734, -0.7, -0.7, -0.2, -0.2, -0.2, -0.5], [1448.1547, -0.5, -0.5, -0.5, -0.2, -0.2, -0.2], [506.85413, -1.4, -0.2, -0.5, -0.5, -1.5, -3.6]] };
20
+ case 7: return { mode: 'dct', dct: [[16283.249, -1.7812846, -1.6309059, -1.0382179, -0.85, -0.7, -0.9, -1.2360638], [5089.1577, -0.3200494, -0.3536285, -0.3034, -0.61, -0.5, -0.5, -0.6], [3397.7761, -0.32132736, -0.3450762, -0.7034, -0.9, -1.0, -1.0, -1.1754606]] };
21
+ case 8: return { mode: 'dct', dct: [[13844.971, -0.971138, -0.658, -0.42026, -0.22712, -0.2206, -0.226, -0.6], [4798.964, -0.6112531, -0.8377079, -0.7901486, -0.26927274, -0.38272768, -0.22924222, -0.20719099], [1807.2369, -1.2, -1.2, -0.7, -0.7, -0.7, -0.4, -0.5]] };
22
+ case 9: return { mode: 'dct4x8', params: [[1], [1], [1]], dct: DCT4X8_PARAMS };
23
+ case 10: return {
24
+ mode: 'afv',
25
+ params: [[3072.0, 3072.0, 256.0, 256.0, 256.0, 414.0, 0.0, 0.0, 0.0], [1024.0, 1024.0, 50.0, 50.0, 50.0, 58.0, 0.0, 0.0, 0.0], [384.0, 384.0, 12.0, 12.0, 12.0, 22.0, -0.25, -0.25, -0.25]],
26
+ dct: DCT4X8_PARAMS, dct4x4: DCT4_PARAMS
27
+ };
28
+ case 11: return common(23966.166, 8380.191, 4493.024);
29
+ case 12: return common(15358.898, 5597.3604, 2919.9617);
30
+ case 13: return common(47932.332, 16760.383, 8986.048);
31
+ case 14: return common(30717.797, 11194.721, 5839.9233);
32
+ case 15: return common(95864.664, 33520.766, 17972.096);
33
+ default: return common(61435.594, 24209.441, 12979.847);
34
+ }
35
+ }
36
+ function interpolate(pos, max, bands) {
37
+ if (bands.length === 1)
38
+ return bands[0];
39
+ const scaled = f32(pos * (bands.length - 1) / max), index = Math.trunc(scaled), frac = f32(scaled - index);
40
+ const a = bands[index], b = bands[index + 1];
41
+ return f32(a * f32((b / a) ** frac));
42
+ }
43
+ const mult = (x) => x > 0 ? 1 + x : 1 / (1 - x);
44
+ function dctWeights(params, w, h) {
45
+ const bands = [params[0]];
46
+ for (let i = 1; i < params.length; i++) {
47
+ const band = f32(bands[i - 1] * f32(mult(params[i])));
48
+ if (band <= 0)
49
+ throw new Error('JPEG XL: invalid dequantization matrix');
50
+ bands.push(band);
51
+ }
52
+ const out = new Float32Array(w * h);
53
+ for (let y = 0; y < h; y++) {
54
+ for (let x = 0; x < w; x++) {
55
+ const dx = f32(x / (w - 1)), dy = f32(y / (h - 1));
56
+ out[y * w + x] = interpolate(f32(Math.sqrt(f32(dx * dx + dy * dy))), f32(Math.SQRT2 + 1e-6), bands);
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+ function weights(e, index) {
62
+ const [w, h] = MATRIX_SIZES[index];
63
+ switch (e.mode) {
64
+ case 'dct': return e.dct.map(p => dctWeights(p, w, h));
65
+ case 'hornuss': return e.params.map(p => {
66
+ const m = new Float32Array(64).fill(p[0]);
67
+ m[0] = 1;
68
+ m[1] = m[8] = p[1];
69
+ m[9] = p[2];
70
+ return m;
71
+ });
72
+ case 'dct2': return e.params.map(p => {
73
+ const m = new Float32Array(64);
74
+ m[0] = 1;
75
+ p.forEach((v, i) => {
76
+ const dim = 1 << (i >> 1);
77
+ if (i % 2 === 0) {
78
+ for (let y = 0; y < dim; y++)
79
+ for (let x = dim; x < 2 * dim; x++)
80
+ m[y * 8 + x] = m[x * 8 + y] = v;
81
+ }
82
+ else
83
+ for (let y = dim; y < 2 * dim; y++)
84
+ for (let x = dim; x < 2 * dim; x++)
85
+ m[y * 8 + x] = v;
86
+ });
87
+ return m;
88
+ });
89
+ case 'dct4': return e.params.map((p, c) => {
90
+ const mat = dctWeights(e.dct[c], 4, 4), m = new Float32Array(64);
91
+ for (let y = 0; y < 4; y++) {
92
+ for (let x = 0; x < 4; x++) {
93
+ const v = mat[y * 4 + x];
94
+ m[y * 16 + x * 2] = m[y * 16 + x * 2 + 1] = m[(y * 2 + 1) * 8 + x * 2] = m[(y * 2 + 1) * 8 + x * 2 + 1] = v;
95
+ }
96
+ }
97
+ m[1] /= p[0];
98
+ m[8] /= p[0];
99
+ m[9] /= p[1];
100
+ return m;
101
+ });
102
+ case 'dct4x8': return e.params.map((p, c) => {
103
+ const mat = dctWeights(e.dct[c], 8, 4), m = new Float32Array(64);
104
+ for (let y = 0; y < 4; y++)
105
+ for (let k = 0; k < 2; k++)
106
+ m.set(mat.subarray(y * 8, y * 8 + 8), (y * 2 + k) * 8);
107
+ m[8] /= p[0];
108
+ return m;
109
+ });
110
+ case 'afv': return e.params.map((p, c) => {
111
+ const FREQS = [0, 0, 0.8517779, 5.3777843, 0, 0, 4.734748, 5.4492455, 1.659827, 4.0, 7.275749, 10.423227, 2.6629324, 7.6306577, 8.962389, 12.971662];
112
+ const lo = FREQS[2], hi = FREQS[15];
113
+ const w4x8 = dctWeights(e.dct[c], 8, 4), w4x4 = dctWeights(e.dct4x4[c], 4, 4);
114
+ const bands = [p[5]];
115
+ for (let i = 1; i < 4; i++)
116
+ bands.push(f32(bands[i - 1] * f32(mult(p[5 + i]))));
117
+ const m = new Float32Array(64);
118
+ for (let y = 0; y < 4; y++) {
119
+ for (let x = 0; x < 4; x++) {
120
+ m[16 * y + 2 * x] = x === 0 && y === 0 ? 1 : x === 0 && y === 1 ? p[2] : x === 1 && y === 0 ? p[3] : x === 1 && y === 1 ? p[4] :
121
+ interpolate(f32(FREQS[y * 4 + x] - lo), f32(hi - lo + 1e-6), bands);
122
+ }
123
+ }
124
+ for (let y = 0; y < 4; y++) {
125
+ for (let x = 0; x < 8; x++)
126
+ m[16 * y + 8 + x] = y === 0 && x === 0 ? p[0] : w4x8[y * 8 + x];
127
+ for (let x = 0; x < 4; x++)
128
+ m[16 * y + 2 * x + 1] = y === 0 && x === 0 ? p[1] : w4x4[y * 4 + x];
129
+ }
130
+ return m;
131
+ });
132
+ default: return e.values.map(v => Float32Array.from(v, q => q * e.denominator));
133
+ }
134
+ }
135
+ export function readDequantMatrices(r, bitDepth, stream, tree) {
136
+ const encodings = [];
137
+ const allDefault = r.bool();
138
+ for (let i = 0; i < 17; i++) {
139
+ if (allDefault) {
140
+ encodings.push(DEFAULTS[i]);
141
+ continue;
142
+ }
143
+ const mode = r.bits(3);
144
+ if (mode >= 1 && mode <= 5 && ![0, 1, 2, 3, 9, 10].includes(i))
145
+ throw new Error('JPEG XL: invalid dequantization matrix encoding');
146
+ const fixed = (n) => [0, 1, 2].map(() => Array.from({ length: n }, () => r.f16()));
147
+ const dctParams = () => {
148
+ const n = r.bits(4) + 1;
149
+ const p = [0, 1, 2].map(() => Array.from({ length: n }, () => r.f16()));
150
+ for (const c of p)
151
+ c[0] *= 64;
152
+ return p;
153
+ };
154
+ switch (mode) {
155
+ case 0:
156
+ encodings.push(DEFAULTS[i]);
157
+ break;
158
+ case 1:
159
+ encodings.push({ mode: 'hornuss', params: fixed(3) });
160
+ break;
161
+ case 2:
162
+ encodings.push({ mode: 'dct2', params: fixed(6) });
163
+ break;
164
+ case 3:
165
+ encodings.push({ mode: 'dct4', params: fixed(2), dct: dctParams() });
166
+ break;
167
+ case 4:
168
+ encodings.push({ mode: 'dct4x8', params: fixed(1), dct: dctParams() });
169
+ break;
170
+ case 5: {
171
+ const params = fixed(9);
172
+ for (const c of params)
173
+ for (let k = 0; k < 6; k++)
174
+ c[k] *= 64;
175
+ encodings.push({ mode: 'afv', params, dct: dctParams(), dct4x4: dctParams() });
176
+ break;
177
+ }
178
+ case 6:
179
+ encodings.push({ mode: 'dct', dct: dctParams() });
180
+ break;
181
+ case 7: {
182
+ const [w, h] = MATRIX_SIZES[i], denominator = r.f16();
183
+ const image = new ModularImage([channel(w, h), channel(w, h), channel(w, h)], bitDepth);
184
+ decodeModular(r, image, stream + i, tree, Infinity, true);
185
+ encodings.push({ mode: 'raw', denominator, values: image.channels.map(c => c.data) });
186
+ break;
187
+ }
188
+ default: throw new Error('JPEG XL: invalid dequantization matrix encoding');
189
+ }
190
+ }
191
+ const matrices = [], transposed = [];
192
+ encodings.forEach((e, i) => {
193
+ const [m, t] = e === DEFAULTS[i] ? defaultMatrices(i) : matrix(e, i);
194
+ matrices.push(m);
195
+ transposed.push(t);
196
+ });
197
+ return { matrices, transposed };
198
+ }
199
+ function matrix(e, i) {
200
+ const m = weights(e, i);
201
+ if (e.mode !== 'raw')
202
+ for (const c of m)
203
+ for (let k = 0; k < c.length; k++)
204
+ c[k] = 1 / c[k];
205
+ for (const c of m)
206
+ for (const v of c)
207
+ if (!(v > 0 && v < 1e8))
208
+ throw new Error('JPEG XL: invalid dequantization matrix');
209
+ const [w, h] = MATRIX_SIZES[i];
210
+ return [m, m.map(c => {
211
+ const t = new Float32Array(c.length);
212
+ for (let k = 0; k < c.length; k++)
213
+ t[k] = c[(k % h) * w + Math.floor(k / h)];
214
+ return t;
215
+ })];
216
+ }
217
+ const DEFAULTS = Array.from({ length: 17 }, (_, i) => defaultEncoding(i));
218
+ const defaultCache = [];
219
+ const defaultMatrices = (i) => defaultCache[i] ??= matrix(DEFAULTS[i], i);
@@ -0,0 +1,52 @@
1
+ export function mirror(i, len) {
2
+ for (;;) {
3
+ if (i < 0)
4
+ i = -i - 1;
5
+ else if (i >= len)
6
+ i = 2 * len - i - 1;
7
+ else
8
+ return i;
9
+ }
10
+ }
11
+ export function upsample(src, w, h, factor, image, outW, outH) {
12
+ const weights = factor === 2 ? image.up2 : factor === 4 ? image.up4 : image.up8;
13
+ const half = factor / 2;
14
+ const kernels = new Float32Array(half * half * 25);
15
+ let k = 0;
16
+ for (let y = 0; y < 5 * half; y++) {
17
+ for (let x = y; x < 5 * half; x++) {
18
+ const v = weights[k++];
19
+ kernels[(Math.floor(y / 5) * half + Math.floor(x / 5)) * 25 + (y % 5) * 5 + x % 5] = v;
20
+ kernels[(Math.floor(x / 5) * half + Math.floor(y / 5)) * 25 + (x % 5) * 5 + y % 5] = v;
21
+ }
22
+ }
23
+ const pw = w + 4, padded = new Float32Array(pw * (h + 4));
24
+ for (let y = 0; y < h + 4; y++) {
25
+ const sy = mirror(y - 2, h);
26
+ for (let x = 0; x < pw; x++)
27
+ padded[y * pw + x] = src[sy * w + mirror(x - 2, w)];
28
+ }
29
+ const out = new Float32Array(outW * outH), window = new Float32Array(25);
30
+ for (let y = 0; y < outH; y++) {
31
+ const ry = Math.floor(y / factor), fy = y % factor, my = Math.min(fy, factor - fy - 1), flipV = fy >= half;
32
+ for (let x = 0; x < outW; x++) {
33
+ const rx = Math.floor(x / factor), fx = x % factor, mx = Math.min(fx, factor - fx - 1), flipH = fx >= half;
34
+ const kernel = (my * half + mx) * 25;
35
+ let sum = 0, min = Infinity, max = -Infinity;
36
+ for (let iy = 0; iy < 5; iy++) {
37
+ const ky = flipV ? 4 - iy : iy, row = (ry + iy) * pw + rx;
38
+ for (let ix = 0; ix < 5; ix++) {
39
+ const kx = flipH ? 4 - ix : ix, v = padded[row + ix];
40
+ sum += kernels[kernel + ky * 5 + kx] * v;
41
+ if (v < min)
42
+ min = v;
43
+ if (v > max)
44
+ max = v;
45
+ }
46
+ }
47
+ out[y * outW + x] = min > max ? NaN : sum < min ? min : sum > max ? max : sum;
48
+ }
49
+ }
50
+ void window;
51
+ return out;
52
+ }