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,491 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* AV1 intra prediction: the edges of a block, and DC, directional, smooth, Paeth, filter, chroma from luma and
|
|
3
|
+
* palette prediction, ported from dav1d (src/ipred_prepare_tmpl.c, src/ipred_tmpl.c). Copyright (c) 2018-2021,
|
|
4
|
+
* VideoLAN and dav1d authors, Copyright (c) 2018, Two Orioles, LLC, BSD-2-Clause License (see THIRD_PARTY_NOTICES.md)
|
|
5
|
+
*/
|
|
6
|
+
import { DC_PRED, VERT_PRED, HOR_PRED, VERT_LEFT_PRED, SMOOTH_PRED, SMOOTH_V_PRED, SMOOTH_H_PRED, PAETH_PRED, FILTER_PRED, LEFT_DC_PRED, TOP_DC_PRED, DC_128_PRED, Z1_PRED, Z2_PRED, Z3_PRED, EDGE_I444_TOP_HAS_RIGHT, EDGE_I444_LEFT_HAS_BOTTOM, SM_WEIGHTS, DR_INTRA_DERIVATIVE, FILTER_INTRA_TAPS } from "./tables.js";
|
|
7
|
+
export const ANGLE_USE_EDGE_FILTER = 1024, ANGLE_SMOOTH_EDGE = 512;
|
|
8
|
+
export const EDGE = 128;
|
|
9
|
+
export const edgeBuffer = new Uint16Array(2 * EDGE + 1);
|
|
10
|
+
const MODE_TO_ANGLE = [90, 180, 45, 135, 113, 157, 203, 67];
|
|
11
|
+
const NEEDS_LEFT = 1, NEEDS_TOP = 2, NEEDS_TOPLEFT = 4, NEEDS_TOPRIGHT = 8, NEEDS_BOTTOMLEFT = 16;
|
|
12
|
+
const NEEDS = [];
|
|
13
|
+
NEEDS[DC_PRED] = NEEDS_TOP | NEEDS_LEFT;
|
|
14
|
+
NEEDS[VERT_PRED] = NEEDS_TOP;
|
|
15
|
+
NEEDS[HOR_PRED] = NEEDS_LEFT;
|
|
16
|
+
NEEDS[LEFT_DC_PRED] = NEEDS_LEFT;
|
|
17
|
+
NEEDS[TOP_DC_PRED] = NEEDS_TOP;
|
|
18
|
+
NEEDS[DC_128_PRED] = 0;
|
|
19
|
+
NEEDS[Z1_PRED] = NEEDS_TOP | NEEDS_TOPRIGHT | NEEDS_TOPLEFT;
|
|
20
|
+
NEEDS[Z2_PRED] = NEEDS_LEFT | NEEDS_TOP | NEEDS_TOPLEFT;
|
|
21
|
+
NEEDS[Z3_PRED] = NEEDS_LEFT | NEEDS_BOTTOMLEFT | NEEDS_TOPLEFT;
|
|
22
|
+
NEEDS[SMOOTH_PRED] = NEEDS[SMOOTH_V_PRED] = NEEDS[SMOOTH_H_PRED] = NEEDS_LEFT | NEEDS_TOP;
|
|
23
|
+
NEEDS[PAETH_PRED] = NEEDS[FILTER_PRED] = NEEDS_LEFT | NEEDS_TOP | NEEDS_TOPLEFT;
|
|
24
|
+
export let preparedAngle = 0;
|
|
25
|
+
export function prepareEdges(x, haveLeft, y, haveTop, w, h, edgeFlags, pic, dst, stride, mode, angle, tw, th, filterEdge, bitdepth) {
|
|
26
|
+
const e = edgeBuffer;
|
|
27
|
+
if (mode >= VERT_PRED && mode <= VERT_LEFT_PRED) {
|
|
28
|
+
angle = MODE_TO_ANGLE[mode - VERT_PRED] + 3 * angle;
|
|
29
|
+
if (angle <= 90)
|
|
30
|
+
mode = angle < 90 && haveTop ? Z1_PRED : VERT_PRED;
|
|
31
|
+
else if (angle < 180)
|
|
32
|
+
mode = Z2_PRED;
|
|
33
|
+
else
|
|
34
|
+
mode = angle > 180 && haveLeft ? Z3_PRED : HOR_PRED;
|
|
35
|
+
}
|
|
36
|
+
else if (mode === DC_PRED) {
|
|
37
|
+
mode = haveLeft ? haveTop ? DC_PRED : LEFT_DC_PRED : haveTop ? TOP_DC_PRED : DC_128_PRED;
|
|
38
|
+
}
|
|
39
|
+
else if (mode === PAETH_PRED) {
|
|
40
|
+
mode = haveLeft ? haveTop ? PAETH_PRED : HOR_PRED : haveTop ? VERT_PRED : DC_128_PRED;
|
|
41
|
+
}
|
|
42
|
+
preparedAngle = angle;
|
|
43
|
+
const needs = NEEDS[mode];
|
|
44
|
+
const top = dst - stride;
|
|
45
|
+
if (needs & NEEDS_LEFT) {
|
|
46
|
+
const sz = th << 2, left = EDGE - sz;
|
|
47
|
+
if (haveLeft) {
|
|
48
|
+
const have = Math.min(sz, (h - y) << 2);
|
|
49
|
+
for (let i = 0; i < have; i++)
|
|
50
|
+
e[left + sz - 1 - i] = pic[dst + stride * i - 1];
|
|
51
|
+
if (have < sz)
|
|
52
|
+
e.fill(e[left + sz - have], left, left + sz - have);
|
|
53
|
+
}
|
|
54
|
+
else
|
|
55
|
+
e.fill(haveTop ? pic[top] : (1 << bitdepth >> 1) + 1, left, left + sz);
|
|
56
|
+
if (needs & NEEDS_BOTTOMLEFT) {
|
|
57
|
+
const haveBottomLeft = haveLeft && y + th < h && edgeFlags & EDGE_I444_LEFT_HAS_BOTTOM;
|
|
58
|
+
if (haveBottomLeft) {
|
|
59
|
+
const have = Math.min(sz, (h - y - th) << 2);
|
|
60
|
+
for (let i = 0; i < have; i++)
|
|
61
|
+
e[left - 1 - i] = pic[dst + (sz + i) * stride - 1];
|
|
62
|
+
if (have < sz)
|
|
63
|
+
e.fill(e[left - have], left - sz, left - have);
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
e.fill(e[left], left - sz, left);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (needs & NEEDS_TOP) {
|
|
70
|
+
const sz = tw << 2, t = EDGE + 1;
|
|
71
|
+
if (haveTop) {
|
|
72
|
+
const have = Math.min(sz, (w - x) << 2);
|
|
73
|
+
for (let i = 0; i < have; i++)
|
|
74
|
+
e[t + i] = pic[top + i];
|
|
75
|
+
if (have < sz)
|
|
76
|
+
e.fill(e[t + have - 1], t + have, t + sz);
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
e.fill(haveLeft ? pic[dst - 1] : (1 << bitdepth >> 1) - 1, t, t + sz);
|
|
80
|
+
if (needs & NEEDS_TOPRIGHT) {
|
|
81
|
+
const haveTopRight = haveTop && x + tw < w && edgeFlags & EDGE_I444_TOP_HAS_RIGHT;
|
|
82
|
+
if (haveTopRight) {
|
|
83
|
+
const have = Math.min(sz, (w - x - tw) << 2);
|
|
84
|
+
for (let i = 0; i < have; i++)
|
|
85
|
+
e[t + sz + i] = pic[top + sz + i];
|
|
86
|
+
if (have < sz)
|
|
87
|
+
e.fill(e[t + sz + have - 1], t + sz + have, t + 2 * sz);
|
|
88
|
+
}
|
|
89
|
+
else
|
|
90
|
+
e.fill(e[t + sz - 1], t + sz, t + 2 * sz);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (needs & NEEDS_TOPLEFT) {
|
|
94
|
+
if (haveLeft)
|
|
95
|
+
e[EDGE] = haveTop ? pic[top - 1] : pic[dst - 1];
|
|
96
|
+
else
|
|
97
|
+
e[EDGE] = haveTop ? pic[top] : 1 << bitdepth >> 1;
|
|
98
|
+
if (mode === Z2_PRED && tw + th >= 6 && filterEdge)
|
|
99
|
+
e[EDGE] = ((e[EDGE - 1] + e[EDGE + 1]) * 5 + e[EDGE] * 6 + 8) >> 4;
|
|
100
|
+
}
|
|
101
|
+
return mode;
|
|
102
|
+
}
|
|
103
|
+
function splat(dst, d, stride, width, height, v) {
|
|
104
|
+
for (let y = 0; y < height; y++, d += stride)
|
|
105
|
+
dst.fill(v, d, d + width);
|
|
106
|
+
}
|
|
107
|
+
const ctz = (v) => 31 - Math.clz32(v & -v);
|
|
108
|
+
function dcTop(e, width) {
|
|
109
|
+
let dc = width >> 1;
|
|
110
|
+
for (let i = 0; i < width; i++)
|
|
111
|
+
dc += e[EDGE + 1 + i];
|
|
112
|
+
return dc >> ctz(width);
|
|
113
|
+
}
|
|
114
|
+
function dcLeft(e, height) {
|
|
115
|
+
let dc = height >> 1;
|
|
116
|
+
for (let i = 0; i < height; i++)
|
|
117
|
+
dc += e[EDGE - 1 - i];
|
|
118
|
+
return dc >> ctz(height);
|
|
119
|
+
}
|
|
120
|
+
function dcBoth(e, width, height, hbd) {
|
|
121
|
+
let dc = (width + height) >> 1;
|
|
122
|
+
for (let i = 0; i < width; i++)
|
|
123
|
+
dc += e[EDGE + 1 + i];
|
|
124
|
+
for (let i = 0; i < height; i++)
|
|
125
|
+
dc += e[EDGE - 1 - i];
|
|
126
|
+
dc >>= ctz(width + height);
|
|
127
|
+
if (width !== height) {
|
|
128
|
+
const quarter = width > height * 2 || height > width * 2;
|
|
129
|
+
dc = hbd ? Math.floor(dc * (quarter ? 0x6667 : 0xAAAB) / 131072) : dc * (quarter ? 0x3334 : 0x5556) >>> 16;
|
|
130
|
+
}
|
|
131
|
+
return dc;
|
|
132
|
+
}
|
|
133
|
+
export function dcValue(mode, width, height, bitdepthMax) {
|
|
134
|
+
const e = edgeBuffer;
|
|
135
|
+
switch (mode) {
|
|
136
|
+
case DC_PRED: return dcBoth(e, width, height, bitdepthMax > 255);
|
|
137
|
+
case LEFT_DC_PRED: return dcLeft(e, height);
|
|
138
|
+
case TOP_DC_PRED: return dcTop(e, width);
|
|
139
|
+
default: return (bitdepthMax + 1) >> 1;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function filterStrength(wh, angle, smooth) {
|
|
143
|
+
if (smooth) {
|
|
144
|
+
if (wh <= 8) {
|
|
145
|
+
if (angle >= 64)
|
|
146
|
+
return 2;
|
|
147
|
+
if (angle >= 40)
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
else if (wh <= 16) {
|
|
151
|
+
if (angle >= 48)
|
|
152
|
+
return 2;
|
|
153
|
+
if (angle >= 20)
|
|
154
|
+
return 1;
|
|
155
|
+
}
|
|
156
|
+
else if (wh <= 24) {
|
|
157
|
+
if (angle >= 4)
|
|
158
|
+
return 3;
|
|
159
|
+
}
|
|
160
|
+
else
|
|
161
|
+
return 3;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
if (wh <= 8) {
|
|
165
|
+
if (angle >= 56)
|
|
166
|
+
return 1;
|
|
167
|
+
}
|
|
168
|
+
else if (wh <= 16) {
|
|
169
|
+
if (angle >= 40)
|
|
170
|
+
return 1;
|
|
171
|
+
}
|
|
172
|
+
else if (wh <= 24) {
|
|
173
|
+
if (angle >= 32)
|
|
174
|
+
return 3;
|
|
175
|
+
if (angle >= 16)
|
|
176
|
+
return 2;
|
|
177
|
+
if (angle >= 8)
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
else if (wh <= 32) {
|
|
181
|
+
if (angle >= 32)
|
|
182
|
+
return 3;
|
|
183
|
+
if (angle >= 4)
|
|
184
|
+
return 2;
|
|
185
|
+
return 1;
|
|
186
|
+
}
|
|
187
|
+
else
|
|
188
|
+
return 3;
|
|
189
|
+
}
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
192
|
+
const KERNELS = [[0, 4, 8, 4, 0], [0, 5, 6, 5, 0], [2, 4, 4, 4, 2]];
|
|
193
|
+
const clampIndex = (i, from, to) => i < from ? from : i > to - 1 ? to - 1 : i;
|
|
194
|
+
function filterEdge(out, o, sz, limFrom, limTo, inp, i0, from, to, strength) {
|
|
195
|
+
const k = KERNELS[strength - 1];
|
|
196
|
+
let i = 0;
|
|
197
|
+
for (; i < Math.min(sz, limFrom); i++)
|
|
198
|
+
out[o + i] = inp[i0 + clampIndex(i, from, to)];
|
|
199
|
+
for (; i < Math.min(limTo, sz); i++) {
|
|
200
|
+
let s = 0;
|
|
201
|
+
for (let j = 0; j < 5; j++)
|
|
202
|
+
s += inp[i0 + clampIndex(i - 2 + j, from, to)] * k[j];
|
|
203
|
+
out[o + i] = (s + 8) >> 4;
|
|
204
|
+
}
|
|
205
|
+
for (; i < sz; i++)
|
|
206
|
+
out[o + i] = inp[i0 + clampIndex(i, from, to)];
|
|
207
|
+
}
|
|
208
|
+
const upsampled = (wh, angle, smooth) => angle < 40 && wh <= 16 >> (smooth ? 1 : 0);
|
|
209
|
+
function upsampleEdge(out, o, hsz, inp, i0, from, to, bitdepthMax) {
|
|
210
|
+
let i;
|
|
211
|
+
for (i = 0; i < hsz - 1; i++) {
|
|
212
|
+
out[o + i * 2] = inp[i0 + clampIndex(i, from, to)];
|
|
213
|
+
const s = -inp[i0 + clampIndex(i - 1, from, to)] + 9 * inp[i0 + clampIndex(i, from, to)] + 9 * inp[i0 + clampIndex(i + 1, from, to)] - inp[i0 + clampIndex(i + 2, from, to)];
|
|
214
|
+
const v = (s + 8) >> 4;
|
|
215
|
+
out[o + i * 2 + 1] = v < 0 ? 0 : v > bitdepthMax ? bitdepthMax : v;
|
|
216
|
+
}
|
|
217
|
+
out[o + i * 2] = inp[i0 + clampIndex(i, from, to)];
|
|
218
|
+
}
|
|
219
|
+
const scratch = new Uint16Array(64 + 64 + 1);
|
|
220
|
+
function z1(dst, d, stride, width, height, angle, bitdepthMax) {
|
|
221
|
+
const e = edgeBuffer;
|
|
222
|
+
const smooth = !!(angle >> 9 & 1), edgeFilter = !!(angle >> 10);
|
|
223
|
+
angle &= 511;
|
|
224
|
+
let dx = DR_INTRA_DERIVATIVE[angle >> 1];
|
|
225
|
+
let top, t0, maxBase;
|
|
226
|
+
const up = edgeFilter && upsampled(width + height, 90 - angle, smooth);
|
|
227
|
+
if (up) {
|
|
228
|
+
upsampleEdge(scratch, 0, width + height, e, EDGE + 1, -1, width + Math.min(width, height), bitdepthMax);
|
|
229
|
+
top = scratch;
|
|
230
|
+
t0 = 0;
|
|
231
|
+
maxBase = 2 * (width + height) - 2;
|
|
232
|
+
dx <<= 1;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
const strength = edgeFilter ? filterStrength(width + height, 90 - angle, smooth) : 0;
|
|
236
|
+
if (strength) {
|
|
237
|
+
filterEdge(scratch, 0, width + height, 0, width + height, e, EDGE + 1, -1, width + Math.min(width, height), strength);
|
|
238
|
+
top = scratch;
|
|
239
|
+
t0 = 0;
|
|
240
|
+
maxBase = width + height - 1;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
top = e;
|
|
244
|
+
t0 = EDGE + 1;
|
|
245
|
+
maxBase = width + Math.min(width, height) - 1;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
const inc = up ? 2 : 1;
|
|
249
|
+
for (let y = 0, xpos = dx; y < height; y++, d += stride, xpos += dx) {
|
|
250
|
+
const frac = xpos & 0x3e;
|
|
251
|
+
for (let x = 0, base = xpos >> 6; x < width; x++, base += inc) {
|
|
252
|
+
if (base < maxBase)
|
|
253
|
+
dst[d + x] = (top[t0 + base] * (64 - frac) + top[t0 + base + 1] * frac + 32) >> 6;
|
|
254
|
+
else {
|
|
255
|
+
dst.fill(top[t0 + maxBase], d + x, d + width);
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function z2(dst, d, stride, width, height, angle, maxWidth, maxHeight, bitdepthMax) {
|
|
262
|
+
const e = edgeBuffer;
|
|
263
|
+
const smooth = !!(angle >> 9 & 1), edgeFilter = !!(angle >> 10);
|
|
264
|
+
angle &= 511;
|
|
265
|
+
let dy = DR_INTRA_DERIVATIVE[(angle - 90) >> 1];
|
|
266
|
+
let dx = DR_INTRA_DERIVATIVE[(180 - angle) >> 1];
|
|
267
|
+
const upLeft = edgeFilter && upsampled(width + height, 180 - angle, smooth);
|
|
268
|
+
const upAbove = edgeFilter && upsampled(width + height, angle - 90, smooth);
|
|
269
|
+
const s = scratch, tl = 64;
|
|
270
|
+
if (upAbove) {
|
|
271
|
+
upsampleEdge(s, tl, width + 1, e, EDGE, 0, width + 1, bitdepthMax);
|
|
272
|
+
dx <<= 1;
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
const strength = edgeFilter ? filterStrength(width + height, angle - 90, smooth) : 0;
|
|
276
|
+
if (strength)
|
|
277
|
+
filterEdge(s, tl + 1, width, 0, maxWidth, e, EDGE + 1, -1, width, strength);
|
|
278
|
+
else
|
|
279
|
+
s.set(e.subarray(EDGE + 1, EDGE + 1 + width), tl + 1);
|
|
280
|
+
}
|
|
281
|
+
if (upLeft) {
|
|
282
|
+
upsampleEdge(s, tl - height * 2, height + 1, e, EDGE - height, 0, height + 1, bitdepthMax);
|
|
283
|
+
dy <<= 1;
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
const strength = edgeFilter ? filterStrength(width + height, 180 - angle, smooth) : 0;
|
|
287
|
+
if (strength)
|
|
288
|
+
filterEdge(s, tl - height, height, height - maxHeight, height, e, EDGE - height, 0, height + 1, strength);
|
|
289
|
+
else
|
|
290
|
+
s.set(e.subarray(EDGE - height, EDGE), tl - height);
|
|
291
|
+
}
|
|
292
|
+
s[tl] = e[EDGE];
|
|
293
|
+
const incX = upAbove ? 2 : 1;
|
|
294
|
+
const left = tl - (upLeft ? 2 : 1);
|
|
295
|
+
for (let y = 0, xpos = ((upAbove ? 2 : 1) << 6) - dx; y < height; y++, xpos -= dx, d += stride) {
|
|
296
|
+
let baseX = xpos >> 6;
|
|
297
|
+
const fracX = xpos & 0x3e;
|
|
298
|
+
for (let x = 0, ypos = (y << (6 + (upLeft ? 1 : 0))) - dy; x < width; x++, baseX += incX, ypos -= dy) {
|
|
299
|
+
let v;
|
|
300
|
+
if (baseX >= 0)
|
|
301
|
+
v = s[tl + baseX] * (64 - fracX) + s[tl + baseX + 1] * fracX;
|
|
302
|
+
else {
|
|
303
|
+
const baseY = ypos >> 6, fracY = ypos & 0x3e;
|
|
304
|
+
v = s[left - baseY] * (64 - fracY) + s[left - baseY - 1] * fracY;
|
|
305
|
+
}
|
|
306
|
+
dst[d + x] = (v + 32) >> 6;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
function z3(dst, d, stride, width, height, angle, bitdepthMax) {
|
|
311
|
+
const e = edgeBuffer;
|
|
312
|
+
const smooth = !!(angle >> 9 & 1), edgeFilter = !!(angle >> 10);
|
|
313
|
+
angle &= 511;
|
|
314
|
+
let dy = DR_INTRA_DERIVATIVE[(270 - angle) >> 1];
|
|
315
|
+
let left, l0, maxBase;
|
|
316
|
+
const up = edgeFilter && upsampled(width + height, angle - 180, smooth);
|
|
317
|
+
if (up) {
|
|
318
|
+
upsampleEdge(scratch, 0, width + height, e, EDGE - (width + height), Math.max(width - height, 0), width + height + 1, bitdepthMax);
|
|
319
|
+
left = scratch;
|
|
320
|
+
l0 = 2 * (width + height) - 2;
|
|
321
|
+
maxBase = 2 * (width + height) - 2;
|
|
322
|
+
dy <<= 1;
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
const strength = edgeFilter ? filterStrength(width + height, angle - 180, smooth) : 0;
|
|
326
|
+
if (strength) {
|
|
327
|
+
filterEdge(scratch, 0, width + height, 0, width + height, e, EDGE - (width + height), Math.max(width - height, 0), width + height + 1, strength);
|
|
328
|
+
left = scratch;
|
|
329
|
+
l0 = width + height - 1;
|
|
330
|
+
maxBase = width + height - 1;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
left = e;
|
|
334
|
+
l0 = EDGE - 1;
|
|
335
|
+
maxBase = height + Math.min(width, height) - 1;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
const inc = up ? 2 : 1;
|
|
339
|
+
for (let x = 0, ypos = dy; x < width; x++, ypos += dy) {
|
|
340
|
+
const frac = ypos & 0x3e;
|
|
341
|
+
for (let y = 0, base = ypos >> 6; y < height; y++, base += inc) {
|
|
342
|
+
if (base < maxBase)
|
|
343
|
+
dst[d + y * stride + x] = (left[l0 - base] * (64 - frac) + left[l0 - base - 1] * frac + 32) >> 6;
|
|
344
|
+
else {
|
|
345
|
+
for (; y < height; y++)
|
|
346
|
+
dst[d + y * stride + x] = left[l0 - maxBase];
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function filterIntra(dst, d, stride, width, height, filter, bitdepthMax) {
|
|
353
|
+
const e = edgeBuffer;
|
|
354
|
+
const taps = filter * 56;
|
|
355
|
+
let topArr = e, top = EDGE + 1;
|
|
356
|
+
for (let y = 0; y < height; y += 2) {
|
|
357
|
+
let tlArr = e, tl = EDGE - y;
|
|
358
|
+
let leftArr = e, left = tl - 1, leftStride = -1;
|
|
359
|
+
for (let x = 0; x < width; x += 4) {
|
|
360
|
+
const p0 = tlArr[tl];
|
|
361
|
+
const p1 = topArr[top], p2 = topArr[top + 1], p3 = topArr[top + 2], p4 = topArr[top + 3];
|
|
362
|
+
const p5 = leftArr[left], p6 = leftArr[left + leftStride];
|
|
363
|
+
let ptr = d + x;
|
|
364
|
+
for (let yy = 0, k = 0; yy < 2; yy++, ptr += stride) {
|
|
365
|
+
for (let xx = 0; xx < 4; xx++, k++) {
|
|
366
|
+
const t = taps + k * 7;
|
|
367
|
+
const acc = FILTER_INTRA_TAPS[t] * p0 + FILTER_INTRA_TAPS[t + 1] * p1 + FILTER_INTRA_TAPS[t + 2] * p2 +
|
|
368
|
+
FILTER_INTRA_TAPS[t + 3] * p3 + FILTER_INTRA_TAPS[t + 4] * p4 + FILTER_INTRA_TAPS[t + 5] * p5 +
|
|
369
|
+
FILTER_INTRA_TAPS[t + 6] * p6;
|
|
370
|
+
const v = (acc + 8) >> 4;
|
|
371
|
+
dst[ptr + xx] = v < 0 ? 0 : v > bitdepthMax ? bitdepthMax : v;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
leftArr = dst;
|
|
375
|
+
left = d + x + 4 - 1;
|
|
376
|
+
leftStride = stride;
|
|
377
|
+
top += 4;
|
|
378
|
+
tlArr = topArr;
|
|
379
|
+
tl = top - 1;
|
|
380
|
+
}
|
|
381
|
+
topArr = dst;
|
|
382
|
+
top = d + stride;
|
|
383
|
+
d += stride * 2;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
export function predict(mode, dst, d, stride, width, height, angle, maxWidth, maxHeight, bitdepthMax) {
|
|
387
|
+
const e = edgeBuffer;
|
|
388
|
+
switch (mode) {
|
|
389
|
+
case DC_PRED:
|
|
390
|
+
case LEFT_DC_PRED:
|
|
391
|
+
case TOP_DC_PRED:
|
|
392
|
+
case DC_128_PRED:
|
|
393
|
+
return splat(dst, d, stride, width, height, dcValue(mode, width, height, bitdepthMax));
|
|
394
|
+
case VERT_PRED:
|
|
395
|
+
for (let y = 0; y < height; y++, d += stride)
|
|
396
|
+
dst.set(e.subarray(EDGE + 1, EDGE + 1 + width), d);
|
|
397
|
+
return;
|
|
398
|
+
case HOR_PRED:
|
|
399
|
+
for (let y = 0; y < height; y++, d += stride)
|
|
400
|
+
dst.fill(e[EDGE - 1 - y], d, d + width);
|
|
401
|
+
return;
|
|
402
|
+
case PAETH_PRED: {
|
|
403
|
+
const topleft = e[EDGE];
|
|
404
|
+
for (let y = 0; y < height; y++, d += stride) {
|
|
405
|
+
const left = e[EDGE - 1 - y];
|
|
406
|
+
for (let x = 0; x < width; x++) {
|
|
407
|
+
const top = e[EDGE + 1 + x];
|
|
408
|
+
const base = left + top - topleft;
|
|
409
|
+
const ldiff = Math.abs(left - base), tdiff = Math.abs(top - base), tldiff = Math.abs(topleft - base);
|
|
410
|
+
dst[d + x] = ldiff <= tdiff && ldiff <= tldiff ? left : tdiff <= tldiff ? top : topleft;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
case SMOOTH_PRED: {
|
|
416
|
+
const right = e[EDGE + width], bottom = e[EDGE - height];
|
|
417
|
+
for (let y = 0; y < height; y++, d += stride) {
|
|
418
|
+
const wv = SM_WEIGHTS[height + y], left = e[EDGE - 1 - y];
|
|
419
|
+
for (let x = 0; x < width; x++) {
|
|
420
|
+
const wh = SM_WEIGHTS[width + x];
|
|
421
|
+
dst[d + x] = (wv * e[EDGE + 1 + x] + (256 - wv) * bottom + wh * left + (256 - wh) * right + 256) >> 9;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
case SMOOTH_V_PRED: {
|
|
427
|
+
const bottom = e[EDGE - height];
|
|
428
|
+
for (let y = 0; y < height; y++, d += stride) {
|
|
429
|
+
const wv = SM_WEIGHTS[height + y];
|
|
430
|
+
for (let x = 0; x < width; x++)
|
|
431
|
+
dst[d + x] = (wv * e[EDGE + 1 + x] + (256 - wv) * bottom + 128) >> 8;
|
|
432
|
+
}
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
case SMOOTH_H_PRED: {
|
|
436
|
+
const right = e[EDGE + width];
|
|
437
|
+
for (let y = 0; y < height; y++, d += stride) {
|
|
438
|
+
const left = e[EDGE - 1 - y];
|
|
439
|
+
for (let x = 0; x < width; x++) {
|
|
440
|
+
const wh = SM_WEIGHTS[width + x];
|
|
441
|
+
dst[d + x] = (wh * left + (256 - wh) * right + 128) >> 8;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
case Z1_PRED: return z1(dst, d, stride, width, height, angle, bitdepthMax);
|
|
447
|
+
case Z2_PRED: return z2(dst, d, stride, width, height, angle, maxWidth, maxHeight, bitdepthMax);
|
|
448
|
+
case Z3_PRED: return z3(dst, d, stride, width, height, angle, bitdepthMax);
|
|
449
|
+
case FILTER_PRED: return filterIntra(dst, d, stride, width, height, angle & 511, bitdepthMax);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
export function cflAc(ac, y, yo, stride, wPad, hPad, width, height, ssHor, ssVer) {
|
|
453
|
+
let a = 0, row;
|
|
454
|
+
for (row = 0; row < height - 4 * hPad; row++) {
|
|
455
|
+
let x;
|
|
456
|
+
for (x = 0; x < width - 4 * wPad; x++) {
|
|
457
|
+
let sum = y[yo + (x << ssHor)];
|
|
458
|
+
if (ssHor)
|
|
459
|
+
sum += y[yo + x * 2 + 1];
|
|
460
|
+
if (ssVer) {
|
|
461
|
+
sum += y[yo + (x << ssHor) + stride];
|
|
462
|
+
if (ssHor)
|
|
463
|
+
sum += y[yo + x * 2 + 1 + stride];
|
|
464
|
+
}
|
|
465
|
+
ac[a + x] = sum << (1 + (ssVer ? 0 : 1) + (ssHor ? 0 : 1));
|
|
466
|
+
}
|
|
467
|
+
for (; x < width; x++)
|
|
468
|
+
ac[a + x] = ac[a + x - 1];
|
|
469
|
+
a += width;
|
|
470
|
+
yo += stride << ssVer;
|
|
471
|
+
}
|
|
472
|
+
for (; row < height; row++, a += width)
|
|
473
|
+
ac.copyWithin(a, a - width, a);
|
|
474
|
+
const log2 = ctz(width) + ctz(height);
|
|
475
|
+
let sum = (1 << log2) >> 1;
|
|
476
|
+
for (let i = 0; i < width * height; i++)
|
|
477
|
+
sum += ac[i];
|
|
478
|
+
sum >>= log2;
|
|
479
|
+
for (let i = 0; i < width * height; i++)
|
|
480
|
+
ac[i] -= sum;
|
|
481
|
+
}
|
|
482
|
+
export function cflPredict(mode, dst, d, stride, width, height, ac, alpha, bitdepthMax) {
|
|
483
|
+
const dc = dcValue(mode, width, height, bitdepthMax);
|
|
484
|
+
for (let y = 0, a = 0; y < height; y++, d += stride) {
|
|
485
|
+
for (let x = 0; x < width; x++, a++) {
|
|
486
|
+
const diff = alpha * ac[a];
|
|
487
|
+
const v = dc + (diff < 0 ? -((-diff + 32) >> 6) : (diff + 32) >> 6);
|
|
488
|
+
dst[d + x] = v < 0 ? 0 : v > bitdepthMax ? bitdepthMax : v;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|