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.
- package/README.md +28 -8
- package/THIRD_PARTY_NOTICES.md +167 -2
- package/dist/animation.d.ts +18 -8
- package/dist/animation.js +23 -2
- package/dist/codecs/av1/cdef.js +197 -0
- package/dist/codecs/av1/data.js +141 -0
- package/dist/codecs/av1/decode.js +1769 -0
- package/dist/codecs/av1/filmgrain.js +219 -0
- package/dist/codecs/av1/frame.js +114 -0
- package/dist/codecs/av1/ipred.js +491 -0
- package/dist/codecs/av1/itx.js +950 -0
- package/dist/codecs/av1/loopfilter.js +149 -0
- package/dist/codecs/av1/msac.js +161 -0
- package/dist/codecs/av1/obu.js +516 -0
- package/dist/codecs/av1/postfilter.js +28 -0
- package/dist/codecs/av1/restoration.js +193 -0
- package/dist/codecs/av1/tables.js +160 -0
- package/dist/codecs/avif.js +581 -0
- package/dist/codecs/bmp.js +317 -0
- package/dist/codecs/hdr.d.ts +25 -0
- package/dist/codecs/hdr.js +201 -0
- package/dist/codecs/ico.js +48 -0
- package/dist/codecs/jpeg.js +2 -1
- package/dist/codecs/jxl/bits.js +126 -0
- package/dist/codecs/jxl/blend.js +117 -0
- package/dist/codecs/jxl/color.js +116 -0
- package/dist/codecs/jxl/dct.js +404 -0
- package/dist/codecs/jxl/entropy.js +556 -0
- package/dist/codecs/jxl/features.js +325 -0
- package/dist/codecs/jxl/filters.js +119 -0
- package/dist/codecs/jxl/frame-header.js +195 -0
- package/dist/codecs/jxl/frame.js +319 -0
- package/dist/codecs/jxl/headers.js +249 -0
- package/dist/codecs/jxl/idct.js +484 -0
- package/dist/codecs/jxl/modular.js +688 -0
- package/dist/codecs/jxl/quant.js +219 -0
- package/dist/codecs/jxl/upsample.js +52 -0
- package/dist/codecs/jxl/vardct.js +472 -0
- package/dist/codecs/jxl.js +89 -0
- package/dist/codecs/netpbm.js +239 -0
- package/dist/codecs/qoi.js +150 -0
- package/dist/codecs/vp8-enc-dsp.js +932 -0
- package/dist/codecs/vp8-enc-tables.js +78 -0
- package/dist/codecs/vp8-enc.js +1930 -0
- package/dist/codecs/webp.js +36 -2
- package/dist/image-type.d.ts +15 -1
- package/dist/image-type.js +45 -2
- package/dist/image.d.ts +47 -6
- package/dist/image.js +49 -3
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -2
- package/dist/render/hinting.js +26 -18
- package/dist/render/layout.js +1 -1
- package/dist/render/svg.js +1 -1
- package/dist/render/unicode.js +1 -9
- package/dist/util/bytes.js +9 -0
- package/dist/util/resample.js +4 -2
- package/dist/version.js +1 -1
- package/package.json +25 -2
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* AV1 superres upscaling and loop restoration (Wiener and self guided filters), as the AV1 specification describes them
|
|
3
|
+
* (sections 7.16, 7.17) and dav1d implements them (src/looprestoration_tmpl.c, src/mc_tmpl.c), with dav1d's tables.
|
|
4
|
+
* Copyright (c) 2018-2021, VideoLAN and dav1d authors, Copyright (c) 2018, Two Orioles, LLC, BSD-2-Clause License (see
|
|
5
|
+
* THIRD_PARTY_NOTICES.md)
|
|
6
|
+
*/
|
|
7
|
+
import { RESTORATION_NONE, RESTORATION_WIENER } from "./obu.js";
|
|
8
|
+
import { RESIZE_FILTER } from "./tables.js";
|
|
9
|
+
export function superres(f, planes) {
|
|
10
|
+
const out = [], strides = [];
|
|
11
|
+
const max = f.bitdepthMax;
|
|
12
|
+
for (let p = 0; p < planes.length; p++) {
|
|
13
|
+
const subX = p ? f.ssx : 0, subY = p ? f.ssy : 0;
|
|
14
|
+
const downW = f.width + subX >> subX, upW = f.hdr.upscaledWidth + subX >> subX, h = f.height + subY >> subY;
|
|
15
|
+
const stepX = Math.floor(((downW << 14) + (upW >> 1)) / upW);
|
|
16
|
+
const err = upW * stepX - (downW << 14);
|
|
17
|
+
let initialSubpelX = Math.trunc((-((upW - downW) << 13) + (upW >> 1)) / upW) + (1 << 7) - Math.trunc(err / 2);
|
|
18
|
+
initialSubpelX &= (1 << 14) - 1;
|
|
19
|
+
const maxX = ((f.bw >> subX) * 4) - 1;
|
|
20
|
+
const src = planes[p], srcStride = f.strides[p];
|
|
21
|
+
const stride = upW + 31 & ~31;
|
|
22
|
+
const dst = new Uint16Array(stride * (h + 8));
|
|
23
|
+
for (let y = 0; y < h; y++) {
|
|
24
|
+
for (let x = 0; x < upW; x++) {
|
|
25
|
+
const srcX = -(1 << 14) + initialSubpelX + x * stepX;
|
|
26
|
+
const px = srcX >> 14, subpel = (srcX & (1 << 14) - 1) >> 8;
|
|
27
|
+
let sum = 0;
|
|
28
|
+
for (let k = 0; k < 8; k++) {
|
|
29
|
+
const sx = Math.min(maxX, Math.max(0, px + k - 3));
|
|
30
|
+
sum -= src[y * srcStride + sx] * RESIZE_FILTER[subpel * 8 + k];
|
|
31
|
+
}
|
|
32
|
+
const v = (sum + 64) >> 7;
|
|
33
|
+
dst[y * stride + x] = v < 0 ? 0 : v > max ? max : v;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
out.push(dst);
|
|
37
|
+
strides.push(stride);
|
|
38
|
+
}
|
|
39
|
+
return { planes: out, strides };
|
|
40
|
+
}
|
|
41
|
+
const SGR = [
|
|
42
|
+
[2, 12, 1, 4], [2, 15, 1, 6], [2, 18, 1, 8], [2, 21, 1, 9], [2, 24, 1, 10], [2, 29, 1, 11], [2, 36, 1, 12],
|
|
43
|
+
[2, 45, 1, 13], [2, 56, 1, 14], [2, 68, 1, 15], [0, 0, 1, 5], [0, 0, 1, 8], [0, 0, 1, 11], [0, 0, 1, 14],
|
|
44
|
+
[2, 30, 0, 0], [2, 75, 0, 0]
|
|
45
|
+
];
|
|
46
|
+
export function loopRestoration(f, pre, cdef, out, strides) {
|
|
47
|
+
const hdr = f.hdr, bitdepth = f.bitdepth, max = f.bitdepthMax;
|
|
48
|
+
for (let p = 0; p < out.length; p++) {
|
|
49
|
+
if (hdr.restoration.types[p] === RESTORATION_NONE)
|
|
50
|
+
continue;
|
|
51
|
+
const subX = p ? f.ssx : 0, subY = p ? f.ssy : 0;
|
|
52
|
+
const planeW = hdr.upscaledWidth + subX >> subX, planeH = f.height + subY >> subY;
|
|
53
|
+
const unitSize = 1 << hdr.restoration.unitSizeLog2[p ? 1 : 0];
|
|
54
|
+
const unitCols = f.lrUnitsW[p], unitRows = f.lrUnitsH[p];
|
|
55
|
+
const stride = strides[p], cur = pre[p], cd = cdef[p], dst = out[p];
|
|
56
|
+
for (let stripe = 0; (-8 + stripe * 64) >> subY < planeH; stripe++) {
|
|
57
|
+
const stripeStart = (-8 + stripe * 64) >> subY, stripeEnd = stripeStart + (64 >> subY) - 1;
|
|
58
|
+
const y0 = Math.max(0, stripeStart), y1 = Math.min(planeH, stripeEnd + 1);
|
|
59
|
+
if (y0 >= y1)
|
|
60
|
+
continue;
|
|
61
|
+
const lumaRow = Math.max(0, stripe * 64 - 8) >> 2;
|
|
62
|
+
const unitRow = Math.min(unitRows - 1, Math.floor(((lumaRow * 4 + 8) >> subY) / unitSize));
|
|
63
|
+
const sample = (x, y) => {
|
|
64
|
+
x = Math.max(0, Math.min(planeW - 1, x));
|
|
65
|
+
y = Math.max(0, Math.min(planeH - 1, y));
|
|
66
|
+
if (y < stripeStart)
|
|
67
|
+
return cur[Math.max(stripeStart - 2, y) * stride + x];
|
|
68
|
+
if (y > stripeEnd)
|
|
69
|
+
return cur[Math.min(stripeEnd + 2, y) * stride + x];
|
|
70
|
+
return cd[y * stride + x];
|
|
71
|
+
};
|
|
72
|
+
for (let unitCol = 0; unitCol < unitCols; unitCol++) {
|
|
73
|
+
const x0 = unitCol * unitSize, x1 = unitCol === unitCols - 1 ? planeW : Math.min(planeW, x0 + unitSize);
|
|
74
|
+
const unit = f.lr[p][unitRow * unitCols + unitCol];
|
|
75
|
+
const w = x1 - x0, h = y1 - y0;
|
|
76
|
+
const ww = w + 6, win = new Int32Array(ww * (h + 6));
|
|
77
|
+
for (let y = 0; y < h + 6; y++)
|
|
78
|
+
for (let x = 0; x < ww; x++)
|
|
79
|
+
win[y * ww + x] = sample(x0 + x - 3, y0 + y - 3);
|
|
80
|
+
if (unit.type === RESTORATION_WIENER)
|
|
81
|
+
wiener(win, ww, w, h, unit.filterV, unit.filterH, bitdepth, dst, y0 * stride + x0, stride);
|
|
82
|
+
else if (unit.type !== RESTORATION_NONE)
|
|
83
|
+
selfGuided(win, ww, w, h, unit.type - 3, unit.sgrWeights, bitdepth, cd, dst, y0 * stride + x0, stride, max);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function wienerFilter(coeff) {
|
|
89
|
+
const filter = [coeff[0], coeff[1], coeff[2], 128, coeff[2], coeff[1], coeff[0]];
|
|
90
|
+
filter[3] -= 2 * (coeff[0] + coeff[1] + coeff[2]);
|
|
91
|
+
return filter;
|
|
92
|
+
}
|
|
93
|
+
function wiener(win, ww, w, h, v, hf, bitdepth, dst, d, stride) {
|
|
94
|
+
const round0 = bitdepth === 12 ? 5 : 3, round1 = bitdepth === 12 ? 9 : 11;
|
|
95
|
+
const vfilter = wienerFilter(v), hfilter = wienerFilter(hf);
|
|
96
|
+
const offset = 1 << (bitdepth + 7 - round0 - 1), limit = (1 << (bitdepth + 1 + 7 - round0)) - 1;
|
|
97
|
+
const max = (1 << bitdepth) - 1;
|
|
98
|
+
const inter = new Int32Array(w * (h + 6));
|
|
99
|
+
for (let r = 0; r < h + 6; r++) {
|
|
100
|
+
for (let c = 0; c < w; c++) {
|
|
101
|
+
let s = 0;
|
|
102
|
+
for (let t = 0; t < 7; t++)
|
|
103
|
+
s += hfilter[t] * win[r * ww + c + t];
|
|
104
|
+
const x = (s + (1 << (round0 - 1))) >> round0;
|
|
105
|
+
inter[r * w + c] = x < -offset ? -offset : x > limit - offset ? limit - offset : x;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (let r = 0; r < h; r++) {
|
|
109
|
+
for (let c = 0; c < w; c++) {
|
|
110
|
+
let s = 0;
|
|
111
|
+
for (let t = 0; t < 7; t++)
|
|
112
|
+
s += vfilter[t] * inter[(r + t) * w + c];
|
|
113
|
+
const x = (s + (1 << (round1 - 1))) >> round1;
|
|
114
|
+
dst[d + r * stride + c] = x < 0 ? 0 : x > max ? max : x;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function boxFilter(win, ww, w, h, r, eps, pass, bitdepth, cd, d, stride) {
|
|
119
|
+
const n = (2 * r + 1) * (2 * r + 1), n2e = n * n * eps;
|
|
120
|
+
const s = Math.floor(((1 << 20) + Math.floor(n2e / 2)) / n2e);
|
|
121
|
+
const oneOverN = Math.floor(((1 << 12) + (n >> 1)) / n);
|
|
122
|
+
const shiftA = 2 * (bitdepth - 8), shiftB = bitdepth - 8;
|
|
123
|
+
const aw = w + 2, A = new Int32Array(aw * (h + 2)), B = new Int32Array(aw * (h + 2));
|
|
124
|
+
const rowSum = new Int32Array(ww), rowSq = new Float64Array(ww);
|
|
125
|
+
for (let i = -1; i < h + 1; i++) {
|
|
126
|
+
if (pass === 0 && !(i & 1))
|
|
127
|
+
continue;
|
|
128
|
+
rowSum.fill(0);
|
|
129
|
+
rowSq.fill(0);
|
|
130
|
+
for (let dy = -r; dy <= r; dy++) {
|
|
131
|
+
const o = (i + dy + 3) * ww;
|
|
132
|
+
for (let x = 0; x < ww; x++) {
|
|
133
|
+
const c = win[o + x];
|
|
134
|
+
rowSum[x] += c;
|
|
135
|
+
rowSq[x] += c * c;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
for (let j = -1; j < w + 1; j++) {
|
|
139
|
+
let a = 0, b = 0;
|
|
140
|
+
for (let dx = -r; dx <= r; dx++) {
|
|
141
|
+
a += rowSq[j + dx + 3];
|
|
142
|
+
b += rowSum[j + dx + 3];
|
|
143
|
+
}
|
|
144
|
+
a = shiftA ? (a + (1 << (shiftA - 1))) >> shiftA : a;
|
|
145
|
+
const dd = shiftB ? (b + (1 << (shiftB - 1))) >> shiftB : b;
|
|
146
|
+
const p = Math.max(0, a * n - dd * dd);
|
|
147
|
+
const z = Math.floor((p * s + (1 << 19)) / (1 << 20));
|
|
148
|
+
const a2 = z >= 255 ? 256 : z === 0 ? 1 : Math.floor(((z << 8) + (z >> 1)) / (z + 1));
|
|
149
|
+
A[(i + 1) * aw + j + 1] = a2;
|
|
150
|
+
B[(i + 1) * aw + j + 1] = Math.floor(((256 - a2) * b * oneOverN + 2048) / 4096);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const F = new Int32Array(w * h);
|
|
154
|
+
for (let i = 0; i < h; i++) {
|
|
155
|
+
const shift = (pass === 0 && i & 1 ? 4 : 5) + 4, rnd = 1 << (shift - 1);
|
|
156
|
+
const up = i * aw, mid = (i + 1) * aw, down = (i + 2) * aw;
|
|
157
|
+
for (let j = 0; j < w; j++) {
|
|
158
|
+
let a, b;
|
|
159
|
+
if (pass === 0) {
|
|
160
|
+
if (i & 1) {
|
|
161
|
+
a = 6 * A[mid + j + 1] + 5 * (A[mid + j] + A[mid + j + 2]);
|
|
162
|
+
b = 6 * B[mid + j + 1] + 5 * (B[mid + j] + B[mid + j + 2]);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
a = 6 * (A[up + j + 1] + A[down + j + 1]) + 5 * (A[up + j] + A[up + j + 2] + A[down + j] + A[down + j + 2]);
|
|
166
|
+
b = 6 * (B[up + j + 1] + B[down + j + 1]) + 5 * (B[up + j] + B[up + j + 2] + B[down + j] + B[down + j + 2]);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
a = 4 * (A[up + j + 1] + A[mid + j] + A[mid + j + 1] + A[mid + j + 2] + A[down + j + 1]) + 3 * (A[up + j] + A[up + j + 2] + A[down + j] + A[down + j + 2]);
|
|
171
|
+
b = 4 * (B[up + j + 1] + B[mid + j] + B[mid + j + 1] + B[mid + j + 2] + B[down + j + 1]) + 3 * (B[up + j] + B[up + j + 2] + B[down + j] + B[down + j + 2]);
|
|
172
|
+
}
|
|
173
|
+
F[i * w + j] = (a * cd[d + i * stride + j] + b + rnd) >> shift;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return F;
|
|
177
|
+
}
|
|
178
|
+
function selfGuided(win, ww, w, h, set, weights, bitdepth, cd, dst, d, stride, max) {
|
|
179
|
+
const [r0, e0, r1, e1] = SGR[set];
|
|
180
|
+
const flt0 = r0 ? boxFilter(win, ww, w, h, r0, e0, 0, bitdepth, cd, d, stride) : null;
|
|
181
|
+
const flt1 = r1 ? boxFilter(win, ww, w, h, r1, e1, 1, bitdepth, cd, d, stride) : null;
|
|
182
|
+
const w0 = weights[0], w1 = weights[1], w2 = 128 - w0 - w1;
|
|
183
|
+
for (let i = 0; i < h; i++) {
|
|
184
|
+
for (let j = 0; j < w; j++) {
|
|
185
|
+
const u = cd[d + i * stride + j] << 4;
|
|
186
|
+
let v = w1 * u;
|
|
187
|
+
v += flt0 ? w0 * flt0[i * w + j] : w0 * u;
|
|
188
|
+
v += flt1 ? w2 * flt1[i * w + j] : w2 * u;
|
|
189
|
+
const s = (v + 1024) >> 11;
|
|
190
|
+
dst[d + i * stride + j] = s < 0 ? 0 : s > max ? max : s;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Constants and tables of the AV1 decoder, ported from dav1d (src/levels.h, src/intra_edge.c, src/qm.c, src/cdf.c).
|
|
3
|
+
* Copyright (c) 2018-2021, VideoLAN and dav1d authors, Copyright (c) 2018, Two Orioles, LLC, BSD-2-Clause License
|
|
4
|
+
* (see THIRD_PARTY_NOTICES.md)
|
|
5
|
+
*/
|
|
6
|
+
import * as data from "./data.js";
|
|
7
|
+
import { base64 } from "../../util/bytes.js";
|
|
8
|
+
import { decompress } from "../zlib.js";
|
|
9
|
+
export const BL_128X128 = 0, BL_64X64 = 1, BL_8X8 = 4;
|
|
10
|
+
export const BS_128x128 = 0, BS_64x64 = 3, BS_4x4 = 21;
|
|
11
|
+
export const PARTITION_NONE = 0, PARTITION_H = 1, PARTITION_V = 2, PARTITION_SPLIT = 3, PARTITION_T_TOP_SPLIT = 4, PARTITION_T_BOTTOM_SPLIT = 5, PARTITION_T_LEFT_SPLIT = 6, PARTITION_T_RIGHT_SPLIT = 7, PARTITION_H4 = 8, PARTITION_V4 = 9;
|
|
12
|
+
export const DC_PRED = 0, VERT_PRED = 1, HOR_PRED = 2, DIAG_DOWN_LEFT_PRED = 3, VERT_LEFT_PRED = 8, SMOOTH_PRED = 9, SMOOTH_V_PRED = 10, SMOOTH_H_PRED = 11, PAETH_PRED = 12, CFL_PRED = 13, FILTER_PRED = 13, LEFT_DC_PRED = 3, TOP_DC_PRED = 4, DC_128_PRED = 5, Z1_PRED = 6, Z2_PRED = 7, Z3_PRED = 8;
|
|
13
|
+
export const TX_4X4 = 0, TX_8X8 = 1, TX_16X16 = 2, TX_32X32 = 3, TX_64X64 = 4, RTX_4X8 = 5;
|
|
14
|
+
export const DCT_DCT = 0, IDTX = 9, WHT_WHT = 16;
|
|
15
|
+
export const TX_CLASS_2D = 0, TX_CLASS_H = 1, TX_CLASS_V = 2;
|
|
16
|
+
export const EDGE_I444_TOP_HAS_RIGHT = 1, EDGE_I422_TOP_HAS_RIGHT = 2, EDGE_I420_TOP_HAS_RIGHT = 4, EDGE_I444_LEFT_HAS_BOTTOM = 8, EDGE_I422_LEFT_HAS_BOTTOM = 16, EDGE_I420_LEFT_HAS_BOTTOM = 32, EDGE_ALL_TOP_HAS_RIGHT = 7, EDGE_ALL_LEFT_HAS_BOTTOM = 56, EDGE_ALL_TR_AND_BL = 63;
|
|
17
|
+
export const { AL_PART_CTX, BLOCK_SIZES, BLOCK_DIMENSIONS, TXFM_DIMENSIONS, MAX_TXFM_SIZE_FOR_BS, TXTP_FROM_UVMODE, PARTITION_TYPE_COUNT, TX_TYPES_PER_SET, FILTER_MODE_TO_Y_MODE, LO_CTX_OFFSETS, SKIP_CTX, TX_TYPE_CLASS, INTRA_MODE_CONTEXT, CDEF_DIRECTIONS, SGR_PARAMS, SGR_X_BY_X, SM_WEIGHTS, DR_INTRA_DERIVATIVE, FILTER_INTRA_TAPS, RESIZE_FILTER, CDF, SCAN_OFFSETS } = data;
|
|
18
|
+
export const CFL_ALLOWED_MASK = (1 << 7) | (1 << 8) | (1 << 9) | (1 << 11) | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 15) |
|
|
19
|
+
(1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21);
|
|
20
|
+
let tables = null;
|
|
21
|
+
function load() {
|
|
22
|
+
if (tables)
|
|
23
|
+
return tables;
|
|
24
|
+
const at = data.PACKED_AT;
|
|
25
|
+
const blob = decompress(base64(data.PACKED), at.size[1]);
|
|
26
|
+
const bytes = ([offset, size]) => blob.subarray(offset, offset + size);
|
|
27
|
+
const words = ([offset, size]) => {
|
|
28
|
+
const w = new Uint16Array(size >> 1);
|
|
29
|
+
for (let i = 0; i < w.length; i++)
|
|
30
|
+
w[i] = blob[offset + i * 2] | blob[offset + i * 2 + 1] << 8;
|
|
31
|
+
return w;
|
|
32
|
+
};
|
|
33
|
+
return tables = {
|
|
34
|
+
modeCdfs: words(at.modeCdfs),
|
|
35
|
+
coefCdfs: [at.coefCdfs0, at.coefCdfs1, at.coefCdfs2, at.coefCdfs3].map(words),
|
|
36
|
+
scans: words(at.scans),
|
|
37
|
+
dq: words(at.dq),
|
|
38
|
+
qm: buildQm(bytes(at.qm)),
|
|
39
|
+
gaussianSequence: new Int16Array(words(at.gaussianSequence))
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function gaussianSequence() {
|
|
43
|
+
return load().gaussianSequence;
|
|
44
|
+
}
|
|
45
|
+
export function defaultCdfs(qidx) {
|
|
46
|
+
const t = load();
|
|
47
|
+
const cdf = new Uint16Array(CDF.size);
|
|
48
|
+
cdf.set(t.modeCdfs);
|
|
49
|
+
cdf.set(t.coefCdfs[(qidx > 20 ? 1 : 0) + (qidx > 60 ? 1 : 0) + (qidx > 120 ? 1 : 0)], t.modeCdfs.length);
|
|
50
|
+
return cdf;
|
|
51
|
+
}
|
|
52
|
+
export function scan(tx) {
|
|
53
|
+
const t = load();
|
|
54
|
+
const w = Math.min(TXFM_DIMENSIONS[tx * 8] * 4, 32), h = Math.min(TXFM_DIMENSIONS[tx * 8 + 1] * 4, 32);
|
|
55
|
+
return t.scans.subarray(SCAN_OFFSETS[tx], SCAN_OFFSETS[tx] + w * h);
|
|
56
|
+
}
|
|
57
|
+
export function dequant(hbd, qidx, ac) {
|
|
58
|
+
return load().dq[(hbd * 256 + qidx) * 2 + ac];
|
|
59
|
+
}
|
|
60
|
+
export function quantizerMatrix(level, chroma, tx) {
|
|
61
|
+
return load().qm[level][chroma][tx];
|
|
62
|
+
}
|
|
63
|
+
function buildQm(src) {
|
|
64
|
+
const subsample = (s, o, h, hstep, vstep) => {
|
|
65
|
+
const out = [];
|
|
66
|
+
for (let y = 0; y < h; y += vstep)
|
|
67
|
+
for (let x = 0; x < 32; x += hstep)
|
|
68
|
+
out.push(s[o + y * 32 + x]);
|
|
69
|
+
return Uint8Array.from(out);
|
|
70
|
+
};
|
|
71
|
+
const transpose = (s, w, h) => {
|
|
72
|
+
const d = new Uint8Array(w * h);
|
|
73
|
+
for (let y = 0; y < h; y++)
|
|
74
|
+
for (let x = 0; x < w; x++)
|
|
75
|
+
d[x * h + y] = s[y * w + x];
|
|
76
|
+
return d;
|
|
77
|
+
};
|
|
78
|
+
const result = [];
|
|
79
|
+
for (let i = 0; i < 15; i++) {
|
|
80
|
+
const level = [];
|
|
81
|
+
for (let j = 0; j < 2; j++) {
|
|
82
|
+
const t32x16 = src.subarray((i * 2 + j) * 512, (i * 2 + j + 1) * 512);
|
|
83
|
+
const tri = src.subarray(15 * 2 * 512 + (i * 2 + j) * 528);
|
|
84
|
+
const t32x32 = new Uint8Array(1024);
|
|
85
|
+
for (let y = 0, o = 0; y < 32; y++)
|
|
86
|
+
for (let x = 0; x <= y; x++, o++)
|
|
87
|
+
t32x32[y * 32 + x] = t32x32[x * 32 + y] = tri[o];
|
|
88
|
+
const t4x4 = subsample(t32x32, 32 * 3 + 3, 32, 8, 8);
|
|
89
|
+
const t8x4 = subsample(t32x16, 32 + 1, 16, 4, 4);
|
|
90
|
+
const t8x8 = subsample(t32x32, 32 + 1, 32, 4, 4);
|
|
91
|
+
const t16x4 = subsample(t32x16, 32, 16, 2, 4);
|
|
92
|
+
const t16x8 = subsample(t32x16, 0, 16, 2, 2);
|
|
93
|
+
const t16x16 = subsample(t32x32, 0, 32, 2, 2);
|
|
94
|
+
const t32x8 = subsample(t32x16, 0, 16, 1, 2);
|
|
95
|
+
const t4x8 = transpose(t8x4, 8, 4), t4x16 = transpose(t16x4, 16, 4), t8x16 = transpose(t16x8, 16, 8);
|
|
96
|
+
const t8x32 = transpose(t32x8, 32, 8), t16x32 = transpose(t32x16, 32, 16);
|
|
97
|
+
const byTx = [];
|
|
98
|
+
byTx[TX_4X4] = t4x4;
|
|
99
|
+
byTx[TX_8X8] = t8x8;
|
|
100
|
+
byTx[TX_16X16] = t16x16;
|
|
101
|
+
byTx[TX_32X32] = t32x32;
|
|
102
|
+
byTx[TX_64X64] = t32x32;
|
|
103
|
+
byTx[5] = t8x4;
|
|
104
|
+
byTx[6] = t4x8;
|
|
105
|
+
byTx[7] = t16x8;
|
|
106
|
+
byTx[8] = t8x16;
|
|
107
|
+
byTx[9] = t32x16;
|
|
108
|
+
byTx[10] = t16x32;
|
|
109
|
+
byTx[11] = t32x32;
|
|
110
|
+
byTx[12] = t32x32;
|
|
111
|
+
byTx[13] = t16x4;
|
|
112
|
+
byTx[14] = t4x16;
|
|
113
|
+
byTx[15] = t32x8;
|
|
114
|
+
byTx[16] = t8x32;
|
|
115
|
+
byTx[17] = t32x16;
|
|
116
|
+
byTx[18] = t16x32;
|
|
117
|
+
level.push(byTx);
|
|
118
|
+
}
|
|
119
|
+
result.push(level);
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
function initEdges(bl, flags) {
|
|
124
|
+
const node = { o: flags, h: [flags | EDGE_ALL_LEFT_HAS_BOTTOM, 0], v: [flags | EDGE_ALL_TOP_HAS_RIGHT, 0], h4: 0, v4: 0, split: [], tip: [] };
|
|
125
|
+
if (bl === BL_8X8) {
|
|
126
|
+
node.h[1] = flags & (EDGE_ALL_LEFT_HAS_BOTTOM | EDGE_I420_TOP_HAS_RIGHT);
|
|
127
|
+
node.v[1] = flags & (EDGE_ALL_TOP_HAS_RIGHT | EDGE_I420_LEFT_HAS_BOTTOM | EDGE_I422_LEFT_HAS_BOTTOM);
|
|
128
|
+
node.tip = [
|
|
129
|
+
flags & EDGE_ALL_TOP_HAS_RIGHT | EDGE_I422_LEFT_HAS_BOTTOM,
|
|
130
|
+
flags | EDGE_I444_TOP_HAS_RIGHT,
|
|
131
|
+
flags & (EDGE_I420_TOP_HAS_RIGHT | EDGE_I420_LEFT_HAS_BOTTOM | EDGE_I422_LEFT_HAS_BOTTOM)
|
|
132
|
+
];
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
node.h[1] = flags & EDGE_ALL_LEFT_HAS_BOTTOM;
|
|
136
|
+
node.v[1] = flags & EDGE_ALL_TOP_HAS_RIGHT;
|
|
137
|
+
node.h4 = EDGE_ALL_LEFT_HAS_BOTTOM;
|
|
138
|
+
node.v4 = EDGE_ALL_TOP_HAS_RIGHT;
|
|
139
|
+
if (bl === 3) {
|
|
140
|
+
node.h4 |= flags & EDGE_I420_TOP_HAS_RIGHT;
|
|
141
|
+
node.v4 |= flags & (EDGE_I420_LEFT_HAS_BOTTOM | EDGE_I422_LEFT_HAS_BOTTOM);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return node;
|
|
145
|
+
}
|
|
146
|
+
function initModeNode(bl, topHasRight, leftHasBottom) {
|
|
147
|
+
const node = initEdges(bl, (topHasRight ? EDGE_ALL_TOP_HAS_RIGHT : 0) | (leftHasBottom ? EDGE_ALL_LEFT_HAS_BOTTOM : 0));
|
|
148
|
+
for (let n = 0; n < 4; n++) {
|
|
149
|
+
const tr = !(n === 3 || n === 1 && !topHasRight), lb = n === 0 || n === 2 && leftHasBottom;
|
|
150
|
+
node.split.push(bl === 3
|
|
151
|
+
? initEdges(bl + 1, (tr ? EDGE_ALL_TOP_HAS_RIGHT : 0) | (lb ? EDGE_ALL_LEFT_HAS_BOTTOM : 0))
|
|
152
|
+
: initModeNode(bl + 1, tr, lb));
|
|
153
|
+
}
|
|
154
|
+
return node;
|
|
155
|
+
}
|
|
156
|
+
let edgeTrees = null;
|
|
157
|
+
export function edgeTree(sb128) {
|
|
158
|
+
edgeTrees ??= [initModeNode(BL_128X128, true, false), initModeNode(BL_64X64, true, false)];
|
|
159
|
+
return edgeTrees[sb128 ? 0 : 1];
|
|
160
|
+
}
|