imagescript 3.2.0 → 3.2.1
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/dist/animation.js +1 -1
- package/dist/codecs/gif.js +20 -17
- package/dist/image.js +7 -3
- package/dist/util/blur.js +88 -0
- package/dist/util/resample.js +240 -77
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/animation.js
CHANGED
|
@@ -13,7 +13,7 @@ const fromPlays = (plays) => plays === 0 ? -1 : plays - 1;
|
|
|
13
13
|
function canvasFrames(width, height, frames) {
|
|
14
14
|
return frames.map(({ pixels, duration }) => {
|
|
15
15
|
const frame = new Frame(width, height, duration, 0, 0, Frame.DISPOSAL_BACKGROUND);
|
|
16
|
-
frame.bitmap
|
|
16
|
+
frame.bitmap = pixels;
|
|
17
17
|
return frame;
|
|
18
18
|
});
|
|
19
19
|
}
|
package/dist/codecs/gif.js
CHANGED
|
@@ -188,23 +188,20 @@ export function decode(data, onlyFirstFrame = false) {
|
|
|
188
188
|
control = null;
|
|
189
189
|
if (!fw || !fh)
|
|
190
190
|
continue;
|
|
191
|
-
const
|
|
192
|
-
const rows = interlaced ? interlacedRows(fh) : null;
|
|
193
|
-
const colors = new Uint8Array(256 * 4);
|
|
191
|
+
const colors = new Uint32Array(256), bytes = new Uint8Array(colors.buffer);
|
|
194
192
|
for (let index = 0; index < 256; index++) {
|
|
195
|
-
if (index === transparentIndex)
|
|
196
|
-
continue;
|
|
197
193
|
if (table && index * 3 + 2 < table.length)
|
|
198
|
-
|
|
199
|
-
|
|
194
|
+
bytes.set(table.subarray(index * 3, index * 3 + 3), index * 4);
|
|
195
|
+
bytes[index * 4 + 3] = 0xff;
|
|
200
196
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
197
|
+
let ordered = indices;
|
|
198
|
+
if (interlaced) {
|
|
199
|
+
const rows = interlacedRows(fh);
|
|
200
|
+
ordered = new Uint8Array(indices.length);
|
|
201
|
+
for (let row = 0; row < fh; row++)
|
|
202
|
+
ordered.set(indices.subarray(row * fw, (row + 1) * fw), rows[row] * fw);
|
|
206
203
|
}
|
|
207
|
-
frames.push({ x, y, width: fw, height: fh, delay, dispose,
|
|
204
|
+
frames.push({ x, y, width: fw, height: fh, delay, dispose, indices: ordered, colors, transparentIndex });
|
|
208
205
|
if (onlyFirstFrame)
|
|
209
206
|
break;
|
|
210
207
|
}
|
|
@@ -215,15 +212,21 @@ export function composite({ width, height, frames }) {
|
|
|
215
212
|
const output = [];
|
|
216
213
|
for (const frame of frames) {
|
|
217
214
|
const previous = frame.dispose === 2 ? canvas.slice() : null;
|
|
218
|
-
const
|
|
215
|
+
const { indices, colors, transparentIndex } = frame;
|
|
219
216
|
const x0 = Math.min(frame.x, width), x1 = Math.min(frame.x + frame.width, width);
|
|
220
217
|
const y0 = Math.min(frame.y, height), y1 = Math.min(frame.y + frame.height, height);
|
|
221
218
|
for (let y = y0; y < y1; y++) {
|
|
222
219
|
const srcRow = (y - frame.y) * frame.width - frame.x;
|
|
223
220
|
const dstRow = y * width;
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
canvas[dstRow + x] =
|
|
221
|
+
if (transparentIndex < 0)
|
|
222
|
+
for (let x = x0; x < x1; x++)
|
|
223
|
+
canvas[dstRow + x] = colors[indices[srcRow + x]];
|
|
224
|
+
else
|
|
225
|
+
for (let x = x0; x < x1; x++) {
|
|
226
|
+
const index = indices[srcRow + x];
|
|
227
|
+
if (index !== transparentIndex)
|
|
228
|
+
canvas[dstRow + x] = colors[index];
|
|
229
|
+
}
|
|
227
230
|
}
|
|
228
231
|
output.push({ pixels: new Uint8Array(canvas.slice().buffer), delay: frame.delay });
|
|
229
232
|
if (frame.dispose === 3) {
|
package/dist/image.js
CHANGED
|
@@ -12,7 +12,7 @@ import { TextLayout } from "./text-layout.js";
|
|
|
12
12
|
import { resolveMetadata, pngText, exifData } from "./metadata.js";
|
|
13
13
|
import { encode as utf8 } from "./util/utf8.js";
|
|
14
14
|
import { resample, BOX, TRIANGLE, CUBIC } from "./util/resample.js";
|
|
15
|
-
import { gaussianBlur, premultiply, unpremultiply } from "./util/blur.js";
|
|
15
|
+
import { gaussianBlur, boxBlurRGBA, premultiply, unpremultiply } from "./util/blur.js";
|
|
16
16
|
import { isOptions } from "./util/options.js";
|
|
17
17
|
export class Image {
|
|
18
18
|
__width__;
|
|
@@ -189,8 +189,10 @@ export class Image {
|
|
|
189
189
|
return this;
|
|
190
190
|
}
|
|
191
191
|
clone() {
|
|
192
|
-
const image = new Image(
|
|
193
|
-
image.
|
|
192
|
+
const image = new Image(1, 1);
|
|
193
|
+
image.__width__ = this.width;
|
|
194
|
+
image.__height__ = this.height;
|
|
195
|
+
image.__set_bitmap__(new Uint8ClampedArray(this.bitmap));
|
|
194
196
|
return image;
|
|
195
197
|
}
|
|
196
198
|
static get RESIZE_NEAREST_NEIGHBOR() {
|
|
@@ -612,6 +614,8 @@ export class Image {
|
|
|
612
614
|
blur(radius) {
|
|
613
615
|
if (isNaN(radius) || radius < 0)
|
|
614
616
|
throw new RangeError('Invalid blur radius');
|
|
617
|
+
if (boxBlurRGBA(this.bitmap, this.width, this.height, radius))
|
|
618
|
+
return this;
|
|
615
619
|
const pixels = premultiply(this.bitmap);
|
|
616
620
|
gaussianBlur(pixels, this.width, this.height, radius);
|
|
617
621
|
unpremultiply(pixels, this.bitmap);
|
package/dist/util/blur.js
CHANGED
|
@@ -119,6 +119,94 @@ export function gaussianBlur(pixels, width, height, sigma) {
|
|
|
119
119
|
boxPassRows(tmp, pixels, width, height, radius);
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
|
+
function boxRowWords(src, dst, s, length, radius, mult) {
|
|
123
|
+
const last = length - 1;
|
|
124
|
+
const first = src[s], end = src[s + last];
|
|
125
|
+
let rb = (radius + 1) * (first & 0xff00ff), ga = (radius + 1) * (first >>> 8 & 0xff00ff);
|
|
126
|
+
for (let k = 1; k <= radius; k++) {
|
|
127
|
+
const p = src[s + (k < last ? k : last)];
|
|
128
|
+
rb += p & 0xff00ff;
|
|
129
|
+
ga += p >>> 8 & 0xff00ff;
|
|
130
|
+
}
|
|
131
|
+
for (let x = 0; x < length; x++) {
|
|
132
|
+
dst[s + x] = (Math.imul(rb & 0xffff, mult) + 32768 >>> 16) | (Math.imul(ga & 0xffff, mult) + 32768 >>> 16) << 8
|
|
133
|
+
| (Math.imul(rb >>> 16, mult) + 32768 >>> 16) << 16 | (Math.imul(ga >>> 16, mult) + 32768 >>> 16) << 24;
|
|
134
|
+
const add = x + radius + 1, remove = x - radius;
|
|
135
|
+
const entering = add < last ? src[s + add] : end, leaving = remove > 0 ? src[s + remove] : first;
|
|
136
|
+
rb += (entering & 0xff00ff) - (leaving & 0xff00ff);
|
|
137
|
+
ga += (entering >>> 8 & 0xff00ff) - (leaving >>> 8 & 0xff00ff);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function boxColumnsWords(src, dst, width, height, radius, mult, rbs, gas) {
|
|
141
|
+
for (let x = 0; x < width; x++) {
|
|
142
|
+
const p = src[x];
|
|
143
|
+
rbs[x] = (radius + 1) * (p & 0xff00ff);
|
|
144
|
+
gas[x] = (radius + 1) * (p >>> 8 & 0xff00ff);
|
|
145
|
+
}
|
|
146
|
+
for (let k = 1; k <= radius; k++) {
|
|
147
|
+
const o = Math.min(k, height - 1) * width;
|
|
148
|
+
for (let x = 0; x < width; x++) {
|
|
149
|
+
const p = src[o + x];
|
|
150
|
+
rbs[x] += p & 0xff00ff;
|
|
151
|
+
gas[x] += p >>> 8 & 0xff00ff;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (let y = 0; y < height; y++) {
|
|
155
|
+
const o = y * width, add = Math.min(height - 1, y + radius + 1) * width, remove = Math.max(0, y - radius) * width;
|
|
156
|
+
for (let x = 0; x < width; x++) {
|
|
157
|
+
const rb = rbs[x], ga = gas[x];
|
|
158
|
+
dst[o + x] = (Math.imul(rb & 0xffff, mult) + 32768 >>> 16) | (Math.imul(ga & 0xffff, mult) + 32768 >>> 16) << 8
|
|
159
|
+
| (Math.imul(rb >>> 16, mult) + 32768 >>> 16) << 16 | (Math.imul(ga >>> 16, mult) + 32768 >>> 16) << 24;
|
|
160
|
+
const entering = src[add + x], leaving = src[remove + x];
|
|
161
|
+
rbs[x] = rb + (entering & 0xff00ff) - (leaving & 0xff00ff);
|
|
162
|
+
gas[x] = ga + (entering >>> 8 & 0xff00ff) - (leaving >>> 8 & 0xff00ff);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export function boxBlurRGBA(bitmap, width, height, sigma) {
|
|
167
|
+
const sizes = boxSizes(sigma);
|
|
168
|
+
if (!(sigma >= 2) || Math.max(...sizes) > 257)
|
|
169
|
+
return false;
|
|
170
|
+
let opaque = true;
|
|
171
|
+
for (let i = 3; i < bitmap.length; i += 4)
|
|
172
|
+
if (bitmap[i] !== 255) {
|
|
173
|
+
opaque = false;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
if (!opaque) {
|
|
177
|
+
for (let i = 0; i < bitmap.length; i += 4) {
|
|
178
|
+
const a = bitmap[i + 3];
|
|
179
|
+
bitmap[i] = (bitmap[i] * a + 128) * 257 >> 16;
|
|
180
|
+
bitmap[i + 1] = (bitmap[i + 1] * a + 128) * 257 >> 16;
|
|
181
|
+
bitmap[i + 2] = (bitmap[i + 2] * a + 128) * 257 >> 16;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const pixels = new Int32Array(bitmap.buffer, bitmap.byteOffset, width * height);
|
|
185
|
+
const tmp = new Int32Array(pixels.length), rbs = new Int32Array(width), gas = new Int32Array(width);
|
|
186
|
+
for (const size of sizes) {
|
|
187
|
+
const radius = (size - 1) / 2;
|
|
188
|
+
if (radius < 1)
|
|
189
|
+
continue;
|
|
190
|
+
const mult = Math.round(65536 / size);
|
|
191
|
+
for (let y = 0; y < height; y++)
|
|
192
|
+
boxRowWords(pixels, tmp, y * width, width, radius, mult);
|
|
193
|
+
boxColumnsWords(tmp, pixels, width, height, radius, mult, rbs, gas);
|
|
194
|
+
}
|
|
195
|
+
if (!opaque) {
|
|
196
|
+
for (let i = 0; i < bitmap.length; i += 4) {
|
|
197
|
+
const a = bitmap[i + 3];
|
|
198
|
+
if (a === 0) {
|
|
199
|
+
bitmap[i] = bitmap[i + 1] = bitmap[i + 2] = 0;
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const f = 255 / a;
|
|
203
|
+
bitmap[i] *= f;
|
|
204
|
+
bitmap[i + 1] *= f;
|
|
205
|
+
bitmap[i + 2] *= f;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
122
210
|
export function premultiply(rgba) {
|
|
123
211
|
const out = new Float32Array(rgba.length);
|
|
124
212
|
for (let i = 0; i < rgba.length; i += 4) {
|
package/dist/util/resample.js
CHANGED
|
@@ -12,106 +12,269 @@ export const CUBIC = {
|
|
|
12
12
|
return 0;
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
-
|
|
15
|
+
const BITS = 14;
|
|
16
|
+
const ONE = 1 << BITS;
|
|
17
|
+
function coefficients(inSize, outSize, filter, bits) {
|
|
16
18
|
const scale = inSize / outSize;
|
|
17
19
|
const filterScale = Math.max(1, scale);
|
|
18
20
|
const support = filter.support * filterScale;
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
const weights = new Float64Array(outSize * size);
|
|
21
|
+
const one = 1 << bits;
|
|
22
|
+
const mins = new Int32Array(outSize), maxs = new Int32Array(outSize);
|
|
23
|
+
let taps = 0;
|
|
23
24
|
for (let i = 0; i < outSize; i++) {
|
|
24
25
|
const center = (i + 0.5) * scale;
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
mins[i] = Math.max(0, Math.floor(center - support + 0.5));
|
|
27
|
+
maxs[i] = Math.min(inSize, Math.floor(center + support + 0.5));
|
|
28
|
+
taps = Math.max(taps, maxs[i] - mins[i]);
|
|
29
|
+
}
|
|
30
|
+
const start = new Int32Array(outSize);
|
|
31
|
+
const weights = new Int32Array(outSize * taps);
|
|
32
|
+
const w = new Float64Array(taps);
|
|
33
|
+
for (let i = 0; i < outSize; i++) {
|
|
34
|
+
const center = (i + 0.5) * scale, min = mins[i], n = maxs[i] - min;
|
|
27
35
|
let total = 0;
|
|
28
|
-
for (let
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
for (let k = 0; k < n; k++)
|
|
37
|
+
total += w[k] = filter.weight((min + k - center + 0.5) / filterScale);
|
|
38
|
+
const shift = Math.max(0, min + taps - inSize), o = i * taps + shift;
|
|
39
|
+
start[i] = min - shift;
|
|
40
|
+
let sum = 0, largest = 0;
|
|
41
|
+
for (let k = 0; k < n; k++) {
|
|
42
|
+
sum += weights[o + k] = Math.round(total ? w[k] / total * one : 0);
|
|
43
|
+
if (Math.abs(w[k]) > Math.abs(w[largest]))
|
|
44
|
+
largest = k;
|
|
32
45
|
}
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
weights[i * size + k] /= total;
|
|
36
|
-
start[i] = min;
|
|
37
|
-
count[i] = max - min;
|
|
46
|
+
if (n)
|
|
47
|
+
weights[o + largest] += one - sum;
|
|
38
48
|
}
|
|
39
|
-
return { start,
|
|
49
|
+
return { start, weights, taps };
|
|
40
50
|
}
|
|
51
|
+
const littleEndian = new Uint8Array(new Uint32Array([1]).buffer)[0] === 1;
|
|
41
52
|
export function resample(src, width, height, outWidth, outHeight, filter, out) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
if (littleEndian && filter.support <= 1 && resampleOpaque(src, width, height, outWidth, outHeight, filter, out))
|
|
54
|
+
return;
|
|
55
|
+
resamplePremultiplied(src, width, height, outWidth, outHeight, filter, out);
|
|
56
|
+
}
|
|
57
|
+
function resampleOpaque(src, width, height, outWidth, outHeight, filter, out) {
|
|
58
|
+
const pixels = new Int32Array(src.buffer, src.byteOffset, width * height);
|
|
59
|
+
let all = -1;
|
|
60
|
+
for (let x = 0, last = (height - 1) * width; x < width; x++)
|
|
61
|
+
all &= pixels[x] & pixels[last + x];
|
|
62
|
+
if (all >>> 24 !== 255)
|
|
63
|
+
return false;
|
|
64
|
+
const lanes = new Int32Array(width * outHeight * 2);
|
|
65
|
+
if (outHeight === height) {
|
|
66
|
+
for (let i = 0, o = 0; i < pixels.length; i++, o += 2) {
|
|
67
|
+
const p = pixels[i];
|
|
68
|
+
all &= p;
|
|
69
|
+
lanes[o] = (p & 0xff00ff) << 8;
|
|
70
|
+
lanes[o + 1] = (p & 0xff00) | 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
let coefficientsV = coefficients(height, outHeight, filter, 8);
|
|
75
|
+
const swar = coefficientsV.taps <= 4;
|
|
76
|
+
if (!swar)
|
|
77
|
+
coefficientsV = coefficients(height, outHeight, filter, BITS);
|
|
78
|
+
const { start, weights, taps } = coefficientsV;
|
|
79
|
+
for (let y = 0, o = 0; y < outHeight; y++) {
|
|
80
|
+
const w = y * taps, r0 = start[y] * width;
|
|
81
|
+
if (swar && taps === 4) {
|
|
82
|
+
const w0 = weights[w], w1 = weights[w + 1], w2 = weights[w + 2], w3 = weights[w + 3];
|
|
83
|
+
const r1 = r0 + width, r2 = r1 + width, r3 = r2 + width;
|
|
84
|
+
for (let x = 0; x < width; x++, o += 2) {
|
|
85
|
+
const p0 = pixels[r0 + x], p1 = pixels[r1 + x], p2 = pixels[r2 + x], p3 = pixels[r3 + x];
|
|
86
|
+
all &= p0 & p1 & p2 & p3;
|
|
87
|
+
lanes[o] = Math.imul(p0 & 0xff00ff, w0) + Math.imul(p1 & 0xff00ff, w1) + Math.imul(p2 & 0xff00ff, w2) + Math.imul(p3 & 0xff00ff, w3);
|
|
88
|
+
lanes[o + 1] = (p0 >> 8 & 255) * w0 + (p1 >> 8 & 255) * w1 + (p2 >> 8 & 255) * w2 + (p3 >> 8 & 255) * w3;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else if (swar && taps === 3) {
|
|
92
|
+
const w0 = weights[w], w1 = weights[w + 1], w2 = weights[w + 2], r1 = r0 + width, r2 = r1 + width;
|
|
93
|
+
for (let x = 0; x < width; x++, o += 2) {
|
|
94
|
+
const p0 = pixels[r0 + x], p1 = pixels[r1 + x], p2 = pixels[r2 + x];
|
|
95
|
+
all &= p0 & p1 & p2;
|
|
96
|
+
lanes[o] = Math.imul(p0 & 0xff00ff, w0) + Math.imul(p1 & 0xff00ff, w1) + Math.imul(p2 & 0xff00ff, w2);
|
|
97
|
+
lanes[o + 1] = (p0 >> 8 & 255) * w0 + (p1 >> 8 & 255) * w1 + (p2 >> 8 & 255) * w2;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (swar && taps === 2) {
|
|
101
|
+
const w0 = weights[w], w1 = weights[w + 1], r1 = r0 + width;
|
|
102
|
+
for (let x = 0; x < width; x++, o += 2) {
|
|
103
|
+
const p0 = pixels[r0 + x], p1 = pixels[r1 + x];
|
|
104
|
+
all &= p0 & p1;
|
|
105
|
+
lanes[o] = Math.imul(p0 & 0xff00ff, w0) + Math.imul(p1 & 0xff00ff, w1);
|
|
106
|
+
lanes[o + 1] = (p0 >> 8 & 255) * w0 + (p1 >> 8 & 255) * w1;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (swar) {
|
|
110
|
+
for (let x = 0; x < width; x++, o += 2) {
|
|
111
|
+
let rb = 0, g = 0;
|
|
112
|
+
for (let k = 0, s = r0 + x; k < taps; k++, s += width) {
|
|
113
|
+
const p = pixels[s], wk = weights[w + k];
|
|
114
|
+
all &= p;
|
|
115
|
+
rb += Math.imul(p & 0xff00ff, wk);
|
|
116
|
+
g += (p >> 8 & 255) * wk;
|
|
117
|
+
}
|
|
118
|
+
lanes[o] = rb;
|
|
119
|
+
lanes[o + 1] = g;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
for (let x = 0; x < width; x++, o += 2) {
|
|
124
|
+
let r = 0, g = 0, b = 0, k = 0, s = r0 + x;
|
|
125
|
+
for (; k + 1 < taps; k += 2, s += width * 2) {
|
|
126
|
+
const p = pixels[s], q = pixels[s + width], w0 = weights[w + k], w1 = weights[w + k + 1];
|
|
127
|
+
all &= p & q;
|
|
128
|
+
r += (p & 255) * w0 + (q & 255) * w1;
|
|
129
|
+
g += (p >> 8 & 255) * w0 + (q >> 8 & 255) * w1;
|
|
130
|
+
b += (p >> 16 & 255) * w0 + (q >> 16 & 255) * w1;
|
|
131
|
+
}
|
|
132
|
+
if (k < taps) {
|
|
133
|
+
const p = pixels[s], w0 = weights[w + k];
|
|
134
|
+
all &= p;
|
|
135
|
+
r += (p & 255) * w0;
|
|
136
|
+
g += (p >> 8 & 255) * w0;
|
|
137
|
+
b += (p >> 16 & 255) * w0;
|
|
138
|
+
}
|
|
139
|
+
lanes[o] = (r + 32 >> 6) | (b + 32 >> 6) << 16;
|
|
140
|
+
lanes[o + 1] = g + 32 >> 6;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (all >>> 24 !== 255)
|
|
146
|
+
return false;
|
|
147
|
+
const result = new Int32Array(out.buffer, out.byteOffset, outWidth * outHeight);
|
|
148
|
+
if (outWidth === width) {
|
|
149
|
+
for (let i = 0, o = 0; i < result.length; i++, o += 2) {
|
|
150
|
+
const rb = lanes[o], g = lanes[o + 1];
|
|
151
|
+
result[i] = ((rb & 0xffff) + 128 >> 8) | (g + 128 >> 8) << 8 | ((rb >>> 16) + 128 >> 8) << 16 | 0xff000000;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
const R = 1 << 7 + BITS, S = 8 + BITS;
|
|
156
|
+
const { start, weights, taps } = coefficients(width, outWidth, filter, BITS);
|
|
157
|
+
for (let y = 0, o = 0; y < outHeight; y++) {
|
|
158
|
+
const row = y * width * 2;
|
|
159
|
+
if (taps === 4) {
|
|
160
|
+
for (let x = 0; x < outWidth; x++, o++) {
|
|
161
|
+
const s = row + start[x] * 2, w = x * 4;
|
|
162
|
+
const a0 = lanes[s], a1 = lanes[s + 2], a2 = lanes[s + 4], a3 = lanes[s + 6];
|
|
163
|
+
const w0 = weights[w], w1 = weights[w + 1], w2 = weights[w + 2], w3 = weights[w + 3];
|
|
164
|
+
const r = (a0 & 0xffff) * w0 + (a1 & 0xffff) * w1 + (a2 & 0xffff) * w2 + (a3 & 0xffff) * w3;
|
|
165
|
+
const b = (a0 >>> 16) * w0 + (a1 >>> 16) * w1 + (a2 >>> 16) * w2 + (a3 >>> 16) * w3;
|
|
166
|
+
const g = lanes[s + 1] * w0 + lanes[s + 3] * w1 + lanes[s + 5] * w2 + lanes[s + 7] * w3;
|
|
167
|
+
result[o] = (r + R >> S) | (g + R >> S) << 8 | (b + R >> S) << 16 | 0xff000000;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else if (taps === 2) {
|
|
171
|
+
for (let x = 0; x < outWidth; x++, o++) {
|
|
172
|
+
const s = row + start[x] * 2, w = x * 2;
|
|
173
|
+
const a0 = lanes[s], a1 = lanes[s + 2], w0 = weights[w], w1 = weights[w + 1];
|
|
174
|
+
const r = (a0 & 0xffff) * w0 + (a1 & 0xffff) * w1;
|
|
175
|
+
const b = (a0 >>> 16) * w0 + (a1 >>> 16) * w1;
|
|
176
|
+
const g = lanes[s + 1] * w0 + lanes[s + 3] * w1;
|
|
177
|
+
result[o] = (r + R >> S) | (g + R >> S) << 8 | (b + R >> S) << 16 | 0xff000000;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
for (let x = 0; x < outWidth; x++, o++) {
|
|
182
|
+
let r = 0, g = 0, b = 0, k = 0, s = row + start[x] * 2, w = x * taps;
|
|
183
|
+
for (; k + 1 < taps; k += 2, s += 4) {
|
|
184
|
+
const a0 = lanes[s], a1 = lanes[s + 2], w0 = weights[w + k], w1 = weights[w + k + 1];
|
|
185
|
+
r += (a0 & 0xffff) * w0 + (a1 & 0xffff) * w1;
|
|
186
|
+
b += (a0 >>> 16) * w0 + (a1 >>> 16) * w1;
|
|
187
|
+
g += lanes[s + 1] * w0 + lanes[s + 3] * w1;
|
|
188
|
+
}
|
|
189
|
+
if (k < taps) {
|
|
190
|
+
const a0 = lanes[s], w0 = weights[w + k];
|
|
191
|
+
r += (a0 & 0xffff) * w0;
|
|
192
|
+
b += (a0 >>> 16) * w0;
|
|
193
|
+
g += lanes[s + 1] * w0;
|
|
194
|
+
}
|
|
195
|
+
result[o] = (r + R >> S) | (g + R >> S) << 8 | (b + R >> S) << 16 | 0xff000000;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return true;
|
|
200
|
+
}
|
|
201
|
+
function resamplePremultiplied(src, width, height, outWidth, outHeight, filter, out) {
|
|
202
|
+
const plane = new Int32Array(width * outHeight * 4);
|
|
203
|
+
if (outHeight === height) {
|
|
204
|
+
for (let s = 0; s < src.length; s += 4) {
|
|
205
|
+
const a = src[s + 3];
|
|
206
|
+
plane[s] = src[s] * a;
|
|
207
|
+
plane[s + 1] = src[s + 1] * a;
|
|
208
|
+
plane[s + 2] = src[s + 2] * a;
|
|
209
|
+
plane[s + 3] = a * 255;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
const { start, weights, taps } = coefficients(height, outHeight, filter, BITS);
|
|
214
|
+
const stride = width * 4, H = ONE >> 1;
|
|
215
|
+
for (let y = 0, o = 0; y < outHeight; y++) {
|
|
216
|
+
const w = y * taps, r0 = start[y] * stride;
|
|
217
|
+
for (let x = 0; x < stride; x += 4, o += 4) {
|
|
218
|
+
let r = 0, g = 0, b = 0, a = 0, k = 0, s = r0 + x;
|
|
219
|
+
for (; k + 1 < taps; k += 2, s += stride * 2) {
|
|
220
|
+
const t = s + stride, wa = weights[w + k] * src[s + 3], wb = weights[w + k + 1] * src[t + 3];
|
|
221
|
+
r += src[s] * wa + src[t] * wb;
|
|
222
|
+
g += src[s + 1] * wa + src[t + 1] * wb;
|
|
223
|
+
b += src[s + 2] * wa + src[t + 2] * wb;
|
|
224
|
+
a += wa + wb;
|
|
225
|
+
}
|
|
226
|
+
if (k < taps) {
|
|
50
227
|
const wa = weights[w + k] * src[s + 3];
|
|
51
228
|
r += src[s] * wa;
|
|
52
229
|
g += src[s + 1] * wa;
|
|
53
230
|
b += src[s + 2] * wa;
|
|
54
231
|
a += wa;
|
|
55
232
|
}
|
|
56
|
-
plane[o] = r
|
|
57
|
-
plane[o + 1] = g
|
|
58
|
-
plane[o + 2] = b
|
|
59
|
-
plane[o + 3] = a;
|
|
233
|
+
plane[o] = r + H >> BITS;
|
|
234
|
+
plane[o + 1] = g + H >> BITS;
|
|
235
|
+
plane[o + 2] = b + H >> BITS;
|
|
236
|
+
plane[o + 3] = a * 255 + H >> BITS;
|
|
60
237
|
}
|
|
61
238
|
}
|
|
62
239
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const next = new Float32Array(outWidth * outHeight * 4);
|
|
75
|
-
const stride = outWidth * 4;
|
|
76
|
-
for (let y = 0; y < outHeight; y++) {
|
|
77
|
-
const o = y * stride, n = count[y], w = y * size;
|
|
78
|
-
const s0 = start[y] * stride, s1 = s0 + stride, s2 = s1 + stride, s3 = s2 + stride;
|
|
79
|
-
const w0 = weights[w], w1 = weights[w + 1], w2 = weights[w + 2], w3 = weights[w + 3];
|
|
80
|
-
if (n === 1)
|
|
81
|
-
for (let x = 0; x < stride; x++)
|
|
82
|
-
next[o + x] = 0 + plane[s0 + x] * w0;
|
|
83
|
-
else if (n === 2)
|
|
84
|
-
for (let x = 0; x < stride; x++)
|
|
85
|
-
next[o + x] = Math.fround(0 + plane[s0 + x] * w0) + plane[s1 + x] * w1;
|
|
86
|
-
else if (n === 3) {
|
|
87
|
-
for (let x = 0; x < stride; x++)
|
|
88
|
-
next[o + x] = Math.fround(Math.fround(0 + plane[s0 + x] * w0) + plane[s1 + x] * w1) + plane[s2 + x] * w2;
|
|
89
|
-
}
|
|
90
|
-
else if (n === 4) {
|
|
91
|
-
for (let x = 0; x < stride; x++)
|
|
92
|
-
next[o + x] = Math.fround(Math.fround(Math.fround(0 + plane[s0 + x] * w0) + plane[s1 + x] * w1) + plane[s2 + x] * w2) + plane[s3 + x] * w3;
|
|
240
|
+
const { start, weights, taps } = outWidth === width ? { start: null, weights: null, taps: 0 } : coefficients(width, outWidth, filter, BITS);
|
|
241
|
+
for (let y = 0, o = 0; y < outHeight; y++) {
|
|
242
|
+
const row = y * width * 4;
|
|
243
|
+
for (let x = 0; x < outWidth; x++, o += 4) {
|
|
244
|
+
let r = 0, g = 0, b = 0, a = 0;
|
|
245
|
+
if (!start || !weights) {
|
|
246
|
+
const s = row + x * 4;
|
|
247
|
+
r = plane[s] * ONE;
|
|
248
|
+
g = plane[s + 1] * ONE;
|
|
249
|
+
b = plane[s + 2] * ONE;
|
|
250
|
+
a = plane[s + 3] * ONE;
|
|
93
251
|
}
|
|
94
252
|
else {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
253
|
+
let k = 0, s = row + start[x] * 4, w = x * taps;
|
|
254
|
+
for (; k + 1 < taps; k += 2, s += 8) {
|
|
255
|
+
const w0 = weights[w + k], w1 = weights[w + k + 1];
|
|
256
|
+
r += plane[s] * w0 + plane[s + 4] * w1;
|
|
257
|
+
g += plane[s + 1] * w0 + plane[s + 5] * w1;
|
|
258
|
+
b += plane[s + 2] * w0 + plane[s + 6] * w1;
|
|
259
|
+
a += plane[s + 3] * w0 + plane[s + 7] * w1;
|
|
260
|
+
}
|
|
261
|
+
if (k < taps) {
|
|
262
|
+
const w0 = weights[w + k];
|
|
263
|
+
r += plane[s] * w0;
|
|
264
|
+
g += plane[s + 1] * w0;
|
|
265
|
+
b += plane[s + 2] * w0;
|
|
266
|
+
a += plane[s + 3] * w0;
|
|
100
267
|
}
|
|
101
268
|
}
|
|
269
|
+
if (a < 127.5 * ONE) {
|
|
270
|
+
out[o] = out[o + 1] = out[o + 2] = out[o + 3] = 0;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const f = 255 / Math.min(a, 65025 * ONE);
|
|
274
|
+
out[o] = r * f;
|
|
275
|
+
out[o + 1] = g * f;
|
|
276
|
+
out[o + 2] = b * f;
|
|
277
|
+
out[o + 3] = a / (255 * ONE);
|
|
102
278
|
}
|
|
103
|
-
plane = next;
|
|
104
|
-
}
|
|
105
|
-
for (let i = 0; i < plane.length; i += 4) {
|
|
106
|
-
const a = plane[i + 3];
|
|
107
|
-
if (a < 0.5) {
|
|
108
|
-
out[i] = out[i + 1] = out[i + 2] = out[i + 3] = 0;
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
const f = 255 / Math.min(255, a);
|
|
112
|
-
out[i] = plane[i] * f;
|
|
113
|
-
out[i + 1] = plane[i + 1] * f;
|
|
114
|
-
out[i + 2] = plane[i + 2] * f;
|
|
115
|
-
out[i + 3] = a;
|
|
116
279
|
}
|
|
117
280
|
}
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '3.2.
|
|
1
|
+
export const VERSION = '3.2.1';
|