token-goat 2.9.15 → 2.9.16
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/{token-goat-chunk-ASYEPR3S.mjs → token-goat-chunk-2IEIBVVD.mjs} +7 -3
- package/dist/{token-goat-chunk-LCZBPOIN.mjs → token-goat-chunk-2PCFAQAS.mjs} +66 -51
- package/dist/{token-goat-chunk-PM76YS22.mjs → token-goat-chunk-3H6FQT62.mjs} +1 -1
- package/dist/{token-goat-chunk-C5JIO6HK.mjs → token-goat-chunk-4DC6DDIB.mjs} +5 -5
- package/dist/{token-goat-chunk-YQ7WI2CO.mjs → token-goat-chunk-5USHO7B6.mjs} +393 -3957
- package/dist/{token-goat-chunk-2X2EBBC6.mjs → token-goat-chunk-63QWJ6UM.mjs} +2 -2
- package/dist/{token-goat-chunk-NDRP4KJQ.mjs → token-goat-chunk-BFNTLGVA.mjs} +226 -50
- package/dist/token-goat-chunk-BGHSSJUA.mjs +102 -0
- package/dist/{token-goat-chunk-IVUQLQWN.mjs → token-goat-chunk-DMQ32ZSR.mjs} +5 -3
- package/dist/{token-goat-chunk-SFAS46RE.mjs → token-goat-chunk-EJCY6KHO.mjs} +2 -2
- package/dist/{token-goat-chunk-Z6UXPYJA.mjs → token-goat-chunk-F2ARFHLJ.mjs} +1 -1
- package/dist/{token-goat-chunk-YKG35VHC.mjs → token-goat-chunk-GIMGT34T.mjs} +1 -1
- package/dist/{token-goat-chunk-SZWYESBS.mjs → token-goat-chunk-GMXBQS6O.mjs} +155 -54
- package/dist/{token-goat-chunk-S4XRY446.mjs → token-goat-chunk-H3DXI6VD.mjs} +4 -3
- package/dist/{token-goat-chunk-6DLVZDB6.mjs → token-goat-chunk-LJL6FGDS.mjs} +13 -12
- package/dist/{token-goat-chunk-NEI4NC54.mjs → token-goat-chunk-LKSXAMJB.mjs} +7 -2
- package/dist/{token-goat-chunk-A4JYKD5H.mjs → token-goat-chunk-M2R4UQ3B.mjs} +2 -2
- package/dist/{token-goat-chunk-MZDIJJ3R.mjs → token-goat-chunk-MA5BZ2KI.mjs} +40 -3
- package/dist/{token-goat-chunk-GIIHUSZX.mjs → token-goat-chunk-MIL62GMN.mjs} +41 -11
- package/dist/{token-goat-chunk-NU7TLMQK.mjs → token-goat-chunk-NAMH252H.mjs} +10 -7
- package/dist/{token-goat-chunk-DQ4J5AFF.mjs → token-goat-chunk-NOBZV7PM.mjs} +69 -18
- package/dist/{token-goat-chunk-5V7DAC7V.mjs → token-goat-chunk-NQZCSVN2.mjs} +10 -3
- package/dist/{token-goat-chunk-7ZYK25AO.mjs → token-goat-chunk-OCI25AXY.mjs} +4 -4
- package/dist/{token-goat-chunk-NDPO7GAH.mjs → token-goat-chunk-QMZMHQRR.mjs} +21 -20
- package/dist/{token-goat-chunk-K7F2BFIK.mjs → token-goat-chunk-R3X5TCPB.mjs} +1 -1
- package/dist/token-goat-chunk-RRNZMM3A.mjs +3364 -0
- package/dist/{token-goat-chunk-ATIFTMRC.mjs → token-goat-chunk-ULA4WCED.mjs} +7 -7
- package/dist/{token-goat-chunk-OUGNPMDA.mjs → token-goat-chunk-UMXD2M7O.mjs} +30 -14
- package/dist/{token-goat-chunk-YZX7EFG4.mjs → token-goat-chunk-UXHDBVUR.mjs} +1 -1
- package/dist/{token-goat-chunk-LT7JRU6K.mjs → token-goat-chunk-VVIYEFBI.mjs} +4 -4
- package/dist/{token-goat-chunk-BL5LNGBG.mjs → token-goat-chunk-XOHTFRDH.mjs} +2966 -3869
- package/dist/{token-goat-chunk-XEPXYDPI.mjs → token-goat-chunk-YPS64ACE.mjs} +11 -2
- package/dist/{token-goat-chunk-GMQQA7E4.mjs → token-goat-chunk-Z5VPAXTC.mjs} +2442 -722
- package/dist/{token-goat-chunk-3NSDDTGL.mjs → token-goat-chunk-ZEHFYJ7Z.mjs} +5 -5
- package/dist/token-goat-hook.mjs +13 -12
- package/dist/token-goat.core.mjs +21 -20
- package/package.json +1 -1
|
@@ -0,0 +1,3364 @@
|
|
|
1
|
+
import { createRequire as __cjsRequire } from 'node:module';
|
|
2
|
+
const require = __cjsRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
__commonJS,
|
|
5
|
+
__toESM,
|
|
6
|
+
init_define_import_meta_env
|
|
7
|
+
} from "./token-goat-chunk-A37V4PBF.mjs";
|
|
8
|
+
|
|
9
|
+
// node_modules/omggif/omggif.js
|
|
10
|
+
var require_omggif = __commonJS({
|
|
11
|
+
"node_modules/omggif/omggif.js"(exports) {
|
|
12
|
+
"use strict";
|
|
13
|
+
init_define_import_meta_env();
|
|
14
|
+
function GifWriter(buf, width, height, gopts) {
|
|
15
|
+
var p = 0;
|
|
16
|
+
var gopts = gopts === void 0 ? {} : gopts;
|
|
17
|
+
var loop_count = gopts.loop === void 0 ? null : gopts.loop;
|
|
18
|
+
var global_palette = gopts.palette === void 0 ? null : gopts.palette;
|
|
19
|
+
if (width <= 0 || height <= 0 || width > 65535 || height > 65535)
|
|
20
|
+
throw new Error("Width/Height invalid.");
|
|
21
|
+
function check_palette_and_num_colors(palette) {
|
|
22
|
+
var num_colors = palette.length;
|
|
23
|
+
if (num_colors < 2 || num_colors > 256 || num_colors & num_colors - 1) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
"Invalid code/color length, must be power of 2 and 2 .. 256."
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return num_colors;
|
|
29
|
+
}
|
|
30
|
+
buf[p++] = 71;
|
|
31
|
+
buf[p++] = 73;
|
|
32
|
+
buf[p++] = 70;
|
|
33
|
+
buf[p++] = 56;
|
|
34
|
+
buf[p++] = 57;
|
|
35
|
+
buf[p++] = 97;
|
|
36
|
+
var gp_num_colors_pow2 = 0;
|
|
37
|
+
var background = 0;
|
|
38
|
+
if (global_palette !== null) {
|
|
39
|
+
var gp_num_colors = check_palette_and_num_colors(global_palette);
|
|
40
|
+
while (gp_num_colors >>= 1) ++gp_num_colors_pow2;
|
|
41
|
+
gp_num_colors = 1 << gp_num_colors_pow2;
|
|
42
|
+
--gp_num_colors_pow2;
|
|
43
|
+
if (gopts.background !== void 0) {
|
|
44
|
+
background = gopts.background;
|
|
45
|
+
if (background >= gp_num_colors)
|
|
46
|
+
throw new Error("Background index out of range.");
|
|
47
|
+
if (background === 0)
|
|
48
|
+
throw new Error("Background index explicitly passed as 0.");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
buf[p++] = width & 255;
|
|
52
|
+
buf[p++] = width >> 8 & 255;
|
|
53
|
+
buf[p++] = height & 255;
|
|
54
|
+
buf[p++] = height >> 8 & 255;
|
|
55
|
+
buf[p++] = (global_palette !== null ? 128 : 0) | // Global Color Table Flag.
|
|
56
|
+
gp_num_colors_pow2;
|
|
57
|
+
buf[p++] = background;
|
|
58
|
+
buf[p++] = 0;
|
|
59
|
+
if (global_palette !== null) {
|
|
60
|
+
for (var i = 0, il = global_palette.length; i < il; ++i) {
|
|
61
|
+
var rgb = global_palette[i];
|
|
62
|
+
buf[p++] = rgb >> 16 & 255;
|
|
63
|
+
buf[p++] = rgb >> 8 & 255;
|
|
64
|
+
buf[p++] = rgb & 255;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (loop_count !== null) {
|
|
68
|
+
if (loop_count < 0 || loop_count > 65535)
|
|
69
|
+
throw new Error("Loop count invalid.");
|
|
70
|
+
buf[p++] = 33;
|
|
71
|
+
buf[p++] = 255;
|
|
72
|
+
buf[p++] = 11;
|
|
73
|
+
buf[p++] = 78;
|
|
74
|
+
buf[p++] = 69;
|
|
75
|
+
buf[p++] = 84;
|
|
76
|
+
buf[p++] = 83;
|
|
77
|
+
buf[p++] = 67;
|
|
78
|
+
buf[p++] = 65;
|
|
79
|
+
buf[p++] = 80;
|
|
80
|
+
buf[p++] = 69;
|
|
81
|
+
buf[p++] = 50;
|
|
82
|
+
buf[p++] = 46;
|
|
83
|
+
buf[p++] = 48;
|
|
84
|
+
buf[p++] = 3;
|
|
85
|
+
buf[p++] = 1;
|
|
86
|
+
buf[p++] = loop_count & 255;
|
|
87
|
+
buf[p++] = loop_count >> 8 & 255;
|
|
88
|
+
buf[p++] = 0;
|
|
89
|
+
}
|
|
90
|
+
var ended = false;
|
|
91
|
+
this.addFrame = function(x, y, w, h, indexed_pixels, opts) {
|
|
92
|
+
if (ended === true) {
|
|
93
|
+
--p;
|
|
94
|
+
ended = false;
|
|
95
|
+
}
|
|
96
|
+
opts = opts === void 0 ? {} : opts;
|
|
97
|
+
if (x < 0 || y < 0 || x > 65535 || y > 65535)
|
|
98
|
+
throw new Error("x/y invalid.");
|
|
99
|
+
if (w <= 0 || h <= 0 || w > 65535 || h > 65535)
|
|
100
|
+
throw new Error("Width/Height invalid.");
|
|
101
|
+
if (indexed_pixels.length < w * h)
|
|
102
|
+
throw new Error("Not enough pixels for the frame size.");
|
|
103
|
+
var using_local_palette = true;
|
|
104
|
+
var palette = opts.palette;
|
|
105
|
+
if (palette === void 0 || palette === null) {
|
|
106
|
+
using_local_palette = false;
|
|
107
|
+
palette = global_palette;
|
|
108
|
+
}
|
|
109
|
+
if (palette === void 0 || palette === null)
|
|
110
|
+
throw new Error("Must supply either a local or global palette.");
|
|
111
|
+
var num_colors = check_palette_and_num_colors(palette);
|
|
112
|
+
var min_code_size = 0;
|
|
113
|
+
while (num_colors >>= 1) ++min_code_size;
|
|
114
|
+
num_colors = 1 << min_code_size;
|
|
115
|
+
var delay = opts.delay === void 0 ? 0 : opts.delay;
|
|
116
|
+
var disposal = opts.disposal === void 0 ? 0 : opts.disposal;
|
|
117
|
+
if (disposal < 0 || disposal > 3)
|
|
118
|
+
throw new Error("Disposal out of range.");
|
|
119
|
+
var use_transparency = false;
|
|
120
|
+
var transparent_index = 0;
|
|
121
|
+
if (opts.transparent !== void 0 && opts.transparent !== null) {
|
|
122
|
+
use_transparency = true;
|
|
123
|
+
transparent_index = opts.transparent;
|
|
124
|
+
if (transparent_index < 0 || transparent_index >= num_colors)
|
|
125
|
+
throw new Error("Transparent color index.");
|
|
126
|
+
}
|
|
127
|
+
if (disposal !== 0 || use_transparency || delay !== 0) {
|
|
128
|
+
buf[p++] = 33;
|
|
129
|
+
buf[p++] = 249;
|
|
130
|
+
buf[p++] = 4;
|
|
131
|
+
buf[p++] = disposal << 2 | (use_transparency === true ? 1 : 0);
|
|
132
|
+
buf[p++] = delay & 255;
|
|
133
|
+
buf[p++] = delay >> 8 & 255;
|
|
134
|
+
buf[p++] = transparent_index;
|
|
135
|
+
buf[p++] = 0;
|
|
136
|
+
}
|
|
137
|
+
buf[p++] = 44;
|
|
138
|
+
buf[p++] = x & 255;
|
|
139
|
+
buf[p++] = x >> 8 & 255;
|
|
140
|
+
buf[p++] = y & 255;
|
|
141
|
+
buf[p++] = y >> 8 & 255;
|
|
142
|
+
buf[p++] = w & 255;
|
|
143
|
+
buf[p++] = w >> 8 & 255;
|
|
144
|
+
buf[p++] = h & 255;
|
|
145
|
+
buf[p++] = h >> 8 & 255;
|
|
146
|
+
buf[p++] = using_local_palette === true ? 128 | min_code_size - 1 : 0;
|
|
147
|
+
if (using_local_palette === true) {
|
|
148
|
+
for (var i2 = 0, il2 = palette.length; i2 < il2; ++i2) {
|
|
149
|
+
var rgb2 = palette[i2];
|
|
150
|
+
buf[p++] = rgb2 >> 16 & 255;
|
|
151
|
+
buf[p++] = rgb2 >> 8 & 255;
|
|
152
|
+
buf[p++] = rgb2 & 255;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
p = GifWriterOutputLZWCodeStream(
|
|
156
|
+
buf,
|
|
157
|
+
p,
|
|
158
|
+
min_code_size < 2 ? 2 : min_code_size,
|
|
159
|
+
indexed_pixels
|
|
160
|
+
);
|
|
161
|
+
return p;
|
|
162
|
+
};
|
|
163
|
+
this.end = function() {
|
|
164
|
+
if (ended === false) {
|
|
165
|
+
buf[p++] = 59;
|
|
166
|
+
ended = true;
|
|
167
|
+
}
|
|
168
|
+
return p;
|
|
169
|
+
};
|
|
170
|
+
this.getOutputBuffer = function() {
|
|
171
|
+
return buf;
|
|
172
|
+
};
|
|
173
|
+
this.setOutputBuffer = function(v) {
|
|
174
|
+
buf = v;
|
|
175
|
+
};
|
|
176
|
+
this.getOutputBufferPosition = function() {
|
|
177
|
+
return p;
|
|
178
|
+
};
|
|
179
|
+
this.setOutputBufferPosition = function(v) {
|
|
180
|
+
p = v;
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function GifWriterOutputLZWCodeStream(buf, p, min_code_size, index_stream) {
|
|
184
|
+
buf[p++] = min_code_size;
|
|
185
|
+
var cur_subblock = p++;
|
|
186
|
+
var clear_code = 1 << min_code_size;
|
|
187
|
+
var code_mask = clear_code - 1;
|
|
188
|
+
var eoi_code = clear_code + 1;
|
|
189
|
+
var next_code = eoi_code + 1;
|
|
190
|
+
var cur_code_size = min_code_size + 1;
|
|
191
|
+
var cur_shift = 0;
|
|
192
|
+
var cur = 0;
|
|
193
|
+
function emit_bytes_to_buffer(bit_block_size) {
|
|
194
|
+
while (cur_shift >= bit_block_size) {
|
|
195
|
+
buf[p++] = cur & 255;
|
|
196
|
+
cur >>= 8;
|
|
197
|
+
cur_shift -= 8;
|
|
198
|
+
if (p === cur_subblock + 256) {
|
|
199
|
+
buf[cur_subblock] = 255;
|
|
200
|
+
cur_subblock = p++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
function emit_code(c) {
|
|
205
|
+
cur |= c << cur_shift;
|
|
206
|
+
cur_shift += cur_code_size;
|
|
207
|
+
emit_bytes_to_buffer(8);
|
|
208
|
+
}
|
|
209
|
+
var ib_code = index_stream[0] & code_mask;
|
|
210
|
+
var code_table = {};
|
|
211
|
+
emit_code(clear_code);
|
|
212
|
+
for (var i = 1, il = index_stream.length; i < il; ++i) {
|
|
213
|
+
var k = index_stream[i] & code_mask;
|
|
214
|
+
var cur_key = ib_code << 8 | k;
|
|
215
|
+
var cur_code = code_table[cur_key];
|
|
216
|
+
if (cur_code === void 0) {
|
|
217
|
+
cur |= ib_code << cur_shift;
|
|
218
|
+
cur_shift += cur_code_size;
|
|
219
|
+
while (cur_shift >= 8) {
|
|
220
|
+
buf[p++] = cur & 255;
|
|
221
|
+
cur >>= 8;
|
|
222
|
+
cur_shift -= 8;
|
|
223
|
+
if (p === cur_subblock + 256) {
|
|
224
|
+
buf[cur_subblock] = 255;
|
|
225
|
+
cur_subblock = p++;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (next_code === 4096) {
|
|
229
|
+
emit_code(clear_code);
|
|
230
|
+
next_code = eoi_code + 1;
|
|
231
|
+
cur_code_size = min_code_size + 1;
|
|
232
|
+
code_table = {};
|
|
233
|
+
} else {
|
|
234
|
+
if (next_code >= 1 << cur_code_size) ++cur_code_size;
|
|
235
|
+
code_table[cur_key] = next_code++;
|
|
236
|
+
}
|
|
237
|
+
ib_code = k;
|
|
238
|
+
} else {
|
|
239
|
+
ib_code = cur_code;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
emit_code(ib_code);
|
|
243
|
+
emit_code(eoi_code);
|
|
244
|
+
emit_bytes_to_buffer(1);
|
|
245
|
+
if (cur_subblock + 1 === p) {
|
|
246
|
+
buf[cur_subblock] = 0;
|
|
247
|
+
} else {
|
|
248
|
+
buf[cur_subblock] = p - cur_subblock - 1;
|
|
249
|
+
buf[p++] = 0;
|
|
250
|
+
}
|
|
251
|
+
return p;
|
|
252
|
+
}
|
|
253
|
+
function GifReader(buf) {
|
|
254
|
+
var p = 0;
|
|
255
|
+
if (buf[p++] !== 71 || buf[p++] !== 73 || buf[p++] !== 70 || buf[p++] !== 56 || (buf[p++] + 1 & 253) !== 56 || buf[p++] !== 97) {
|
|
256
|
+
throw new Error("Invalid GIF 87a/89a header.");
|
|
257
|
+
}
|
|
258
|
+
var width = buf[p++] | buf[p++] << 8;
|
|
259
|
+
var height = buf[p++] | buf[p++] << 8;
|
|
260
|
+
var pf0 = buf[p++];
|
|
261
|
+
var global_palette_flag = pf0 >> 7;
|
|
262
|
+
var num_global_colors_pow2 = pf0 & 7;
|
|
263
|
+
var num_global_colors = 1 << num_global_colors_pow2 + 1;
|
|
264
|
+
var background = buf[p++];
|
|
265
|
+
buf[p++];
|
|
266
|
+
var global_palette_offset = null;
|
|
267
|
+
var global_palette_size = null;
|
|
268
|
+
if (global_palette_flag) {
|
|
269
|
+
global_palette_offset = p;
|
|
270
|
+
global_palette_size = num_global_colors;
|
|
271
|
+
p += num_global_colors * 3;
|
|
272
|
+
}
|
|
273
|
+
var no_eof = true;
|
|
274
|
+
var frames = [];
|
|
275
|
+
var delay = 0;
|
|
276
|
+
var transparent_index = null;
|
|
277
|
+
var disposal = 0;
|
|
278
|
+
var loop_count = null;
|
|
279
|
+
this.width = width;
|
|
280
|
+
this.height = height;
|
|
281
|
+
while (no_eof && p < buf.length) {
|
|
282
|
+
switch (buf[p++]) {
|
|
283
|
+
case 33:
|
|
284
|
+
switch (buf[p++]) {
|
|
285
|
+
case 255:
|
|
286
|
+
if (buf[p] !== 11 || // 21 FF already read, check block size.
|
|
287
|
+
// NETSCAPE2.0
|
|
288
|
+
buf[p + 1] == 78 && buf[p + 2] == 69 && buf[p + 3] == 84 && buf[p + 4] == 83 && buf[p + 5] == 67 && buf[p + 6] == 65 && buf[p + 7] == 80 && buf[p + 8] == 69 && buf[p + 9] == 50 && buf[p + 10] == 46 && buf[p + 11] == 48 && // Sub-block
|
|
289
|
+
buf[p + 12] == 3 && buf[p + 13] == 1 && buf[p + 16] == 0) {
|
|
290
|
+
p += 14;
|
|
291
|
+
loop_count = buf[p++] | buf[p++] << 8;
|
|
292
|
+
p++;
|
|
293
|
+
} else {
|
|
294
|
+
p += 12;
|
|
295
|
+
while (true) {
|
|
296
|
+
var block_size = buf[p++];
|
|
297
|
+
if (!(block_size >= 0)) throw Error("Invalid block size");
|
|
298
|
+
if (block_size === 0) break;
|
|
299
|
+
p += block_size;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
break;
|
|
303
|
+
case 249:
|
|
304
|
+
if (buf[p++] !== 4 || buf[p + 4] !== 0)
|
|
305
|
+
throw new Error("Invalid graphics extension block.");
|
|
306
|
+
var pf1 = buf[p++];
|
|
307
|
+
delay = buf[p++] | buf[p++] << 8;
|
|
308
|
+
transparent_index = buf[p++];
|
|
309
|
+
if ((pf1 & 1) === 0) transparent_index = null;
|
|
310
|
+
disposal = pf1 >> 2 & 7;
|
|
311
|
+
p++;
|
|
312
|
+
break;
|
|
313
|
+
case 254:
|
|
314
|
+
while (true) {
|
|
315
|
+
var block_size = buf[p++];
|
|
316
|
+
if (!(block_size >= 0)) throw Error("Invalid block size");
|
|
317
|
+
if (block_size === 0) break;
|
|
318
|
+
p += block_size;
|
|
319
|
+
}
|
|
320
|
+
break;
|
|
321
|
+
default:
|
|
322
|
+
throw new Error(
|
|
323
|
+
"Unknown graphic control label: 0x" + buf[p - 1].toString(16)
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
break;
|
|
327
|
+
case 44:
|
|
328
|
+
var x = buf[p++] | buf[p++] << 8;
|
|
329
|
+
var y = buf[p++] | buf[p++] << 8;
|
|
330
|
+
var w = buf[p++] | buf[p++] << 8;
|
|
331
|
+
var h = buf[p++] | buf[p++] << 8;
|
|
332
|
+
var pf2 = buf[p++];
|
|
333
|
+
var local_palette_flag = pf2 >> 7;
|
|
334
|
+
var interlace_flag = pf2 >> 6 & 1;
|
|
335
|
+
var num_local_colors_pow2 = pf2 & 7;
|
|
336
|
+
var num_local_colors = 1 << num_local_colors_pow2 + 1;
|
|
337
|
+
var palette_offset = global_palette_offset;
|
|
338
|
+
var palette_size = global_palette_size;
|
|
339
|
+
var has_local_palette = false;
|
|
340
|
+
if (local_palette_flag) {
|
|
341
|
+
var has_local_palette = true;
|
|
342
|
+
palette_offset = p;
|
|
343
|
+
palette_size = num_local_colors;
|
|
344
|
+
p += num_local_colors * 3;
|
|
345
|
+
}
|
|
346
|
+
var data_offset = p;
|
|
347
|
+
p++;
|
|
348
|
+
while (true) {
|
|
349
|
+
var block_size = buf[p++];
|
|
350
|
+
if (!(block_size >= 0)) throw Error("Invalid block size");
|
|
351
|
+
if (block_size === 0) break;
|
|
352
|
+
p += block_size;
|
|
353
|
+
}
|
|
354
|
+
frames.push({
|
|
355
|
+
x,
|
|
356
|
+
y,
|
|
357
|
+
width: w,
|
|
358
|
+
height: h,
|
|
359
|
+
has_local_palette,
|
|
360
|
+
palette_offset,
|
|
361
|
+
palette_size,
|
|
362
|
+
data_offset,
|
|
363
|
+
data_length: p - data_offset,
|
|
364
|
+
transparent_index,
|
|
365
|
+
interlaced: !!interlace_flag,
|
|
366
|
+
delay,
|
|
367
|
+
disposal
|
|
368
|
+
});
|
|
369
|
+
break;
|
|
370
|
+
case 59:
|
|
371
|
+
no_eof = false;
|
|
372
|
+
break;
|
|
373
|
+
default:
|
|
374
|
+
throw new Error("Unknown gif block: 0x" + buf[p - 1].toString(16));
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
this.numFrames = function() {
|
|
379
|
+
return frames.length;
|
|
380
|
+
};
|
|
381
|
+
this.loopCount = function() {
|
|
382
|
+
return loop_count;
|
|
383
|
+
};
|
|
384
|
+
this.frameInfo = function(frame_num) {
|
|
385
|
+
if (frame_num < 0 || frame_num >= frames.length)
|
|
386
|
+
throw new Error("Frame index out of range.");
|
|
387
|
+
return frames[frame_num];
|
|
388
|
+
};
|
|
389
|
+
this.decodeAndBlitFrameBGRA = function(frame_num, pixels) {
|
|
390
|
+
var frame = this.frameInfo(frame_num);
|
|
391
|
+
var num_pixels = frame.width * frame.height;
|
|
392
|
+
var index_stream = new Uint8Array(num_pixels);
|
|
393
|
+
GifReaderLZWOutputIndexStream(
|
|
394
|
+
buf,
|
|
395
|
+
frame.data_offset,
|
|
396
|
+
index_stream,
|
|
397
|
+
num_pixels
|
|
398
|
+
);
|
|
399
|
+
var palette_offset2 = frame.palette_offset;
|
|
400
|
+
var trans = frame.transparent_index;
|
|
401
|
+
if (trans === null) trans = 256;
|
|
402
|
+
var framewidth = frame.width;
|
|
403
|
+
var framestride = width - framewidth;
|
|
404
|
+
var xleft = framewidth;
|
|
405
|
+
var opbeg = (frame.y * width + frame.x) * 4;
|
|
406
|
+
var opend = ((frame.y + frame.height) * width + frame.x) * 4;
|
|
407
|
+
var op = opbeg;
|
|
408
|
+
var scanstride = framestride * 4;
|
|
409
|
+
if (frame.interlaced === true) {
|
|
410
|
+
scanstride += width * 4 * 7;
|
|
411
|
+
}
|
|
412
|
+
var interlaceskip = 8;
|
|
413
|
+
for (var i = 0, il = index_stream.length; i < il; ++i) {
|
|
414
|
+
var index = index_stream[i];
|
|
415
|
+
if (xleft === 0) {
|
|
416
|
+
op += scanstride;
|
|
417
|
+
xleft = framewidth;
|
|
418
|
+
if (op >= opend) {
|
|
419
|
+
scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
|
|
420
|
+
op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
|
|
421
|
+
interlaceskip >>= 1;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (index === trans) {
|
|
425
|
+
op += 4;
|
|
426
|
+
} else {
|
|
427
|
+
var r = buf[palette_offset2 + index * 3];
|
|
428
|
+
var g = buf[palette_offset2 + index * 3 + 1];
|
|
429
|
+
var b = buf[palette_offset2 + index * 3 + 2];
|
|
430
|
+
pixels[op++] = b;
|
|
431
|
+
pixels[op++] = g;
|
|
432
|
+
pixels[op++] = r;
|
|
433
|
+
pixels[op++] = 255;
|
|
434
|
+
}
|
|
435
|
+
--xleft;
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
this.decodeAndBlitFrameRGBA = function(frame_num, pixels) {
|
|
439
|
+
var frame = this.frameInfo(frame_num);
|
|
440
|
+
var num_pixels = frame.width * frame.height;
|
|
441
|
+
var index_stream = new Uint8Array(num_pixels);
|
|
442
|
+
GifReaderLZWOutputIndexStream(
|
|
443
|
+
buf,
|
|
444
|
+
frame.data_offset,
|
|
445
|
+
index_stream,
|
|
446
|
+
num_pixels
|
|
447
|
+
);
|
|
448
|
+
var palette_offset2 = frame.palette_offset;
|
|
449
|
+
var trans = frame.transparent_index;
|
|
450
|
+
if (trans === null) trans = 256;
|
|
451
|
+
var framewidth = frame.width;
|
|
452
|
+
var framestride = width - framewidth;
|
|
453
|
+
var xleft = framewidth;
|
|
454
|
+
var opbeg = (frame.y * width + frame.x) * 4;
|
|
455
|
+
var opend = ((frame.y + frame.height) * width + frame.x) * 4;
|
|
456
|
+
var op = opbeg;
|
|
457
|
+
var scanstride = framestride * 4;
|
|
458
|
+
if (frame.interlaced === true) {
|
|
459
|
+
scanstride += width * 4 * 7;
|
|
460
|
+
}
|
|
461
|
+
var interlaceskip = 8;
|
|
462
|
+
for (var i = 0, il = index_stream.length; i < il; ++i) {
|
|
463
|
+
var index = index_stream[i];
|
|
464
|
+
if (xleft === 0) {
|
|
465
|
+
op += scanstride;
|
|
466
|
+
xleft = framewidth;
|
|
467
|
+
if (op >= opend) {
|
|
468
|
+
scanstride = framestride * 4 + width * 4 * (interlaceskip - 1);
|
|
469
|
+
op = opbeg + (framewidth + framestride) * (interlaceskip << 1);
|
|
470
|
+
interlaceskip >>= 1;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (index === trans) {
|
|
474
|
+
op += 4;
|
|
475
|
+
} else {
|
|
476
|
+
var r = buf[palette_offset2 + index * 3];
|
|
477
|
+
var g = buf[palette_offset2 + index * 3 + 1];
|
|
478
|
+
var b = buf[palette_offset2 + index * 3 + 2];
|
|
479
|
+
pixels[op++] = r;
|
|
480
|
+
pixels[op++] = g;
|
|
481
|
+
pixels[op++] = b;
|
|
482
|
+
pixels[op++] = 255;
|
|
483
|
+
}
|
|
484
|
+
--xleft;
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
function GifReaderLZWOutputIndexStream(code_stream, p, output, output_length) {
|
|
489
|
+
var min_code_size = code_stream[p++];
|
|
490
|
+
var clear_code = 1 << min_code_size;
|
|
491
|
+
var eoi_code = clear_code + 1;
|
|
492
|
+
var next_code = eoi_code + 1;
|
|
493
|
+
var cur_code_size = min_code_size + 1;
|
|
494
|
+
var code_mask = (1 << cur_code_size) - 1;
|
|
495
|
+
var cur_shift = 0;
|
|
496
|
+
var cur = 0;
|
|
497
|
+
var op = 0;
|
|
498
|
+
var subblock_size = code_stream[p++];
|
|
499
|
+
var code_table = new Int32Array(4096);
|
|
500
|
+
var prev_code = null;
|
|
501
|
+
while (true) {
|
|
502
|
+
while (cur_shift < 16) {
|
|
503
|
+
if (subblock_size === 0) break;
|
|
504
|
+
cur |= code_stream[p++] << cur_shift;
|
|
505
|
+
cur_shift += 8;
|
|
506
|
+
if (subblock_size === 1) {
|
|
507
|
+
subblock_size = code_stream[p++];
|
|
508
|
+
} else {
|
|
509
|
+
--subblock_size;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (cur_shift < cur_code_size)
|
|
513
|
+
break;
|
|
514
|
+
var code = cur & code_mask;
|
|
515
|
+
cur >>= cur_code_size;
|
|
516
|
+
cur_shift -= cur_code_size;
|
|
517
|
+
if (code === clear_code) {
|
|
518
|
+
next_code = eoi_code + 1;
|
|
519
|
+
cur_code_size = min_code_size + 1;
|
|
520
|
+
code_mask = (1 << cur_code_size) - 1;
|
|
521
|
+
prev_code = null;
|
|
522
|
+
continue;
|
|
523
|
+
} else if (code === eoi_code) {
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
var chase_code = code < next_code ? code : prev_code;
|
|
527
|
+
var chase_length = 0;
|
|
528
|
+
var chase = chase_code;
|
|
529
|
+
while (chase > clear_code) {
|
|
530
|
+
chase = code_table[chase] >> 8;
|
|
531
|
+
++chase_length;
|
|
532
|
+
}
|
|
533
|
+
var k = chase;
|
|
534
|
+
var op_end = op + chase_length + (chase_code !== code ? 1 : 0);
|
|
535
|
+
if (op_end > output_length) {
|
|
536
|
+
console.log("Warning, gif stream longer than expected.");
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
output[op++] = k;
|
|
540
|
+
op += chase_length;
|
|
541
|
+
var b = op;
|
|
542
|
+
if (chase_code !== code)
|
|
543
|
+
output[op++] = k;
|
|
544
|
+
chase = chase_code;
|
|
545
|
+
while (chase_length--) {
|
|
546
|
+
chase = code_table[chase];
|
|
547
|
+
output[--b] = chase & 255;
|
|
548
|
+
chase >>= 8;
|
|
549
|
+
}
|
|
550
|
+
if (prev_code !== null && next_code < 4096) {
|
|
551
|
+
code_table[next_code++] = prev_code << 8 | k;
|
|
552
|
+
if (next_code >= code_mask + 1 && cur_code_size < 12) {
|
|
553
|
+
++cur_code_size;
|
|
554
|
+
code_mask = code_mask << 1 | 1;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
prev_code = code;
|
|
558
|
+
}
|
|
559
|
+
if (op !== output_length) {
|
|
560
|
+
console.log("Warning, gif stream shorter than expected.");
|
|
561
|
+
}
|
|
562
|
+
return output;
|
|
563
|
+
}
|
|
564
|
+
try {
|
|
565
|
+
exports.GifWriter = GifWriter;
|
|
566
|
+
exports.GifReader = GifReader;
|
|
567
|
+
} catch (e) {
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// node_modules/jpeg-js/lib/encoder.js
|
|
573
|
+
var require_encoder = __commonJS({
|
|
574
|
+
"node_modules/jpeg-js/lib/encoder.js"(exports, module) {
|
|
575
|
+
init_define_import_meta_env();
|
|
576
|
+
var btoa = btoa || function(buf) {
|
|
577
|
+
return Buffer.from(buf).toString("base64");
|
|
578
|
+
};
|
|
579
|
+
function JPEGEncoder(quality) {
|
|
580
|
+
var self = this;
|
|
581
|
+
var fround = Math.round;
|
|
582
|
+
var ffloor = Math.floor;
|
|
583
|
+
var YTable = new Array(64);
|
|
584
|
+
var UVTable = new Array(64);
|
|
585
|
+
var fdtbl_Y = new Array(64);
|
|
586
|
+
var fdtbl_UV = new Array(64);
|
|
587
|
+
var YDC_HT;
|
|
588
|
+
var UVDC_HT;
|
|
589
|
+
var YAC_HT;
|
|
590
|
+
var UVAC_HT;
|
|
591
|
+
var bitcode = new Array(65535);
|
|
592
|
+
var category = new Array(65535);
|
|
593
|
+
var outputfDCTQuant = new Array(64);
|
|
594
|
+
var DU = new Array(64);
|
|
595
|
+
var byteout = [];
|
|
596
|
+
var bytenew = 0;
|
|
597
|
+
var bytepos = 7;
|
|
598
|
+
var YDU = new Array(64);
|
|
599
|
+
var UDU = new Array(64);
|
|
600
|
+
var VDU = new Array(64);
|
|
601
|
+
var clt = new Array(256);
|
|
602
|
+
var RGB_YUV_TABLE = new Array(2048);
|
|
603
|
+
var currentQuality;
|
|
604
|
+
var ZigZag = [
|
|
605
|
+
0,
|
|
606
|
+
1,
|
|
607
|
+
5,
|
|
608
|
+
6,
|
|
609
|
+
14,
|
|
610
|
+
15,
|
|
611
|
+
27,
|
|
612
|
+
28,
|
|
613
|
+
2,
|
|
614
|
+
4,
|
|
615
|
+
7,
|
|
616
|
+
13,
|
|
617
|
+
16,
|
|
618
|
+
26,
|
|
619
|
+
29,
|
|
620
|
+
42,
|
|
621
|
+
3,
|
|
622
|
+
8,
|
|
623
|
+
12,
|
|
624
|
+
17,
|
|
625
|
+
25,
|
|
626
|
+
30,
|
|
627
|
+
41,
|
|
628
|
+
43,
|
|
629
|
+
9,
|
|
630
|
+
11,
|
|
631
|
+
18,
|
|
632
|
+
24,
|
|
633
|
+
31,
|
|
634
|
+
40,
|
|
635
|
+
44,
|
|
636
|
+
53,
|
|
637
|
+
10,
|
|
638
|
+
19,
|
|
639
|
+
23,
|
|
640
|
+
32,
|
|
641
|
+
39,
|
|
642
|
+
45,
|
|
643
|
+
52,
|
|
644
|
+
54,
|
|
645
|
+
20,
|
|
646
|
+
22,
|
|
647
|
+
33,
|
|
648
|
+
38,
|
|
649
|
+
46,
|
|
650
|
+
51,
|
|
651
|
+
55,
|
|
652
|
+
60,
|
|
653
|
+
21,
|
|
654
|
+
34,
|
|
655
|
+
37,
|
|
656
|
+
47,
|
|
657
|
+
50,
|
|
658
|
+
56,
|
|
659
|
+
59,
|
|
660
|
+
61,
|
|
661
|
+
35,
|
|
662
|
+
36,
|
|
663
|
+
48,
|
|
664
|
+
49,
|
|
665
|
+
57,
|
|
666
|
+
58,
|
|
667
|
+
62,
|
|
668
|
+
63
|
|
669
|
+
];
|
|
670
|
+
var std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0];
|
|
671
|
+
var std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
672
|
+
var std_ac_luminance_nrcodes = [0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 125];
|
|
673
|
+
var std_ac_luminance_values = [
|
|
674
|
+
1,
|
|
675
|
+
2,
|
|
676
|
+
3,
|
|
677
|
+
0,
|
|
678
|
+
4,
|
|
679
|
+
17,
|
|
680
|
+
5,
|
|
681
|
+
18,
|
|
682
|
+
33,
|
|
683
|
+
49,
|
|
684
|
+
65,
|
|
685
|
+
6,
|
|
686
|
+
19,
|
|
687
|
+
81,
|
|
688
|
+
97,
|
|
689
|
+
7,
|
|
690
|
+
34,
|
|
691
|
+
113,
|
|
692
|
+
20,
|
|
693
|
+
50,
|
|
694
|
+
129,
|
|
695
|
+
145,
|
|
696
|
+
161,
|
|
697
|
+
8,
|
|
698
|
+
35,
|
|
699
|
+
66,
|
|
700
|
+
177,
|
|
701
|
+
193,
|
|
702
|
+
21,
|
|
703
|
+
82,
|
|
704
|
+
209,
|
|
705
|
+
240,
|
|
706
|
+
36,
|
|
707
|
+
51,
|
|
708
|
+
98,
|
|
709
|
+
114,
|
|
710
|
+
130,
|
|
711
|
+
9,
|
|
712
|
+
10,
|
|
713
|
+
22,
|
|
714
|
+
23,
|
|
715
|
+
24,
|
|
716
|
+
25,
|
|
717
|
+
26,
|
|
718
|
+
37,
|
|
719
|
+
38,
|
|
720
|
+
39,
|
|
721
|
+
40,
|
|
722
|
+
41,
|
|
723
|
+
42,
|
|
724
|
+
52,
|
|
725
|
+
53,
|
|
726
|
+
54,
|
|
727
|
+
55,
|
|
728
|
+
56,
|
|
729
|
+
57,
|
|
730
|
+
58,
|
|
731
|
+
67,
|
|
732
|
+
68,
|
|
733
|
+
69,
|
|
734
|
+
70,
|
|
735
|
+
71,
|
|
736
|
+
72,
|
|
737
|
+
73,
|
|
738
|
+
74,
|
|
739
|
+
83,
|
|
740
|
+
84,
|
|
741
|
+
85,
|
|
742
|
+
86,
|
|
743
|
+
87,
|
|
744
|
+
88,
|
|
745
|
+
89,
|
|
746
|
+
90,
|
|
747
|
+
99,
|
|
748
|
+
100,
|
|
749
|
+
101,
|
|
750
|
+
102,
|
|
751
|
+
103,
|
|
752
|
+
104,
|
|
753
|
+
105,
|
|
754
|
+
106,
|
|
755
|
+
115,
|
|
756
|
+
116,
|
|
757
|
+
117,
|
|
758
|
+
118,
|
|
759
|
+
119,
|
|
760
|
+
120,
|
|
761
|
+
121,
|
|
762
|
+
122,
|
|
763
|
+
131,
|
|
764
|
+
132,
|
|
765
|
+
133,
|
|
766
|
+
134,
|
|
767
|
+
135,
|
|
768
|
+
136,
|
|
769
|
+
137,
|
|
770
|
+
138,
|
|
771
|
+
146,
|
|
772
|
+
147,
|
|
773
|
+
148,
|
|
774
|
+
149,
|
|
775
|
+
150,
|
|
776
|
+
151,
|
|
777
|
+
152,
|
|
778
|
+
153,
|
|
779
|
+
154,
|
|
780
|
+
162,
|
|
781
|
+
163,
|
|
782
|
+
164,
|
|
783
|
+
165,
|
|
784
|
+
166,
|
|
785
|
+
167,
|
|
786
|
+
168,
|
|
787
|
+
169,
|
|
788
|
+
170,
|
|
789
|
+
178,
|
|
790
|
+
179,
|
|
791
|
+
180,
|
|
792
|
+
181,
|
|
793
|
+
182,
|
|
794
|
+
183,
|
|
795
|
+
184,
|
|
796
|
+
185,
|
|
797
|
+
186,
|
|
798
|
+
194,
|
|
799
|
+
195,
|
|
800
|
+
196,
|
|
801
|
+
197,
|
|
802
|
+
198,
|
|
803
|
+
199,
|
|
804
|
+
200,
|
|
805
|
+
201,
|
|
806
|
+
202,
|
|
807
|
+
210,
|
|
808
|
+
211,
|
|
809
|
+
212,
|
|
810
|
+
213,
|
|
811
|
+
214,
|
|
812
|
+
215,
|
|
813
|
+
216,
|
|
814
|
+
217,
|
|
815
|
+
218,
|
|
816
|
+
225,
|
|
817
|
+
226,
|
|
818
|
+
227,
|
|
819
|
+
228,
|
|
820
|
+
229,
|
|
821
|
+
230,
|
|
822
|
+
231,
|
|
823
|
+
232,
|
|
824
|
+
233,
|
|
825
|
+
234,
|
|
826
|
+
241,
|
|
827
|
+
242,
|
|
828
|
+
243,
|
|
829
|
+
244,
|
|
830
|
+
245,
|
|
831
|
+
246,
|
|
832
|
+
247,
|
|
833
|
+
248,
|
|
834
|
+
249,
|
|
835
|
+
250
|
|
836
|
+
];
|
|
837
|
+
var std_dc_chrominance_nrcodes = [0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0];
|
|
838
|
+
var std_dc_chrominance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
839
|
+
var std_ac_chrominance_nrcodes = [0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 119];
|
|
840
|
+
var std_ac_chrominance_values = [
|
|
841
|
+
0,
|
|
842
|
+
1,
|
|
843
|
+
2,
|
|
844
|
+
3,
|
|
845
|
+
17,
|
|
846
|
+
4,
|
|
847
|
+
5,
|
|
848
|
+
33,
|
|
849
|
+
49,
|
|
850
|
+
6,
|
|
851
|
+
18,
|
|
852
|
+
65,
|
|
853
|
+
81,
|
|
854
|
+
7,
|
|
855
|
+
97,
|
|
856
|
+
113,
|
|
857
|
+
19,
|
|
858
|
+
34,
|
|
859
|
+
50,
|
|
860
|
+
129,
|
|
861
|
+
8,
|
|
862
|
+
20,
|
|
863
|
+
66,
|
|
864
|
+
145,
|
|
865
|
+
161,
|
|
866
|
+
177,
|
|
867
|
+
193,
|
|
868
|
+
9,
|
|
869
|
+
35,
|
|
870
|
+
51,
|
|
871
|
+
82,
|
|
872
|
+
240,
|
|
873
|
+
21,
|
|
874
|
+
98,
|
|
875
|
+
114,
|
|
876
|
+
209,
|
|
877
|
+
10,
|
|
878
|
+
22,
|
|
879
|
+
36,
|
|
880
|
+
52,
|
|
881
|
+
225,
|
|
882
|
+
37,
|
|
883
|
+
241,
|
|
884
|
+
23,
|
|
885
|
+
24,
|
|
886
|
+
25,
|
|
887
|
+
26,
|
|
888
|
+
38,
|
|
889
|
+
39,
|
|
890
|
+
40,
|
|
891
|
+
41,
|
|
892
|
+
42,
|
|
893
|
+
53,
|
|
894
|
+
54,
|
|
895
|
+
55,
|
|
896
|
+
56,
|
|
897
|
+
57,
|
|
898
|
+
58,
|
|
899
|
+
67,
|
|
900
|
+
68,
|
|
901
|
+
69,
|
|
902
|
+
70,
|
|
903
|
+
71,
|
|
904
|
+
72,
|
|
905
|
+
73,
|
|
906
|
+
74,
|
|
907
|
+
83,
|
|
908
|
+
84,
|
|
909
|
+
85,
|
|
910
|
+
86,
|
|
911
|
+
87,
|
|
912
|
+
88,
|
|
913
|
+
89,
|
|
914
|
+
90,
|
|
915
|
+
99,
|
|
916
|
+
100,
|
|
917
|
+
101,
|
|
918
|
+
102,
|
|
919
|
+
103,
|
|
920
|
+
104,
|
|
921
|
+
105,
|
|
922
|
+
106,
|
|
923
|
+
115,
|
|
924
|
+
116,
|
|
925
|
+
117,
|
|
926
|
+
118,
|
|
927
|
+
119,
|
|
928
|
+
120,
|
|
929
|
+
121,
|
|
930
|
+
122,
|
|
931
|
+
130,
|
|
932
|
+
131,
|
|
933
|
+
132,
|
|
934
|
+
133,
|
|
935
|
+
134,
|
|
936
|
+
135,
|
|
937
|
+
136,
|
|
938
|
+
137,
|
|
939
|
+
138,
|
|
940
|
+
146,
|
|
941
|
+
147,
|
|
942
|
+
148,
|
|
943
|
+
149,
|
|
944
|
+
150,
|
|
945
|
+
151,
|
|
946
|
+
152,
|
|
947
|
+
153,
|
|
948
|
+
154,
|
|
949
|
+
162,
|
|
950
|
+
163,
|
|
951
|
+
164,
|
|
952
|
+
165,
|
|
953
|
+
166,
|
|
954
|
+
167,
|
|
955
|
+
168,
|
|
956
|
+
169,
|
|
957
|
+
170,
|
|
958
|
+
178,
|
|
959
|
+
179,
|
|
960
|
+
180,
|
|
961
|
+
181,
|
|
962
|
+
182,
|
|
963
|
+
183,
|
|
964
|
+
184,
|
|
965
|
+
185,
|
|
966
|
+
186,
|
|
967
|
+
194,
|
|
968
|
+
195,
|
|
969
|
+
196,
|
|
970
|
+
197,
|
|
971
|
+
198,
|
|
972
|
+
199,
|
|
973
|
+
200,
|
|
974
|
+
201,
|
|
975
|
+
202,
|
|
976
|
+
210,
|
|
977
|
+
211,
|
|
978
|
+
212,
|
|
979
|
+
213,
|
|
980
|
+
214,
|
|
981
|
+
215,
|
|
982
|
+
216,
|
|
983
|
+
217,
|
|
984
|
+
218,
|
|
985
|
+
226,
|
|
986
|
+
227,
|
|
987
|
+
228,
|
|
988
|
+
229,
|
|
989
|
+
230,
|
|
990
|
+
231,
|
|
991
|
+
232,
|
|
992
|
+
233,
|
|
993
|
+
234,
|
|
994
|
+
242,
|
|
995
|
+
243,
|
|
996
|
+
244,
|
|
997
|
+
245,
|
|
998
|
+
246,
|
|
999
|
+
247,
|
|
1000
|
+
248,
|
|
1001
|
+
249,
|
|
1002
|
+
250
|
|
1003
|
+
];
|
|
1004
|
+
function initQuantTables(sf) {
|
|
1005
|
+
var YQT = [
|
|
1006
|
+
16,
|
|
1007
|
+
11,
|
|
1008
|
+
10,
|
|
1009
|
+
16,
|
|
1010
|
+
24,
|
|
1011
|
+
40,
|
|
1012
|
+
51,
|
|
1013
|
+
61,
|
|
1014
|
+
12,
|
|
1015
|
+
12,
|
|
1016
|
+
14,
|
|
1017
|
+
19,
|
|
1018
|
+
26,
|
|
1019
|
+
58,
|
|
1020
|
+
60,
|
|
1021
|
+
55,
|
|
1022
|
+
14,
|
|
1023
|
+
13,
|
|
1024
|
+
16,
|
|
1025
|
+
24,
|
|
1026
|
+
40,
|
|
1027
|
+
57,
|
|
1028
|
+
69,
|
|
1029
|
+
56,
|
|
1030
|
+
14,
|
|
1031
|
+
17,
|
|
1032
|
+
22,
|
|
1033
|
+
29,
|
|
1034
|
+
51,
|
|
1035
|
+
87,
|
|
1036
|
+
80,
|
|
1037
|
+
62,
|
|
1038
|
+
18,
|
|
1039
|
+
22,
|
|
1040
|
+
37,
|
|
1041
|
+
56,
|
|
1042
|
+
68,
|
|
1043
|
+
109,
|
|
1044
|
+
103,
|
|
1045
|
+
77,
|
|
1046
|
+
24,
|
|
1047
|
+
35,
|
|
1048
|
+
55,
|
|
1049
|
+
64,
|
|
1050
|
+
81,
|
|
1051
|
+
104,
|
|
1052
|
+
113,
|
|
1053
|
+
92,
|
|
1054
|
+
49,
|
|
1055
|
+
64,
|
|
1056
|
+
78,
|
|
1057
|
+
87,
|
|
1058
|
+
103,
|
|
1059
|
+
121,
|
|
1060
|
+
120,
|
|
1061
|
+
101,
|
|
1062
|
+
72,
|
|
1063
|
+
92,
|
|
1064
|
+
95,
|
|
1065
|
+
98,
|
|
1066
|
+
112,
|
|
1067
|
+
100,
|
|
1068
|
+
103,
|
|
1069
|
+
99
|
|
1070
|
+
];
|
|
1071
|
+
for (var i = 0; i < 64; i++) {
|
|
1072
|
+
var t = ffloor((YQT[i] * sf + 50) / 100);
|
|
1073
|
+
if (t < 1) {
|
|
1074
|
+
t = 1;
|
|
1075
|
+
} else if (t > 255) {
|
|
1076
|
+
t = 255;
|
|
1077
|
+
}
|
|
1078
|
+
YTable[ZigZag[i]] = t;
|
|
1079
|
+
}
|
|
1080
|
+
var UVQT = [
|
|
1081
|
+
17,
|
|
1082
|
+
18,
|
|
1083
|
+
24,
|
|
1084
|
+
47,
|
|
1085
|
+
99,
|
|
1086
|
+
99,
|
|
1087
|
+
99,
|
|
1088
|
+
99,
|
|
1089
|
+
18,
|
|
1090
|
+
21,
|
|
1091
|
+
26,
|
|
1092
|
+
66,
|
|
1093
|
+
99,
|
|
1094
|
+
99,
|
|
1095
|
+
99,
|
|
1096
|
+
99,
|
|
1097
|
+
24,
|
|
1098
|
+
26,
|
|
1099
|
+
56,
|
|
1100
|
+
99,
|
|
1101
|
+
99,
|
|
1102
|
+
99,
|
|
1103
|
+
99,
|
|
1104
|
+
99,
|
|
1105
|
+
47,
|
|
1106
|
+
66,
|
|
1107
|
+
99,
|
|
1108
|
+
99,
|
|
1109
|
+
99,
|
|
1110
|
+
99,
|
|
1111
|
+
99,
|
|
1112
|
+
99,
|
|
1113
|
+
99,
|
|
1114
|
+
99,
|
|
1115
|
+
99,
|
|
1116
|
+
99,
|
|
1117
|
+
99,
|
|
1118
|
+
99,
|
|
1119
|
+
99,
|
|
1120
|
+
99,
|
|
1121
|
+
99,
|
|
1122
|
+
99,
|
|
1123
|
+
99,
|
|
1124
|
+
99,
|
|
1125
|
+
99,
|
|
1126
|
+
99,
|
|
1127
|
+
99,
|
|
1128
|
+
99,
|
|
1129
|
+
99,
|
|
1130
|
+
99,
|
|
1131
|
+
99,
|
|
1132
|
+
99,
|
|
1133
|
+
99,
|
|
1134
|
+
99,
|
|
1135
|
+
99,
|
|
1136
|
+
99,
|
|
1137
|
+
99,
|
|
1138
|
+
99,
|
|
1139
|
+
99,
|
|
1140
|
+
99,
|
|
1141
|
+
99,
|
|
1142
|
+
99,
|
|
1143
|
+
99,
|
|
1144
|
+
99
|
|
1145
|
+
];
|
|
1146
|
+
for (var j = 0; j < 64; j++) {
|
|
1147
|
+
var u = ffloor((UVQT[j] * sf + 50) / 100);
|
|
1148
|
+
if (u < 1) {
|
|
1149
|
+
u = 1;
|
|
1150
|
+
} else if (u > 255) {
|
|
1151
|
+
u = 255;
|
|
1152
|
+
}
|
|
1153
|
+
UVTable[ZigZag[j]] = u;
|
|
1154
|
+
}
|
|
1155
|
+
var aasf = [
|
|
1156
|
+
1,
|
|
1157
|
+
1.387039845,
|
|
1158
|
+
1.306562965,
|
|
1159
|
+
1.175875602,
|
|
1160
|
+
1,
|
|
1161
|
+
0.785694958,
|
|
1162
|
+
0.5411961,
|
|
1163
|
+
0.275899379
|
|
1164
|
+
];
|
|
1165
|
+
var k = 0;
|
|
1166
|
+
for (var row = 0; row < 8; row++) {
|
|
1167
|
+
for (var col = 0; col < 8; col++) {
|
|
1168
|
+
fdtbl_Y[k] = 1 / (YTable[ZigZag[k]] * aasf[row] * aasf[col] * 8);
|
|
1169
|
+
fdtbl_UV[k] = 1 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8);
|
|
1170
|
+
k++;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
function computeHuffmanTbl(nrcodes, std_table) {
|
|
1175
|
+
var codevalue = 0;
|
|
1176
|
+
var pos_in_table = 0;
|
|
1177
|
+
var HT = new Array();
|
|
1178
|
+
for (var k = 1; k <= 16; k++) {
|
|
1179
|
+
for (var j = 1; j <= nrcodes[k]; j++) {
|
|
1180
|
+
HT[std_table[pos_in_table]] = [];
|
|
1181
|
+
HT[std_table[pos_in_table]][0] = codevalue;
|
|
1182
|
+
HT[std_table[pos_in_table]][1] = k;
|
|
1183
|
+
pos_in_table++;
|
|
1184
|
+
codevalue++;
|
|
1185
|
+
}
|
|
1186
|
+
codevalue *= 2;
|
|
1187
|
+
}
|
|
1188
|
+
return HT;
|
|
1189
|
+
}
|
|
1190
|
+
function initHuffmanTbl() {
|
|
1191
|
+
YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_values);
|
|
1192
|
+
UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes, std_dc_chrominance_values);
|
|
1193
|
+
YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values);
|
|
1194
|
+
UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values);
|
|
1195
|
+
}
|
|
1196
|
+
function initCategoryNumber() {
|
|
1197
|
+
var nrlower = 1;
|
|
1198
|
+
var nrupper = 2;
|
|
1199
|
+
for (var cat = 1; cat <= 15; cat++) {
|
|
1200
|
+
for (var nr = nrlower; nr < nrupper; nr++) {
|
|
1201
|
+
category[32767 + nr] = cat;
|
|
1202
|
+
bitcode[32767 + nr] = [];
|
|
1203
|
+
bitcode[32767 + nr][1] = cat;
|
|
1204
|
+
bitcode[32767 + nr][0] = nr;
|
|
1205
|
+
}
|
|
1206
|
+
for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) {
|
|
1207
|
+
category[32767 + nrneg] = cat;
|
|
1208
|
+
bitcode[32767 + nrneg] = [];
|
|
1209
|
+
bitcode[32767 + nrneg][1] = cat;
|
|
1210
|
+
bitcode[32767 + nrneg][0] = nrupper - 1 + nrneg;
|
|
1211
|
+
}
|
|
1212
|
+
nrlower <<= 1;
|
|
1213
|
+
nrupper <<= 1;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
function initRGBYUVTable() {
|
|
1217
|
+
for (var i = 0; i < 256; i++) {
|
|
1218
|
+
RGB_YUV_TABLE[i] = 19595 * i;
|
|
1219
|
+
RGB_YUV_TABLE[i + 256 >> 0] = 38470 * i;
|
|
1220
|
+
RGB_YUV_TABLE[i + 512 >> 0] = 7471 * i + 32768;
|
|
1221
|
+
RGB_YUV_TABLE[i + 768 >> 0] = -11059 * i;
|
|
1222
|
+
RGB_YUV_TABLE[i + 1024 >> 0] = -21709 * i;
|
|
1223
|
+
RGB_YUV_TABLE[i + 1280 >> 0] = 32768 * i + 8421375;
|
|
1224
|
+
RGB_YUV_TABLE[i + 1536 >> 0] = -27439 * i;
|
|
1225
|
+
RGB_YUV_TABLE[i + 1792 >> 0] = -5329 * i;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
function writeBits(bs) {
|
|
1229
|
+
var value = bs[0];
|
|
1230
|
+
var posval = bs[1] - 1;
|
|
1231
|
+
while (posval >= 0) {
|
|
1232
|
+
if (value & 1 << posval) {
|
|
1233
|
+
bytenew |= 1 << bytepos;
|
|
1234
|
+
}
|
|
1235
|
+
posval--;
|
|
1236
|
+
bytepos--;
|
|
1237
|
+
if (bytepos < 0) {
|
|
1238
|
+
if (bytenew == 255) {
|
|
1239
|
+
writeByte(255);
|
|
1240
|
+
writeByte(0);
|
|
1241
|
+
} else {
|
|
1242
|
+
writeByte(bytenew);
|
|
1243
|
+
}
|
|
1244
|
+
bytepos = 7;
|
|
1245
|
+
bytenew = 0;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
function writeByte(value) {
|
|
1250
|
+
byteout.push(value);
|
|
1251
|
+
}
|
|
1252
|
+
function writeWord(value) {
|
|
1253
|
+
writeByte(value >> 8 & 255);
|
|
1254
|
+
writeByte(value & 255);
|
|
1255
|
+
}
|
|
1256
|
+
function fDCTQuant(data, fdtbl) {
|
|
1257
|
+
var d0, d1, d2, d3, d4, d5, d6, d7;
|
|
1258
|
+
var dataOff = 0;
|
|
1259
|
+
var i;
|
|
1260
|
+
var I8 = 8;
|
|
1261
|
+
var I64 = 64;
|
|
1262
|
+
for (i = 0; i < I8; ++i) {
|
|
1263
|
+
d0 = data[dataOff];
|
|
1264
|
+
d1 = data[dataOff + 1];
|
|
1265
|
+
d2 = data[dataOff + 2];
|
|
1266
|
+
d3 = data[dataOff + 3];
|
|
1267
|
+
d4 = data[dataOff + 4];
|
|
1268
|
+
d5 = data[dataOff + 5];
|
|
1269
|
+
d6 = data[dataOff + 6];
|
|
1270
|
+
d7 = data[dataOff + 7];
|
|
1271
|
+
var tmp0 = d0 + d7;
|
|
1272
|
+
var tmp7 = d0 - d7;
|
|
1273
|
+
var tmp1 = d1 + d6;
|
|
1274
|
+
var tmp6 = d1 - d6;
|
|
1275
|
+
var tmp2 = d2 + d5;
|
|
1276
|
+
var tmp5 = d2 - d5;
|
|
1277
|
+
var tmp3 = d3 + d4;
|
|
1278
|
+
var tmp4 = d3 - d4;
|
|
1279
|
+
var tmp10 = tmp0 + tmp3;
|
|
1280
|
+
var tmp13 = tmp0 - tmp3;
|
|
1281
|
+
var tmp11 = tmp1 + tmp2;
|
|
1282
|
+
var tmp12 = tmp1 - tmp2;
|
|
1283
|
+
data[dataOff] = tmp10 + tmp11;
|
|
1284
|
+
data[dataOff + 4] = tmp10 - tmp11;
|
|
1285
|
+
var z1 = (tmp12 + tmp13) * 0.707106781;
|
|
1286
|
+
data[dataOff + 2] = tmp13 + z1;
|
|
1287
|
+
data[dataOff + 6] = tmp13 - z1;
|
|
1288
|
+
tmp10 = tmp4 + tmp5;
|
|
1289
|
+
tmp11 = tmp5 + tmp6;
|
|
1290
|
+
tmp12 = tmp6 + tmp7;
|
|
1291
|
+
var z5 = (tmp10 - tmp12) * 0.382683433;
|
|
1292
|
+
var z2 = 0.5411961 * tmp10 + z5;
|
|
1293
|
+
var z4 = 1.306562965 * tmp12 + z5;
|
|
1294
|
+
var z3 = tmp11 * 0.707106781;
|
|
1295
|
+
var z11 = tmp7 + z3;
|
|
1296
|
+
var z13 = tmp7 - z3;
|
|
1297
|
+
data[dataOff + 5] = z13 + z2;
|
|
1298
|
+
data[dataOff + 3] = z13 - z2;
|
|
1299
|
+
data[dataOff + 1] = z11 + z4;
|
|
1300
|
+
data[dataOff + 7] = z11 - z4;
|
|
1301
|
+
dataOff += 8;
|
|
1302
|
+
}
|
|
1303
|
+
dataOff = 0;
|
|
1304
|
+
for (i = 0; i < I8; ++i) {
|
|
1305
|
+
d0 = data[dataOff];
|
|
1306
|
+
d1 = data[dataOff + 8];
|
|
1307
|
+
d2 = data[dataOff + 16];
|
|
1308
|
+
d3 = data[dataOff + 24];
|
|
1309
|
+
d4 = data[dataOff + 32];
|
|
1310
|
+
d5 = data[dataOff + 40];
|
|
1311
|
+
d6 = data[dataOff + 48];
|
|
1312
|
+
d7 = data[dataOff + 56];
|
|
1313
|
+
var tmp0p2 = d0 + d7;
|
|
1314
|
+
var tmp7p2 = d0 - d7;
|
|
1315
|
+
var tmp1p2 = d1 + d6;
|
|
1316
|
+
var tmp6p2 = d1 - d6;
|
|
1317
|
+
var tmp2p2 = d2 + d5;
|
|
1318
|
+
var tmp5p2 = d2 - d5;
|
|
1319
|
+
var tmp3p2 = d3 + d4;
|
|
1320
|
+
var tmp4p2 = d3 - d4;
|
|
1321
|
+
var tmp10p2 = tmp0p2 + tmp3p2;
|
|
1322
|
+
var tmp13p2 = tmp0p2 - tmp3p2;
|
|
1323
|
+
var tmp11p2 = tmp1p2 + tmp2p2;
|
|
1324
|
+
var tmp12p2 = tmp1p2 - tmp2p2;
|
|
1325
|
+
data[dataOff] = tmp10p2 + tmp11p2;
|
|
1326
|
+
data[dataOff + 32] = tmp10p2 - tmp11p2;
|
|
1327
|
+
var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781;
|
|
1328
|
+
data[dataOff + 16] = tmp13p2 + z1p2;
|
|
1329
|
+
data[dataOff + 48] = tmp13p2 - z1p2;
|
|
1330
|
+
tmp10p2 = tmp4p2 + tmp5p2;
|
|
1331
|
+
tmp11p2 = tmp5p2 + tmp6p2;
|
|
1332
|
+
tmp12p2 = tmp6p2 + tmp7p2;
|
|
1333
|
+
var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433;
|
|
1334
|
+
var z2p2 = 0.5411961 * tmp10p2 + z5p2;
|
|
1335
|
+
var z4p2 = 1.306562965 * tmp12p2 + z5p2;
|
|
1336
|
+
var z3p2 = tmp11p2 * 0.707106781;
|
|
1337
|
+
var z11p2 = tmp7p2 + z3p2;
|
|
1338
|
+
var z13p2 = tmp7p2 - z3p2;
|
|
1339
|
+
data[dataOff + 40] = z13p2 + z2p2;
|
|
1340
|
+
data[dataOff + 24] = z13p2 - z2p2;
|
|
1341
|
+
data[dataOff + 8] = z11p2 + z4p2;
|
|
1342
|
+
data[dataOff + 56] = z11p2 - z4p2;
|
|
1343
|
+
dataOff++;
|
|
1344
|
+
}
|
|
1345
|
+
var fDCTQuant2;
|
|
1346
|
+
for (i = 0; i < I64; ++i) {
|
|
1347
|
+
fDCTQuant2 = data[i] * fdtbl[i];
|
|
1348
|
+
outputfDCTQuant[i] = fDCTQuant2 > 0 ? fDCTQuant2 + 0.5 | 0 : fDCTQuant2 - 0.5 | 0;
|
|
1349
|
+
}
|
|
1350
|
+
return outputfDCTQuant;
|
|
1351
|
+
}
|
|
1352
|
+
function writeAPP0() {
|
|
1353
|
+
writeWord(65504);
|
|
1354
|
+
writeWord(16);
|
|
1355
|
+
writeByte(74);
|
|
1356
|
+
writeByte(70);
|
|
1357
|
+
writeByte(73);
|
|
1358
|
+
writeByte(70);
|
|
1359
|
+
writeByte(0);
|
|
1360
|
+
writeByte(1);
|
|
1361
|
+
writeByte(1);
|
|
1362
|
+
writeByte(0);
|
|
1363
|
+
writeWord(1);
|
|
1364
|
+
writeWord(1);
|
|
1365
|
+
writeByte(0);
|
|
1366
|
+
writeByte(0);
|
|
1367
|
+
}
|
|
1368
|
+
function writeAPP1(exifBuffer) {
|
|
1369
|
+
if (!exifBuffer) return;
|
|
1370
|
+
writeWord(65505);
|
|
1371
|
+
if (exifBuffer[0] === 69 && exifBuffer[1] === 120 && exifBuffer[2] === 105 && exifBuffer[3] === 102) {
|
|
1372
|
+
writeWord(exifBuffer.length + 2);
|
|
1373
|
+
} else {
|
|
1374
|
+
writeWord(exifBuffer.length + 5 + 2);
|
|
1375
|
+
writeByte(69);
|
|
1376
|
+
writeByte(120);
|
|
1377
|
+
writeByte(105);
|
|
1378
|
+
writeByte(102);
|
|
1379
|
+
writeByte(0);
|
|
1380
|
+
}
|
|
1381
|
+
for (var i = 0; i < exifBuffer.length; i++) {
|
|
1382
|
+
writeByte(exifBuffer[i]);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
function writeSOF0(width, height) {
|
|
1386
|
+
writeWord(65472);
|
|
1387
|
+
writeWord(17);
|
|
1388
|
+
writeByte(8);
|
|
1389
|
+
writeWord(height);
|
|
1390
|
+
writeWord(width);
|
|
1391
|
+
writeByte(3);
|
|
1392
|
+
writeByte(1);
|
|
1393
|
+
writeByte(17);
|
|
1394
|
+
writeByte(0);
|
|
1395
|
+
writeByte(2);
|
|
1396
|
+
writeByte(17);
|
|
1397
|
+
writeByte(1);
|
|
1398
|
+
writeByte(3);
|
|
1399
|
+
writeByte(17);
|
|
1400
|
+
writeByte(1);
|
|
1401
|
+
}
|
|
1402
|
+
function writeDQT() {
|
|
1403
|
+
writeWord(65499);
|
|
1404
|
+
writeWord(132);
|
|
1405
|
+
writeByte(0);
|
|
1406
|
+
for (var i = 0; i < 64; i++) {
|
|
1407
|
+
writeByte(YTable[i]);
|
|
1408
|
+
}
|
|
1409
|
+
writeByte(1);
|
|
1410
|
+
for (var j = 0; j < 64; j++) {
|
|
1411
|
+
writeByte(UVTable[j]);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
function writeDHT() {
|
|
1415
|
+
writeWord(65476);
|
|
1416
|
+
writeWord(418);
|
|
1417
|
+
writeByte(0);
|
|
1418
|
+
for (var i = 0; i < 16; i++) {
|
|
1419
|
+
writeByte(std_dc_luminance_nrcodes[i + 1]);
|
|
1420
|
+
}
|
|
1421
|
+
for (var j = 0; j <= 11; j++) {
|
|
1422
|
+
writeByte(std_dc_luminance_values[j]);
|
|
1423
|
+
}
|
|
1424
|
+
writeByte(16);
|
|
1425
|
+
for (var k = 0; k < 16; k++) {
|
|
1426
|
+
writeByte(std_ac_luminance_nrcodes[k + 1]);
|
|
1427
|
+
}
|
|
1428
|
+
for (var l = 0; l <= 161; l++) {
|
|
1429
|
+
writeByte(std_ac_luminance_values[l]);
|
|
1430
|
+
}
|
|
1431
|
+
writeByte(1);
|
|
1432
|
+
for (var m = 0; m < 16; m++) {
|
|
1433
|
+
writeByte(std_dc_chrominance_nrcodes[m + 1]);
|
|
1434
|
+
}
|
|
1435
|
+
for (var n = 0; n <= 11; n++) {
|
|
1436
|
+
writeByte(std_dc_chrominance_values[n]);
|
|
1437
|
+
}
|
|
1438
|
+
writeByte(17);
|
|
1439
|
+
for (var o = 0; o < 16; o++) {
|
|
1440
|
+
writeByte(std_ac_chrominance_nrcodes[o + 1]);
|
|
1441
|
+
}
|
|
1442
|
+
for (var p = 0; p <= 161; p++) {
|
|
1443
|
+
writeByte(std_ac_chrominance_values[p]);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
function writeCOM(comments) {
|
|
1447
|
+
if (typeof comments === "undefined" || comments.constructor !== Array) return;
|
|
1448
|
+
comments.forEach((e) => {
|
|
1449
|
+
if (typeof e !== "string") return;
|
|
1450
|
+
writeWord(65534);
|
|
1451
|
+
var l = e.length;
|
|
1452
|
+
writeWord(l + 2);
|
|
1453
|
+
var i;
|
|
1454
|
+
for (i = 0; i < l; i++)
|
|
1455
|
+
writeByte(e.charCodeAt(i));
|
|
1456
|
+
});
|
|
1457
|
+
}
|
|
1458
|
+
function writeSOS() {
|
|
1459
|
+
writeWord(65498);
|
|
1460
|
+
writeWord(12);
|
|
1461
|
+
writeByte(3);
|
|
1462
|
+
writeByte(1);
|
|
1463
|
+
writeByte(0);
|
|
1464
|
+
writeByte(2);
|
|
1465
|
+
writeByte(17);
|
|
1466
|
+
writeByte(3);
|
|
1467
|
+
writeByte(17);
|
|
1468
|
+
writeByte(0);
|
|
1469
|
+
writeByte(63);
|
|
1470
|
+
writeByte(0);
|
|
1471
|
+
}
|
|
1472
|
+
function processDU(CDU, fdtbl, DC, HTDC, HTAC) {
|
|
1473
|
+
var EOB = HTAC[0];
|
|
1474
|
+
var M16zeroes = HTAC[240];
|
|
1475
|
+
var pos;
|
|
1476
|
+
var I16 = 16;
|
|
1477
|
+
var I63 = 63;
|
|
1478
|
+
var I64 = 64;
|
|
1479
|
+
var DU_DCT = fDCTQuant(CDU, fdtbl);
|
|
1480
|
+
for (var j = 0; j < I64; ++j) {
|
|
1481
|
+
DU[ZigZag[j]] = DU_DCT[j];
|
|
1482
|
+
}
|
|
1483
|
+
var Diff = DU[0] - DC;
|
|
1484
|
+
DC = DU[0];
|
|
1485
|
+
if (Diff == 0) {
|
|
1486
|
+
writeBits(HTDC[0]);
|
|
1487
|
+
} else {
|
|
1488
|
+
pos = 32767 + Diff;
|
|
1489
|
+
writeBits(HTDC[category[pos]]);
|
|
1490
|
+
writeBits(bitcode[pos]);
|
|
1491
|
+
}
|
|
1492
|
+
var end0pos = 63;
|
|
1493
|
+
for (; end0pos > 0 && DU[end0pos] == 0; end0pos--) {
|
|
1494
|
+
}
|
|
1495
|
+
;
|
|
1496
|
+
if (end0pos == 0) {
|
|
1497
|
+
writeBits(EOB);
|
|
1498
|
+
return DC;
|
|
1499
|
+
}
|
|
1500
|
+
var i = 1;
|
|
1501
|
+
var lng;
|
|
1502
|
+
while (i <= end0pos) {
|
|
1503
|
+
var startpos = i;
|
|
1504
|
+
for (; DU[i] == 0 && i <= end0pos; ++i) {
|
|
1505
|
+
}
|
|
1506
|
+
var nrzeroes = i - startpos;
|
|
1507
|
+
if (nrzeroes >= I16) {
|
|
1508
|
+
lng = nrzeroes >> 4;
|
|
1509
|
+
for (var nrmarker = 1; nrmarker <= lng; ++nrmarker)
|
|
1510
|
+
writeBits(M16zeroes);
|
|
1511
|
+
nrzeroes = nrzeroes & 15;
|
|
1512
|
+
}
|
|
1513
|
+
pos = 32767 + DU[i];
|
|
1514
|
+
writeBits(HTAC[(nrzeroes << 4) + category[pos]]);
|
|
1515
|
+
writeBits(bitcode[pos]);
|
|
1516
|
+
i++;
|
|
1517
|
+
}
|
|
1518
|
+
if (end0pos != I63) {
|
|
1519
|
+
writeBits(EOB);
|
|
1520
|
+
}
|
|
1521
|
+
return DC;
|
|
1522
|
+
}
|
|
1523
|
+
function initCharLookupTable() {
|
|
1524
|
+
var sfcc = String.fromCharCode;
|
|
1525
|
+
for (var i = 0; i < 256; i++) {
|
|
1526
|
+
clt[i] = sfcc(i);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
this.encode = function(image, quality2) {
|
|
1530
|
+
var time_start = (/* @__PURE__ */ new Date()).getTime();
|
|
1531
|
+
if (quality2) setQuality(quality2);
|
|
1532
|
+
byteout = new Array();
|
|
1533
|
+
bytenew = 0;
|
|
1534
|
+
bytepos = 7;
|
|
1535
|
+
writeWord(65496);
|
|
1536
|
+
writeAPP0();
|
|
1537
|
+
writeCOM(image.comments);
|
|
1538
|
+
writeAPP1(image.exifBuffer);
|
|
1539
|
+
writeDQT();
|
|
1540
|
+
writeSOF0(image.width, image.height);
|
|
1541
|
+
writeDHT();
|
|
1542
|
+
writeSOS();
|
|
1543
|
+
var DCY = 0;
|
|
1544
|
+
var DCU = 0;
|
|
1545
|
+
var DCV = 0;
|
|
1546
|
+
bytenew = 0;
|
|
1547
|
+
bytepos = 7;
|
|
1548
|
+
this.encode.displayName = "_encode_";
|
|
1549
|
+
var imageData = image.data;
|
|
1550
|
+
var width = image.width;
|
|
1551
|
+
var height = image.height;
|
|
1552
|
+
var quadWidth = width * 4;
|
|
1553
|
+
var tripleWidth = width * 3;
|
|
1554
|
+
var x, y = 0;
|
|
1555
|
+
var r, g, b;
|
|
1556
|
+
var start, p, col, row, pos;
|
|
1557
|
+
while (y < height) {
|
|
1558
|
+
x = 0;
|
|
1559
|
+
while (x < quadWidth) {
|
|
1560
|
+
start = quadWidth * y + x;
|
|
1561
|
+
p = start;
|
|
1562
|
+
col = -1;
|
|
1563
|
+
row = 0;
|
|
1564
|
+
for (pos = 0; pos < 64; pos++) {
|
|
1565
|
+
row = pos >> 3;
|
|
1566
|
+
col = (pos & 7) * 4;
|
|
1567
|
+
p = start + row * quadWidth + col;
|
|
1568
|
+
if (y + row >= height) {
|
|
1569
|
+
p -= quadWidth * (y + 1 + row - height);
|
|
1570
|
+
}
|
|
1571
|
+
if (x + col >= quadWidth) {
|
|
1572
|
+
p -= x + col - quadWidth + 4;
|
|
1573
|
+
}
|
|
1574
|
+
r = imageData[p++];
|
|
1575
|
+
g = imageData[p++];
|
|
1576
|
+
b = imageData[p++];
|
|
1577
|
+
YDU[pos] = (RGB_YUV_TABLE[r] + RGB_YUV_TABLE[g + 256 >> 0] + RGB_YUV_TABLE[b + 512 >> 0] >> 16) - 128;
|
|
1578
|
+
UDU[pos] = (RGB_YUV_TABLE[r + 768 >> 0] + RGB_YUV_TABLE[g + 1024 >> 0] + RGB_YUV_TABLE[b + 1280 >> 0] >> 16) - 128;
|
|
1579
|
+
VDU[pos] = (RGB_YUV_TABLE[r + 1280 >> 0] + RGB_YUV_TABLE[g + 1536 >> 0] + RGB_YUV_TABLE[b + 1792 >> 0] >> 16) - 128;
|
|
1580
|
+
}
|
|
1581
|
+
DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
|
|
1582
|
+
DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
|
|
1583
|
+
DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
|
|
1584
|
+
x += 32;
|
|
1585
|
+
}
|
|
1586
|
+
y += 8;
|
|
1587
|
+
}
|
|
1588
|
+
if (bytepos >= 0) {
|
|
1589
|
+
var fillbits = [];
|
|
1590
|
+
fillbits[1] = bytepos + 1;
|
|
1591
|
+
fillbits[0] = (1 << bytepos + 1) - 1;
|
|
1592
|
+
writeBits(fillbits);
|
|
1593
|
+
}
|
|
1594
|
+
writeWord(65497);
|
|
1595
|
+
if (typeof module === "undefined") return new Uint8Array(byteout);
|
|
1596
|
+
return Buffer.from(byteout);
|
|
1597
|
+
var jpegDataUri = "data:image/jpeg;base64," + btoa(byteout.join(""));
|
|
1598
|
+
byteout = [];
|
|
1599
|
+
var duration = (/* @__PURE__ */ new Date()).getTime() - time_start;
|
|
1600
|
+
return jpegDataUri;
|
|
1601
|
+
};
|
|
1602
|
+
function setQuality(quality2) {
|
|
1603
|
+
if (quality2 <= 0) {
|
|
1604
|
+
quality2 = 1;
|
|
1605
|
+
}
|
|
1606
|
+
if (quality2 > 100) {
|
|
1607
|
+
quality2 = 100;
|
|
1608
|
+
}
|
|
1609
|
+
if (currentQuality == quality2) return;
|
|
1610
|
+
var sf = 0;
|
|
1611
|
+
if (quality2 < 50) {
|
|
1612
|
+
sf = Math.floor(5e3 / quality2);
|
|
1613
|
+
} else {
|
|
1614
|
+
sf = Math.floor(200 - quality2 * 2);
|
|
1615
|
+
}
|
|
1616
|
+
initQuantTables(sf);
|
|
1617
|
+
currentQuality = quality2;
|
|
1618
|
+
}
|
|
1619
|
+
function init() {
|
|
1620
|
+
var time_start = (/* @__PURE__ */ new Date()).getTime();
|
|
1621
|
+
if (!quality) quality = 50;
|
|
1622
|
+
initCharLookupTable();
|
|
1623
|
+
initHuffmanTbl();
|
|
1624
|
+
initCategoryNumber();
|
|
1625
|
+
initRGBYUVTable();
|
|
1626
|
+
setQuality(quality);
|
|
1627
|
+
var duration = (/* @__PURE__ */ new Date()).getTime() - time_start;
|
|
1628
|
+
}
|
|
1629
|
+
init();
|
|
1630
|
+
}
|
|
1631
|
+
if (typeof module !== "undefined") {
|
|
1632
|
+
module.exports = encode;
|
|
1633
|
+
} else if (typeof window !== "undefined") {
|
|
1634
|
+
window["jpeg-js"] = window["jpeg-js"] || {};
|
|
1635
|
+
window["jpeg-js"].encode = encode;
|
|
1636
|
+
}
|
|
1637
|
+
function encode(imgData, qu) {
|
|
1638
|
+
if (typeof qu === "undefined") qu = 50;
|
|
1639
|
+
var encoder = new JPEGEncoder(qu);
|
|
1640
|
+
var data = encoder.encode(imgData, qu);
|
|
1641
|
+
return {
|
|
1642
|
+
data,
|
|
1643
|
+
width: imgData.width,
|
|
1644
|
+
height: imgData.height
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
});
|
|
1649
|
+
|
|
1650
|
+
// node_modules/jpeg-js/lib/decoder.js
|
|
1651
|
+
var require_decoder = __commonJS({
|
|
1652
|
+
"node_modules/jpeg-js/lib/decoder.js"(exports, module) {
|
|
1653
|
+
init_define_import_meta_env();
|
|
1654
|
+
var JpegImage = (function jpegImage() {
|
|
1655
|
+
"use strict";
|
|
1656
|
+
var dctZigZag = new Int32Array([
|
|
1657
|
+
0,
|
|
1658
|
+
1,
|
|
1659
|
+
8,
|
|
1660
|
+
16,
|
|
1661
|
+
9,
|
|
1662
|
+
2,
|
|
1663
|
+
3,
|
|
1664
|
+
10,
|
|
1665
|
+
17,
|
|
1666
|
+
24,
|
|
1667
|
+
32,
|
|
1668
|
+
25,
|
|
1669
|
+
18,
|
|
1670
|
+
11,
|
|
1671
|
+
4,
|
|
1672
|
+
5,
|
|
1673
|
+
12,
|
|
1674
|
+
19,
|
|
1675
|
+
26,
|
|
1676
|
+
33,
|
|
1677
|
+
40,
|
|
1678
|
+
48,
|
|
1679
|
+
41,
|
|
1680
|
+
34,
|
|
1681
|
+
27,
|
|
1682
|
+
20,
|
|
1683
|
+
13,
|
|
1684
|
+
6,
|
|
1685
|
+
7,
|
|
1686
|
+
14,
|
|
1687
|
+
21,
|
|
1688
|
+
28,
|
|
1689
|
+
35,
|
|
1690
|
+
42,
|
|
1691
|
+
49,
|
|
1692
|
+
56,
|
|
1693
|
+
57,
|
|
1694
|
+
50,
|
|
1695
|
+
43,
|
|
1696
|
+
36,
|
|
1697
|
+
29,
|
|
1698
|
+
22,
|
|
1699
|
+
15,
|
|
1700
|
+
23,
|
|
1701
|
+
30,
|
|
1702
|
+
37,
|
|
1703
|
+
44,
|
|
1704
|
+
51,
|
|
1705
|
+
58,
|
|
1706
|
+
59,
|
|
1707
|
+
52,
|
|
1708
|
+
45,
|
|
1709
|
+
38,
|
|
1710
|
+
31,
|
|
1711
|
+
39,
|
|
1712
|
+
46,
|
|
1713
|
+
53,
|
|
1714
|
+
60,
|
|
1715
|
+
61,
|
|
1716
|
+
54,
|
|
1717
|
+
47,
|
|
1718
|
+
55,
|
|
1719
|
+
62,
|
|
1720
|
+
63
|
|
1721
|
+
]);
|
|
1722
|
+
var dctCos1 = 4017;
|
|
1723
|
+
var dctSin1 = 799;
|
|
1724
|
+
var dctCos3 = 3406;
|
|
1725
|
+
var dctSin3 = 2276;
|
|
1726
|
+
var dctCos6 = 1567;
|
|
1727
|
+
var dctSin6 = 3784;
|
|
1728
|
+
var dctSqrt2 = 5793;
|
|
1729
|
+
var dctSqrt1d2 = 2896;
|
|
1730
|
+
function constructor() {
|
|
1731
|
+
}
|
|
1732
|
+
function buildHuffmanTable(codeLengths, values) {
|
|
1733
|
+
var k = 0, code = [], i, j, length = 16;
|
|
1734
|
+
while (length > 0 && !codeLengths[length - 1])
|
|
1735
|
+
length--;
|
|
1736
|
+
code.push({ children: [], index: 0 });
|
|
1737
|
+
var p = code[0], q;
|
|
1738
|
+
for (i = 0; i < length; i++) {
|
|
1739
|
+
for (j = 0; j < codeLengths[i]; j++) {
|
|
1740
|
+
p = code.pop();
|
|
1741
|
+
p.children[p.index] = values[k];
|
|
1742
|
+
while (p.index > 0) {
|
|
1743
|
+
if (code.length === 0)
|
|
1744
|
+
throw new Error("Could not recreate Huffman Table");
|
|
1745
|
+
p = code.pop();
|
|
1746
|
+
}
|
|
1747
|
+
p.index++;
|
|
1748
|
+
code.push(p);
|
|
1749
|
+
while (code.length <= i) {
|
|
1750
|
+
code.push(q = { children: [], index: 0 });
|
|
1751
|
+
p.children[p.index] = q.children;
|
|
1752
|
+
p = q;
|
|
1753
|
+
}
|
|
1754
|
+
k++;
|
|
1755
|
+
}
|
|
1756
|
+
if (i + 1 < length) {
|
|
1757
|
+
code.push(q = { children: [], index: 0 });
|
|
1758
|
+
p.children[p.index] = q.children;
|
|
1759
|
+
p = q;
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
return code[0].children;
|
|
1763
|
+
}
|
|
1764
|
+
function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive, opts) {
|
|
1765
|
+
var precision = frame.precision;
|
|
1766
|
+
var samplesPerLine = frame.samplesPerLine;
|
|
1767
|
+
var scanLines = frame.scanLines;
|
|
1768
|
+
var mcusPerLine = frame.mcusPerLine;
|
|
1769
|
+
var progressive = frame.progressive;
|
|
1770
|
+
var maxH = frame.maxH, maxV = frame.maxV;
|
|
1771
|
+
var startOffset = offset, bitsData = 0, bitsCount = 0;
|
|
1772
|
+
function readBit() {
|
|
1773
|
+
if (bitsCount > 0) {
|
|
1774
|
+
bitsCount--;
|
|
1775
|
+
return bitsData >> bitsCount & 1;
|
|
1776
|
+
}
|
|
1777
|
+
bitsData = data[offset++];
|
|
1778
|
+
if (bitsData == 255) {
|
|
1779
|
+
var nextByte = data[offset++];
|
|
1780
|
+
if (nextByte) {
|
|
1781
|
+
throw new Error("unexpected marker: " + (bitsData << 8 | nextByte).toString(16));
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
bitsCount = 7;
|
|
1785
|
+
return bitsData >>> 7;
|
|
1786
|
+
}
|
|
1787
|
+
function decodeHuffman(tree) {
|
|
1788
|
+
var node = tree, bit;
|
|
1789
|
+
while ((bit = readBit()) !== null) {
|
|
1790
|
+
node = node[bit];
|
|
1791
|
+
if (typeof node === "number")
|
|
1792
|
+
return node;
|
|
1793
|
+
if (typeof node !== "object")
|
|
1794
|
+
throw new Error("invalid huffman sequence");
|
|
1795
|
+
}
|
|
1796
|
+
return null;
|
|
1797
|
+
}
|
|
1798
|
+
function receive(length) {
|
|
1799
|
+
var n2 = 0;
|
|
1800
|
+
while (length > 0) {
|
|
1801
|
+
var bit = readBit();
|
|
1802
|
+
if (bit === null) return;
|
|
1803
|
+
n2 = n2 << 1 | bit;
|
|
1804
|
+
length--;
|
|
1805
|
+
}
|
|
1806
|
+
return n2;
|
|
1807
|
+
}
|
|
1808
|
+
function receiveAndExtend(length) {
|
|
1809
|
+
var n2 = receive(length);
|
|
1810
|
+
if (n2 >= 1 << length - 1)
|
|
1811
|
+
return n2;
|
|
1812
|
+
return n2 + (-1 << length) + 1;
|
|
1813
|
+
}
|
|
1814
|
+
function decodeBaseline(component2, zz) {
|
|
1815
|
+
var t = decodeHuffman(component2.huffmanTableDC);
|
|
1816
|
+
var diff = t === 0 ? 0 : receiveAndExtend(t);
|
|
1817
|
+
zz[0] = component2.pred += diff;
|
|
1818
|
+
var k2 = 1;
|
|
1819
|
+
while (k2 < 64) {
|
|
1820
|
+
var rs = decodeHuffman(component2.huffmanTableAC);
|
|
1821
|
+
var s = rs & 15, r = rs >> 4;
|
|
1822
|
+
if (s === 0) {
|
|
1823
|
+
if (r < 15)
|
|
1824
|
+
break;
|
|
1825
|
+
k2 += 16;
|
|
1826
|
+
continue;
|
|
1827
|
+
}
|
|
1828
|
+
k2 += r;
|
|
1829
|
+
var z = dctZigZag[k2];
|
|
1830
|
+
zz[z] = receiveAndExtend(s);
|
|
1831
|
+
k2++;
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
function decodeDCFirst(component2, zz) {
|
|
1835
|
+
var t = decodeHuffman(component2.huffmanTableDC);
|
|
1836
|
+
var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
|
|
1837
|
+
zz[0] = component2.pred += diff;
|
|
1838
|
+
}
|
|
1839
|
+
function decodeDCSuccessive(component2, zz) {
|
|
1840
|
+
zz[0] |= readBit() << successive;
|
|
1841
|
+
}
|
|
1842
|
+
var eobrun = 0;
|
|
1843
|
+
function decodeACFirst(component2, zz) {
|
|
1844
|
+
if (eobrun > 0) {
|
|
1845
|
+
eobrun--;
|
|
1846
|
+
return;
|
|
1847
|
+
}
|
|
1848
|
+
var k2 = spectralStart, e = spectralEnd;
|
|
1849
|
+
while (k2 <= e) {
|
|
1850
|
+
var rs = decodeHuffman(component2.huffmanTableAC);
|
|
1851
|
+
var s = rs & 15, r = rs >> 4;
|
|
1852
|
+
if (s === 0) {
|
|
1853
|
+
if (r < 15) {
|
|
1854
|
+
eobrun = receive(r) + (1 << r) - 1;
|
|
1855
|
+
break;
|
|
1856
|
+
}
|
|
1857
|
+
k2 += 16;
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
k2 += r;
|
|
1861
|
+
var z = dctZigZag[k2];
|
|
1862
|
+
zz[z] = receiveAndExtend(s) * (1 << successive);
|
|
1863
|
+
k2++;
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
var successiveACState = 0, successiveACNextValue;
|
|
1867
|
+
function decodeACSuccessive(component2, zz) {
|
|
1868
|
+
var k2 = spectralStart, e = spectralEnd, r = 0;
|
|
1869
|
+
while (k2 <= e) {
|
|
1870
|
+
var z = dctZigZag[k2];
|
|
1871
|
+
var direction = zz[z] < 0 ? -1 : 1;
|
|
1872
|
+
switch (successiveACState) {
|
|
1873
|
+
case 0:
|
|
1874
|
+
var rs = decodeHuffman(component2.huffmanTableAC);
|
|
1875
|
+
var s = rs & 15, r = rs >> 4;
|
|
1876
|
+
if (s === 0) {
|
|
1877
|
+
if (r < 15) {
|
|
1878
|
+
eobrun = receive(r) + (1 << r);
|
|
1879
|
+
successiveACState = 4;
|
|
1880
|
+
} else {
|
|
1881
|
+
r = 16;
|
|
1882
|
+
successiveACState = 1;
|
|
1883
|
+
}
|
|
1884
|
+
} else {
|
|
1885
|
+
if (s !== 1)
|
|
1886
|
+
throw new Error("invalid ACn encoding");
|
|
1887
|
+
successiveACNextValue = receiveAndExtend(s);
|
|
1888
|
+
successiveACState = r ? 2 : 3;
|
|
1889
|
+
}
|
|
1890
|
+
continue;
|
|
1891
|
+
case 1:
|
|
1892
|
+
// skipping r zero items
|
|
1893
|
+
case 2:
|
|
1894
|
+
if (zz[z])
|
|
1895
|
+
zz[z] += (readBit() << successive) * direction;
|
|
1896
|
+
else {
|
|
1897
|
+
r--;
|
|
1898
|
+
if (r === 0)
|
|
1899
|
+
successiveACState = successiveACState == 2 ? 3 : 0;
|
|
1900
|
+
}
|
|
1901
|
+
break;
|
|
1902
|
+
case 3:
|
|
1903
|
+
if (zz[z])
|
|
1904
|
+
zz[z] += (readBit() << successive) * direction;
|
|
1905
|
+
else {
|
|
1906
|
+
zz[z] = successiveACNextValue << successive;
|
|
1907
|
+
successiveACState = 0;
|
|
1908
|
+
}
|
|
1909
|
+
break;
|
|
1910
|
+
case 4:
|
|
1911
|
+
if (zz[z])
|
|
1912
|
+
zz[z] += (readBit() << successive) * direction;
|
|
1913
|
+
break;
|
|
1914
|
+
}
|
|
1915
|
+
k2++;
|
|
1916
|
+
}
|
|
1917
|
+
if (successiveACState === 4) {
|
|
1918
|
+
eobrun--;
|
|
1919
|
+
if (eobrun === 0)
|
|
1920
|
+
successiveACState = 0;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
function decodeMcu(component2, decode2, mcu2, row, col) {
|
|
1924
|
+
var mcuRow = mcu2 / mcusPerLine | 0;
|
|
1925
|
+
var mcuCol = mcu2 % mcusPerLine;
|
|
1926
|
+
var blockRow = mcuRow * component2.v + row;
|
|
1927
|
+
var blockCol = mcuCol * component2.h + col;
|
|
1928
|
+
if (component2.blocks[blockRow] === void 0 && opts.tolerantDecoding)
|
|
1929
|
+
return;
|
|
1930
|
+
decode2(component2, component2.blocks[blockRow][blockCol]);
|
|
1931
|
+
}
|
|
1932
|
+
function decodeBlock(component2, decode2, mcu2) {
|
|
1933
|
+
var blockRow = mcu2 / component2.blocksPerLine | 0;
|
|
1934
|
+
var blockCol = mcu2 % component2.blocksPerLine;
|
|
1935
|
+
if (component2.blocks[blockRow] === void 0 && opts.tolerantDecoding)
|
|
1936
|
+
return;
|
|
1937
|
+
decode2(component2, component2.blocks[blockRow][blockCol]);
|
|
1938
|
+
}
|
|
1939
|
+
var componentsLength = components.length;
|
|
1940
|
+
var component, i, j, k, n;
|
|
1941
|
+
var decodeFn;
|
|
1942
|
+
if (progressive) {
|
|
1943
|
+
if (spectralStart === 0)
|
|
1944
|
+
decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
|
|
1945
|
+
else
|
|
1946
|
+
decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
|
|
1947
|
+
} else {
|
|
1948
|
+
decodeFn = decodeBaseline;
|
|
1949
|
+
}
|
|
1950
|
+
var mcu = 0, marker;
|
|
1951
|
+
var mcuExpected;
|
|
1952
|
+
if (componentsLength == 1) {
|
|
1953
|
+
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
|
1954
|
+
} else {
|
|
1955
|
+
mcuExpected = mcusPerLine * frame.mcusPerColumn;
|
|
1956
|
+
}
|
|
1957
|
+
if (!resetInterval) resetInterval = mcuExpected;
|
|
1958
|
+
var h, v;
|
|
1959
|
+
while (mcu < mcuExpected) {
|
|
1960
|
+
for (i = 0; i < componentsLength; i++)
|
|
1961
|
+
components[i].pred = 0;
|
|
1962
|
+
eobrun = 0;
|
|
1963
|
+
if (componentsLength == 1) {
|
|
1964
|
+
component = components[0];
|
|
1965
|
+
for (n = 0; n < resetInterval; n++) {
|
|
1966
|
+
decodeBlock(component, decodeFn, mcu);
|
|
1967
|
+
mcu++;
|
|
1968
|
+
}
|
|
1969
|
+
} else {
|
|
1970
|
+
for (n = 0; n < resetInterval; n++) {
|
|
1971
|
+
for (i = 0; i < componentsLength; i++) {
|
|
1972
|
+
component = components[i];
|
|
1973
|
+
h = component.h;
|
|
1974
|
+
v = component.v;
|
|
1975
|
+
for (j = 0; j < v; j++) {
|
|
1976
|
+
for (k = 0; k < h; k++) {
|
|
1977
|
+
decodeMcu(component, decodeFn, mcu, j, k);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
mcu++;
|
|
1982
|
+
if (mcu === mcuExpected) break;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
if (mcu === mcuExpected) {
|
|
1986
|
+
do {
|
|
1987
|
+
if (data[offset] === 255) {
|
|
1988
|
+
if (data[offset + 1] !== 0) {
|
|
1989
|
+
break;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
offset += 1;
|
|
1993
|
+
} while (offset < data.length - 2);
|
|
1994
|
+
}
|
|
1995
|
+
bitsCount = 0;
|
|
1996
|
+
marker = data[offset] << 8 | data[offset + 1];
|
|
1997
|
+
if (marker < 65280) {
|
|
1998
|
+
throw new Error("marker was not found");
|
|
1999
|
+
}
|
|
2000
|
+
if (marker >= 65488 && marker <= 65495) {
|
|
2001
|
+
offset += 2;
|
|
2002
|
+
} else
|
|
2003
|
+
break;
|
|
2004
|
+
}
|
|
2005
|
+
return offset - startOffset;
|
|
2006
|
+
}
|
|
2007
|
+
function buildComponentData(frame, component) {
|
|
2008
|
+
var lines = [];
|
|
2009
|
+
var blocksPerLine = component.blocksPerLine;
|
|
2010
|
+
var blocksPerColumn = component.blocksPerColumn;
|
|
2011
|
+
var samplesPerLine = blocksPerLine << 3;
|
|
2012
|
+
var R = new Int32Array(64), r = new Uint8Array(64);
|
|
2013
|
+
function quantizeAndInverse(zz, dataOut, dataIn) {
|
|
2014
|
+
var qt = component.quantizationTable;
|
|
2015
|
+
var v0, v1, v2, v3, v4, v5, v6, v7, t;
|
|
2016
|
+
var p = dataIn;
|
|
2017
|
+
var i2;
|
|
2018
|
+
for (i2 = 0; i2 < 64; i2++)
|
|
2019
|
+
p[i2] = zz[i2] * qt[i2];
|
|
2020
|
+
for (i2 = 0; i2 < 8; ++i2) {
|
|
2021
|
+
var row = 8 * i2;
|
|
2022
|
+
if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 && p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 && p[7 + row] == 0) {
|
|
2023
|
+
t = dctSqrt2 * p[0 + row] + 512 >> 10;
|
|
2024
|
+
p[0 + row] = t;
|
|
2025
|
+
p[1 + row] = t;
|
|
2026
|
+
p[2 + row] = t;
|
|
2027
|
+
p[3 + row] = t;
|
|
2028
|
+
p[4 + row] = t;
|
|
2029
|
+
p[5 + row] = t;
|
|
2030
|
+
p[6 + row] = t;
|
|
2031
|
+
p[7 + row] = t;
|
|
2032
|
+
continue;
|
|
2033
|
+
}
|
|
2034
|
+
v0 = dctSqrt2 * p[0 + row] + 128 >> 8;
|
|
2035
|
+
v1 = dctSqrt2 * p[4 + row] + 128 >> 8;
|
|
2036
|
+
v2 = p[2 + row];
|
|
2037
|
+
v3 = p[6 + row];
|
|
2038
|
+
v4 = dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128 >> 8;
|
|
2039
|
+
v7 = dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128 >> 8;
|
|
2040
|
+
v5 = p[3 + row] << 4;
|
|
2041
|
+
v6 = p[5 + row] << 4;
|
|
2042
|
+
t = v0 - v1 + 1 >> 1;
|
|
2043
|
+
v0 = v0 + v1 + 1 >> 1;
|
|
2044
|
+
v1 = t;
|
|
2045
|
+
t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8;
|
|
2046
|
+
v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8;
|
|
2047
|
+
v3 = t;
|
|
2048
|
+
t = v4 - v6 + 1 >> 1;
|
|
2049
|
+
v4 = v4 + v6 + 1 >> 1;
|
|
2050
|
+
v6 = t;
|
|
2051
|
+
t = v7 + v5 + 1 >> 1;
|
|
2052
|
+
v5 = v7 - v5 + 1 >> 1;
|
|
2053
|
+
v7 = t;
|
|
2054
|
+
t = v0 - v3 + 1 >> 1;
|
|
2055
|
+
v0 = v0 + v3 + 1 >> 1;
|
|
2056
|
+
v3 = t;
|
|
2057
|
+
t = v1 - v2 + 1 >> 1;
|
|
2058
|
+
v1 = v1 + v2 + 1 >> 1;
|
|
2059
|
+
v2 = t;
|
|
2060
|
+
t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
|
|
2061
|
+
v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
|
|
2062
|
+
v7 = t;
|
|
2063
|
+
t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
|
|
2064
|
+
v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
|
|
2065
|
+
v6 = t;
|
|
2066
|
+
p[0 + row] = v0 + v7;
|
|
2067
|
+
p[7 + row] = v0 - v7;
|
|
2068
|
+
p[1 + row] = v1 + v6;
|
|
2069
|
+
p[6 + row] = v1 - v6;
|
|
2070
|
+
p[2 + row] = v2 + v5;
|
|
2071
|
+
p[5 + row] = v2 - v5;
|
|
2072
|
+
p[3 + row] = v3 + v4;
|
|
2073
|
+
p[4 + row] = v3 - v4;
|
|
2074
|
+
}
|
|
2075
|
+
for (i2 = 0; i2 < 8; ++i2) {
|
|
2076
|
+
var col = i2;
|
|
2077
|
+
if (p[1 * 8 + col] == 0 && p[2 * 8 + col] == 0 && p[3 * 8 + col] == 0 && p[4 * 8 + col] == 0 && p[5 * 8 + col] == 0 && p[6 * 8 + col] == 0 && p[7 * 8 + col] == 0) {
|
|
2078
|
+
t = dctSqrt2 * dataIn[i2 + 0] + 8192 >> 14;
|
|
2079
|
+
p[0 * 8 + col] = t;
|
|
2080
|
+
p[1 * 8 + col] = t;
|
|
2081
|
+
p[2 * 8 + col] = t;
|
|
2082
|
+
p[3 * 8 + col] = t;
|
|
2083
|
+
p[4 * 8 + col] = t;
|
|
2084
|
+
p[5 * 8 + col] = t;
|
|
2085
|
+
p[6 * 8 + col] = t;
|
|
2086
|
+
p[7 * 8 + col] = t;
|
|
2087
|
+
continue;
|
|
2088
|
+
}
|
|
2089
|
+
v0 = dctSqrt2 * p[0 * 8 + col] + 2048 >> 12;
|
|
2090
|
+
v1 = dctSqrt2 * p[4 * 8 + col] + 2048 >> 12;
|
|
2091
|
+
v2 = p[2 * 8 + col];
|
|
2092
|
+
v3 = p[6 * 8 + col];
|
|
2093
|
+
v4 = dctSqrt1d2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048 >> 12;
|
|
2094
|
+
v7 = dctSqrt1d2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048 >> 12;
|
|
2095
|
+
v5 = p[3 * 8 + col];
|
|
2096
|
+
v6 = p[5 * 8 + col];
|
|
2097
|
+
t = v0 - v1 + 1 >> 1;
|
|
2098
|
+
v0 = v0 + v1 + 1 >> 1;
|
|
2099
|
+
v1 = t;
|
|
2100
|
+
t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12;
|
|
2101
|
+
v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12;
|
|
2102
|
+
v3 = t;
|
|
2103
|
+
t = v4 - v6 + 1 >> 1;
|
|
2104
|
+
v4 = v4 + v6 + 1 >> 1;
|
|
2105
|
+
v6 = t;
|
|
2106
|
+
t = v7 + v5 + 1 >> 1;
|
|
2107
|
+
v5 = v7 - v5 + 1 >> 1;
|
|
2108
|
+
v7 = t;
|
|
2109
|
+
t = v0 - v3 + 1 >> 1;
|
|
2110
|
+
v0 = v0 + v3 + 1 >> 1;
|
|
2111
|
+
v3 = t;
|
|
2112
|
+
t = v1 - v2 + 1 >> 1;
|
|
2113
|
+
v1 = v1 + v2 + 1 >> 1;
|
|
2114
|
+
v2 = t;
|
|
2115
|
+
t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
|
|
2116
|
+
v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
|
|
2117
|
+
v7 = t;
|
|
2118
|
+
t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
|
|
2119
|
+
v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
|
|
2120
|
+
v6 = t;
|
|
2121
|
+
p[0 * 8 + col] = v0 + v7;
|
|
2122
|
+
p[7 * 8 + col] = v0 - v7;
|
|
2123
|
+
p[1 * 8 + col] = v1 + v6;
|
|
2124
|
+
p[6 * 8 + col] = v1 - v6;
|
|
2125
|
+
p[2 * 8 + col] = v2 + v5;
|
|
2126
|
+
p[5 * 8 + col] = v2 - v5;
|
|
2127
|
+
p[3 * 8 + col] = v3 + v4;
|
|
2128
|
+
p[4 * 8 + col] = v3 - v4;
|
|
2129
|
+
}
|
|
2130
|
+
for (i2 = 0; i2 < 64; ++i2) {
|
|
2131
|
+
var sample2 = 128 + (p[i2] + 8 >> 4);
|
|
2132
|
+
dataOut[i2] = sample2 < 0 ? 0 : sample2 > 255 ? 255 : sample2;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
requestMemoryAllocation(samplesPerLine * blocksPerColumn * 8);
|
|
2136
|
+
var i, j;
|
|
2137
|
+
for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
|
|
2138
|
+
var scanLine = blockRow << 3;
|
|
2139
|
+
for (i = 0; i < 8; i++)
|
|
2140
|
+
lines.push(new Uint8Array(samplesPerLine));
|
|
2141
|
+
for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
|
2142
|
+
quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
|
|
2143
|
+
var offset = 0, sample = blockCol << 3;
|
|
2144
|
+
for (j = 0; j < 8; j++) {
|
|
2145
|
+
var line = lines[scanLine + j];
|
|
2146
|
+
for (i = 0; i < 8; i++)
|
|
2147
|
+
line[sample + i] = r[offset++];
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
return lines;
|
|
2152
|
+
}
|
|
2153
|
+
function clampTo8bit(a) {
|
|
2154
|
+
return a < 0 ? 0 : a > 255 ? 255 : a;
|
|
2155
|
+
}
|
|
2156
|
+
constructor.prototype = {
|
|
2157
|
+
load: function load(path) {
|
|
2158
|
+
var xhr = new XMLHttpRequest();
|
|
2159
|
+
xhr.open("GET", path, true);
|
|
2160
|
+
xhr.responseType = "arraybuffer";
|
|
2161
|
+
xhr.onload = (function() {
|
|
2162
|
+
var data = new Uint8Array(xhr.response || xhr.mozResponseArrayBuffer);
|
|
2163
|
+
this.parse(data);
|
|
2164
|
+
if (this.onload)
|
|
2165
|
+
this.onload();
|
|
2166
|
+
}).bind(this);
|
|
2167
|
+
xhr.send(null);
|
|
2168
|
+
},
|
|
2169
|
+
parse: function parse(data) {
|
|
2170
|
+
var maxResolutionInPixels = this.opts.maxResolutionInMP * 1e3 * 1e3;
|
|
2171
|
+
var offset = 0, length = data.length;
|
|
2172
|
+
function readUint16() {
|
|
2173
|
+
var value = data[offset] << 8 | data[offset + 1];
|
|
2174
|
+
offset += 2;
|
|
2175
|
+
return value;
|
|
2176
|
+
}
|
|
2177
|
+
function readDataBlock() {
|
|
2178
|
+
var length2 = readUint16();
|
|
2179
|
+
var array = data.subarray(offset, offset + length2 - 2);
|
|
2180
|
+
offset += array.length;
|
|
2181
|
+
return array;
|
|
2182
|
+
}
|
|
2183
|
+
function prepareComponents(frame2) {
|
|
2184
|
+
var maxH2 = 1, maxV2 = 1;
|
|
2185
|
+
var component2, componentId2;
|
|
2186
|
+
for (componentId2 in frame2.components) {
|
|
2187
|
+
if (frame2.components.hasOwnProperty(componentId2)) {
|
|
2188
|
+
component2 = frame2.components[componentId2];
|
|
2189
|
+
if (maxH2 < component2.h) maxH2 = component2.h;
|
|
2190
|
+
if (maxV2 < component2.v) maxV2 = component2.v;
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
var mcusPerLine = Math.ceil(frame2.samplesPerLine / 8 / maxH2);
|
|
2194
|
+
var mcusPerColumn = Math.ceil(frame2.scanLines / 8 / maxV2);
|
|
2195
|
+
for (componentId2 in frame2.components) {
|
|
2196
|
+
if (frame2.components.hasOwnProperty(componentId2)) {
|
|
2197
|
+
component2 = frame2.components[componentId2];
|
|
2198
|
+
var blocksPerLine = Math.ceil(Math.ceil(frame2.samplesPerLine / 8) * component2.h / maxH2);
|
|
2199
|
+
var blocksPerColumn = Math.ceil(Math.ceil(frame2.scanLines / 8) * component2.v / maxV2);
|
|
2200
|
+
var blocksPerLineForMcu = mcusPerLine * component2.h;
|
|
2201
|
+
var blocksPerColumnForMcu = mcusPerColumn * component2.v;
|
|
2202
|
+
var blocksToAllocate = blocksPerColumnForMcu * blocksPerLineForMcu;
|
|
2203
|
+
var blocks = [];
|
|
2204
|
+
requestMemoryAllocation(blocksToAllocate * 256);
|
|
2205
|
+
for (var i2 = 0; i2 < blocksPerColumnForMcu; i2++) {
|
|
2206
|
+
var row = [];
|
|
2207
|
+
for (var j2 = 0; j2 < blocksPerLineForMcu; j2++)
|
|
2208
|
+
row.push(new Int32Array(64));
|
|
2209
|
+
blocks.push(row);
|
|
2210
|
+
}
|
|
2211
|
+
component2.blocksPerLine = blocksPerLine;
|
|
2212
|
+
component2.blocksPerColumn = blocksPerColumn;
|
|
2213
|
+
component2.blocks = blocks;
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
frame2.maxH = maxH2;
|
|
2217
|
+
frame2.maxV = maxV2;
|
|
2218
|
+
frame2.mcusPerLine = mcusPerLine;
|
|
2219
|
+
frame2.mcusPerColumn = mcusPerColumn;
|
|
2220
|
+
}
|
|
2221
|
+
var jfif = null;
|
|
2222
|
+
var adobe = null;
|
|
2223
|
+
var pixels = null;
|
|
2224
|
+
var frame, resetInterval;
|
|
2225
|
+
var quantizationTables = [], frames = [];
|
|
2226
|
+
var huffmanTablesAC = [], huffmanTablesDC = [];
|
|
2227
|
+
var fileMarker = readUint16();
|
|
2228
|
+
var malformedDataOffset = -1;
|
|
2229
|
+
this.comments = [];
|
|
2230
|
+
if (fileMarker != 65496) {
|
|
2231
|
+
throw new Error("SOI not found");
|
|
2232
|
+
}
|
|
2233
|
+
fileMarker = readUint16();
|
|
2234
|
+
while (fileMarker != 65497) {
|
|
2235
|
+
var i, j, l;
|
|
2236
|
+
switch (fileMarker) {
|
|
2237
|
+
case 65280:
|
|
2238
|
+
break;
|
|
2239
|
+
case 65504:
|
|
2240
|
+
// APP0 (Application Specific)
|
|
2241
|
+
case 65505:
|
|
2242
|
+
// APP1
|
|
2243
|
+
case 65506:
|
|
2244
|
+
// APP2
|
|
2245
|
+
case 65507:
|
|
2246
|
+
// APP3
|
|
2247
|
+
case 65508:
|
|
2248
|
+
// APP4
|
|
2249
|
+
case 65509:
|
|
2250
|
+
// APP5
|
|
2251
|
+
case 65510:
|
|
2252
|
+
// APP6
|
|
2253
|
+
case 65511:
|
|
2254
|
+
// APP7
|
|
2255
|
+
case 65512:
|
|
2256
|
+
// APP8
|
|
2257
|
+
case 65513:
|
|
2258
|
+
// APP9
|
|
2259
|
+
case 65514:
|
|
2260
|
+
// APP10
|
|
2261
|
+
case 65515:
|
|
2262
|
+
// APP11
|
|
2263
|
+
case 65516:
|
|
2264
|
+
// APP12
|
|
2265
|
+
case 65517:
|
|
2266
|
+
// APP13
|
|
2267
|
+
case 65518:
|
|
2268
|
+
// APP14
|
|
2269
|
+
case 65519:
|
|
2270
|
+
// APP15
|
|
2271
|
+
case 65534:
|
|
2272
|
+
var appData = readDataBlock();
|
|
2273
|
+
if (fileMarker === 65534) {
|
|
2274
|
+
var comment = String.fromCharCode.apply(null, appData);
|
|
2275
|
+
this.comments.push(comment);
|
|
2276
|
+
}
|
|
2277
|
+
if (fileMarker === 65504) {
|
|
2278
|
+
if (appData[0] === 74 && appData[1] === 70 && appData[2] === 73 && appData[3] === 70 && appData[4] === 0) {
|
|
2279
|
+
jfif = {
|
|
2280
|
+
version: { major: appData[5], minor: appData[6] },
|
|
2281
|
+
densityUnits: appData[7],
|
|
2282
|
+
xDensity: appData[8] << 8 | appData[9],
|
|
2283
|
+
yDensity: appData[10] << 8 | appData[11],
|
|
2284
|
+
thumbWidth: appData[12],
|
|
2285
|
+
thumbHeight: appData[13],
|
|
2286
|
+
thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
|
|
2287
|
+
};
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
if (fileMarker === 65505) {
|
|
2291
|
+
if (appData[0] === 69 && appData[1] === 120 && appData[2] === 105 && appData[3] === 102 && appData[4] === 0) {
|
|
2292
|
+
this.exifBuffer = appData.subarray(5, appData.length);
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2295
|
+
if (fileMarker === 65518) {
|
|
2296
|
+
if (appData[0] === 65 && appData[1] === 100 && appData[2] === 111 && appData[3] === 98 && appData[4] === 101 && appData[5] === 0) {
|
|
2297
|
+
adobe = {
|
|
2298
|
+
version: appData[6],
|
|
2299
|
+
flags0: appData[7] << 8 | appData[8],
|
|
2300
|
+
flags1: appData[9] << 8 | appData[10],
|
|
2301
|
+
transformCode: appData[11]
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
break;
|
|
2306
|
+
case 65499:
|
|
2307
|
+
var quantizationTablesLength = readUint16();
|
|
2308
|
+
var quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
|
2309
|
+
while (offset < quantizationTablesEnd) {
|
|
2310
|
+
var quantizationTableSpec = data[offset++];
|
|
2311
|
+
requestMemoryAllocation(64 * 4);
|
|
2312
|
+
var tableData = new Int32Array(64);
|
|
2313
|
+
if (quantizationTableSpec >> 4 === 0) {
|
|
2314
|
+
for (j = 0; j < 64; j++) {
|
|
2315
|
+
var z = dctZigZag[j];
|
|
2316
|
+
tableData[z] = data[offset++];
|
|
2317
|
+
}
|
|
2318
|
+
} else if (quantizationTableSpec >> 4 === 1) {
|
|
2319
|
+
for (j = 0; j < 64; j++) {
|
|
2320
|
+
var z = dctZigZag[j];
|
|
2321
|
+
tableData[z] = readUint16();
|
|
2322
|
+
}
|
|
2323
|
+
} else
|
|
2324
|
+
throw new Error("DQT: invalid table spec");
|
|
2325
|
+
quantizationTables[quantizationTableSpec & 15] = tableData;
|
|
2326
|
+
}
|
|
2327
|
+
break;
|
|
2328
|
+
case 65472:
|
|
2329
|
+
// SOF0 (Start of Frame, Baseline DCT)
|
|
2330
|
+
case 65473:
|
|
2331
|
+
// SOF1 (Start of Frame, Extended DCT)
|
|
2332
|
+
case 65474:
|
|
2333
|
+
readUint16();
|
|
2334
|
+
frame = {};
|
|
2335
|
+
frame.extended = fileMarker === 65473;
|
|
2336
|
+
frame.progressive = fileMarker === 65474;
|
|
2337
|
+
frame.precision = data[offset++];
|
|
2338
|
+
frame.scanLines = readUint16();
|
|
2339
|
+
frame.samplesPerLine = readUint16();
|
|
2340
|
+
frame.components = {};
|
|
2341
|
+
frame.componentsOrder = [];
|
|
2342
|
+
var pixelsInFrame = frame.scanLines * frame.samplesPerLine;
|
|
2343
|
+
if (pixelsInFrame > maxResolutionInPixels) {
|
|
2344
|
+
var exceededAmount = Math.ceil((pixelsInFrame - maxResolutionInPixels) / 1e6);
|
|
2345
|
+
throw new Error(`maxResolutionInMP limit exceeded by ${exceededAmount}MP`);
|
|
2346
|
+
}
|
|
2347
|
+
var componentsCount = data[offset++], componentId;
|
|
2348
|
+
var maxH = 0, maxV = 0;
|
|
2349
|
+
for (i = 0; i < componentsCount; i++) {
|
|
2350
|
+
componentId = data[offset];
|
|
2351
|
+
var h = data[offset + 1] >> 4;
|
|
2352
|
+
var v = data[offset + 1] & 15;
|
|
2353
|
+
var qId = data[offset + 2];
|
|
2354
|
+
if (h <= 0 || v <= 0) {
|
|
2355
|
+
throw new Error("Invalid sampling factor, expected values above 0");
|
|
2356
|
+
}
|
|
2357
|
+
frame.componentsOrder.push(componentId);
|
|
2358
|
+
frame.components[componentId] = {
|
|
2359
|
+
h,
|
|
2360
|
+
v,
|
|
2361
|
+
quantizationIdx: qId
|
|
2362
|
+
};
|
|
2363
|
+
offset += 3;
|
|
2364
|
+
}
|
|
2365
|
+
prepareComponents(frame);
|
|
2366
|
+
frames.push(frame);
|
|
2367
|
+
break;
|
|
2368
|
+
case 65476:
|
|
2369
|
+
var huffmanLength = readUint16();
|
|
2370
|
+
for (i = 2; i < huffmanLength; ) {
|
|
2371
|
+
var huffmanTableSpec = data[offset++];
|
|
2372
|
+
var codeLengths = new Uint8Array(16);
|
|
2373
|
+
var codeLengthSum = 0;
|
|
2374
|
+
for (j = 0; j < 16; j++, offset++) {
|
|
2375
|
+
codeLengthSum += codeLengths[j] = data[offset];
|
|
2376
|
+
}
|
|
2377
|
+
requestMemoryAllocation(16 + codeLengthSum);
|
|
2378
|
+
var huffmanValues = new Uint8Array(codeLengthSum);
|
|
2379
|
+
for (j = 0; j < codeLengthSum; j++, offset++)
|
|
2380
|
+
huffmanValues[j] = data[offset];
|
|
2381
|
+
i += 17 + codeLengthSum;
|
|
2382
|
+
(huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues);
|
|
2383
|
+
}
|
|
2384
|
+
break;
|
|
2385
|
+
case 65501:
|
|
2386
|
+
readUint16();
|
|
2387
|
+
resetInterval = readUint16();
|
|
2388
|
+
break;
|
|
2389
|
+
case 65500:
|
|
2390
|
+
readUint16();
|
|
2391
|
+
readUint16();
|
|
2392
|
+
break;
|
|
2393
|
+
case 65498:
|
|
2394
|
+
var scanLength = readUint16();
|
|
2395
|
+
var selectorsCount = data[offset++];
|
|
2396
|
+
var components = [], component;
|
|
2397
|
+
for (i = 0; i < selectorsCount; i++) {
|
|
2398
|
+
component = frame.components[data[offset++]];
|
|
2399
|
+
var tableSpec = data[offset++];
|
|
2400
|
+
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
|
|
2401
|
+
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
|
|
2402
|
+
components.push(component);
|
|
2403
|
+
}
|
|
2404
|
+
var spectralStart = data[offset++];
|
|
2405
|
+
var spectralEnd = data[offset++];
|
|
2406
|
+
var successiveApproximation = data[offset++];
|
|
2407
|
+
var processed = decodeScan(
|
|
2408
|
+
data,
|
|
2409
|
+
offset,
|
|
2410
|
+
frame,
|
|
2411
|
+
components,
|
|
2412
|
+
resetInterval,
|
|
2413
|
+
spectralStart,
|
|
2414
|
+
spectralEnd,
|
|
2415
|
+
successiveApproximation >> 4,
|
|
2416
|
+
successiveApproximation & 15,
|
|
2417
|
+
this.opts
|
|
2418
|
+
);
|
|
2419
|
+
offset += processed;
|
|
2420
|
+
break;
|
|
2421
|
+
case 65535:
|
|
2422
|
+
if (data[offset] !== 255) {
|
|
2423
|
+
offset--;
|
|
2424
|
+
}
|
|
2425
|
+
break;
|
|
2426
|
+
default:
|
|
2427
|
+
if (data[offset - 3] == 255 && data[offset - 2] >= 192 && data[offset - 2] <= 254) {
|
|
2428
|
+
offset -= 3;
|
|
2429
|
+
break;
|
|
2430
|
+
} else if (fileMarker === 224 || fileMarker == 225) {
|
|
2431
|
+
if (malformedDataOffset !== -1) {
|
|
2432
|
+
throw new Error(`first unknown JPEG marker at offset ${malformedDataOffset.toString(16)}, second unknown JPEG marker ${fileMarker.toString(16)} at offset ${(offset - 1).toString(16)}`);
|
|
2433
|
+
}
|
|
2434
|
+
malformedDataOffset = offset - 1;
|
|
2435
|
+
const nextOffset = readUint16();
|
|
2436
|
+
if (data[offset + nextOffset - 2] === 255) {
|
|
2437
|
+
offset += nextOffset - 2;
|
|
2438
|
+
break;
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
throw new Error("unknown JPEG marker " + fileMarker.toString(16));
|
|
2442
|
+
}
|
|
2443
|
+
fileMarker = readUint16();
|
|
2444
|
+
}
|
|
2445
|
+
if (frames.length != 1)
|
|
2446
|
+
throw new Error("only single frame JPEGs supported");
|
|
2447
|
+
for (var i = 0; i < frames.length; i++) {
|
|
2448
|
+
var cp = frames[i].components;
|
|
2449
|
+
for (var j in cp) {
|
|
2450
|
+
cp[j].quantizationTable = quantizationTables[cp[j].quantizationIdx];
|
|
2451
|
+
delete cp[j].quantizationIdx;
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
this.width = frame.samplesPerLine;
|
|
2455
|
+
this.height = frame.scanLines;
|
|
2456
|
+
this.jfif = jfif;
|
|
2457
|
+
this.adobe = adobe;
|
|
2458
|
+
this.components = [];
|
|
2459
|
+
for (var i = 0; i < frame.componentsOrder.length; i++) {
|
|
2460
|
+
var component = frame.components[frame.componentsOrder[i]];
|
|
2461
|
+
this.components.push({
|
|
2462
|
+
lines: buildComponentData(frame, component),
|
|
2463
|
+
scaleX: component.h / frame.maxH,
|
|
2464
|
+
scaleY: component.v / frame.maxV
|
|
2465
|
+
});
|
|
2466
|
+
}
|
|
2467
|
+
},
|
|
2468
|
+
getData: function getData(width, height) {
|
|
2469
|
+
var scaleX = this.width / width, scaleY = this.height / height;
|
|
2470
|
+
var component1, component2, component3, component4;
|
|
2471
|
+
var component1Line, component2Line, component3Line, component4Line;
|
|
2472
|
+
var x, y;
|
|
2473
|
+
var offset = 0;
|
|
2474
|
+
var Y, Cb, Cr, K, C, M, Ye, R, G, B;
|
|
2475
|
+
var colorTransform;
|
|
2476
|
+
var dataLength = width * height * this.components.length;
|
|
2477
|
+
requestMemoryAllocation(dataLength);
|
|
2478
|
+
var data = new Uint8Array(dataLength);
|
|
2479
|
+
switch (this.components.length) {
|
|
2480
|
+
case 1:
|
|
2481
|
+
component1 = this.components[0];
|
|
2482
|
+
for (y = 0; y < height; y++) {
|
|
2483
|
+
component1Line = component1.lines[0 | y * component1.scaleY * scaleY];
|
|
2484
|
+
for (x = 0; x < width; x++) {
|
|
2485
|
+
Y = component1Line[0 | x * component1.scaleX * scaleX];
|
|
2486
|
+
data[offset++] = Y;
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
break;
|
|
2490
|
+
case 2:
|
|
2491
|
+
component1 = this.components[0];
|
|
2492
|
+
component2 = this.components[1];
|
|
2493
|
+
for (y = 0; y < height; y++) {
|
|
2494
|
+
component1Line = component1.lines[0 | y * component1.scaleY * scaleY];
|
|
2495
|
+
component2Line = component2.lines[0 | y * component2.scaleY * scaleY];
|
|
2496
|
+
for (x = 0; x < width; x++) {
|
|
2497
|
+
Y = component1Line[0 | x * component1.scaleX * scaleX];
|
|
2498
|
+
data[offset++] = Y;
|
|
2499
|
+
Y = component2Line[0 | x * component2.scaleX * scaleX];
|
|
2500
|
+
data[offset++] = Y;
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
break;
|
|
2504
|
+
case 3:
|
|
2505
|
+
colorTransform = true;
|
|
2506
|
+
if (this.adobe && this.adobe.transformCode)
|
|
2507
|
+
colorTransform = true;
|
|
2508
|
+
else if (typeof this.opts.colorTransform !== "undefined")
|
|
2509
|
+
colorTransform = !!this.opts.colorTransform;
|
|
2510
|
+
component1 = this.components[0];
|
|
2511
|
+
component2 = this.components[1];
|
|
2512
|
+
component3 = this.components[2];
|
|
2513
|
+
for (y = 0; y < height; y++) {
|
|
2514
|
+
component1Line = component1.lines[0 | y * component1.scaleY * scaleY];
|
|
2515
|
+
component2Line = component2.lines[0 | y * component2.scaleY * scaleY];
|
|
2516
|
+
component3Line = component3.lines[0 | y * component3.scaleY * scaleY];
|
|
2517
|
+
for (x = 0; x < width; x++) {
|
|
2518
|
+
if (!colorTransform) {
|
|
2519
|
+
R = component1Line[0 | x * component1.scaleX * scaleX];
|
|
2520
|
+
G = component2Line[0 | x * component2.scaleX * scaleX];
|
|
2521
|
+
B = component3Line[0 | x * component3.scaleX * scaleX];
|
|
2522
|
+
} else {
|
|
2523
|
+
Y = component1Line[0 | x * component1.scaleX * scaleX];
|
|
2524
|
+
Cb = component2Line[0 | x * component2.scaleX * scaleX];
|
|
2525
|
+
Cr = component3Line[0 | x * component3.scaleX * scaleX];
|
|
2526
|
+
R = clampTo8bit(Y + 1.402 * (Cr - 128));
|
|
2527
|
+
G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
|
|
2528
|
+
B = clampTo8bit(Y + 1.772 * (Cb - 128));
|
|
2529
|
+
}
|
|
2530
|
+
data[offset++] = R;
|
|
2531
|
+
data[offset++] = G;
|
|
2532
|
+
data[offset++] = B;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
break;
|
|
2536
|
+
case 4:
|
|
2537
|
+
if (!this.adobe)
|
|
2538
|
+
throw new Error("Unsupported color mode (4 components)");
|
|
2539
|
+
colorTransform = false;
|
|
2540
|
+
if (this.adobe && this.adobe.transformCode)
|
|
2541
|
+
colorTransform = true;
|
|
2542
|
+
else if (typeof this.opts.colorTransform !== "undefined")
|
|
2543
|
+
colorTransform = !!this.opts.colorTransform;
|
|
2544
|
+
component1 = this.components[0];
|
|
2545
|
+
component2 = this.components[1];
|
|
2546
|
+
component3 = this.components[2];
|
|
2547
|
+
component4 = this.components[3];
|
|
2548
|
+
for (y = 0; y < height; y++) {
|
|
2549
|
+
component1Line = component1.lines[0 | y * component1.scaleY * scaleY];
|
|
2550
|
+
component2Line = component2.lines[0 | y * component2.scaleY * scaleY];
|
|
2551
|
+
component3Line = component3.lines[0 | y * component3.scaleY * scaleY];
|
|
2552
|
+
component4Line = component4.lines[0 | y * component4.scaleY * scaleY];
|
|
2553
|
+
for (x = 0; x < width; x++) {
|
|
2554
|
+
if (!colorTransform) {
|
|
2555
|
+
C = component1Line[0 | x * component1.scaleX * scaleX];
|
|
2556
|
+
M = component2Line[0 | x * component2.scaleX * scaleX];
|
|
2557
|
+
Ye = component3Line[0 | x * component3.scaleX * scaleX];
|
|
2558
|
+
K = component4Line[0 | x * component4.scaleX * scaleX];
|
|
2559
|
+
} else {
|
|
2560
|
+
Y = component1Line[0 | x * component1.scaleX * scaleX];
|
|
2561
|
+
Cb = component2Line[0 | x * component2.scaleX * scaleX];
|
|
2562
|
+
Cr = component3Line[0 | x * component3.scaleX * scaleX];
|
|
2563
|
+
K = component4Line[0 | x * component4.scaleX * scaleX];
|
|
2564
|
+
C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128));
|
|
2565
|
+
M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
|
|
2566
|
+
Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128));
|
|
2567
|
+
}
|
|
2568
|
+
data[offset++] = 255 - C;
|
|
2569
|
+
data[offset++] = 255 - M;
|
|
2570
|
+
data[offset++] = 255 - Ye;
|
|
2571
|
+
data[offset++] = 255 - K;
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
break;
|
|
2575
|
+
default:
|
|
2576
|
+
throw new Error("Unsupported color mode");
|
|
2577
|
+
}
|
|
2578
|
+
return data;
|
|
2579
|
+
},
|
|
2580
|
+
copyToImageData: function copyToImageData(imageData, formatAsRGBA) {
|
|
2581
|
+
var width = imageData.width, height = imageData.height;
|
|
2582
|
+
var imageDataArray = imageData.data;
|
|
2583
|
+
var data = this.getData(width, height);
|
|
2584
|
+
var i = 0, j = 0, x, y;
|
|
2585
|
+
var Y, K, C, M, R, G, B;
|
|
2586
|
+
switch (this.components.length) {
|
|
2587
|
+
case 1:
|
|
2588
|
+
for (y = 0; y < height; y++) {
|
|
2589
|
+
for (x = 0; x < width; x++) {
|
|
2590
|
+
Y = data[i++];
|
|
2591
|
+
imageDataArray[j++] = Y;
|
|
2592
|
+
imageDataArray[j++] = Y;
|
|
2593
|
+
imageDataArray[j++] = Y;
|
|
2594
|
+
if (formatAsRGBA) {
|
|
2595
|
+
imageDataArray[j++] = 255;
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2599
|
+
break;
|
|
2600
|
+
case 3:
|
|
2601
|
+
for (y = 0; y < height; y++) {
|
|
2602
|
+
for (x = 0; x < width; x++) {
|
|
2603
|
+
R = data[i++];
|
|
2604
|
+
G = data[i++];
|
|
2605
|
+
B = data[i++];
|
|
2606
|
+
imageDataArray[j++] = R;
|
|
2607
|
+
imageDataArray[j++] = G;
|
|
2608
|
+
imageDataArray[j++] = B;
|
|
2609
|
+
if (formatAsRGBA) {
|
|
2610
|
+
imageDataArray[j++] = 255;
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
}
|
|
2614
|
+
break;
|
|
2615
|
+
case 4:
|
|
2616
|
+
for (y = 0; y < height; y++) {
|
|
2617
|
+
for (x = 0; x < width; x++) {
|
|
2618
|
+
C = data[i++];
|
|
2619
|
+
M = data[i++];
|
|
2620
|
+
Y = data[i++];
|
|
2621
|
+
K = data[i++];
|
|
2622
|
+
R = 255 - clampTo8bit(C * (1 - K / 255) + K);
|
|
2623
|
+
G = 255 - clampTo8bit(M * (1 - K / 255) + K);
|
|
2624
|
+
B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
|
|
2625
|
+
imageDataArray[j++] = R;
|
|
2626
|
+
imageDataArray[j++] = G;
|
|
2627
|
+
imageDataArray[j++] = B;
|
|
2628
|
+
if (formatAsRGBA) {
|
|
2629
|
+
imageDataArray[j++] = 255;
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
break;
|
|
2634
|
+
default:
|
|
2635
|
+
throw new Error("Unsupported color mode");
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
};
|
|
2639
|
+
var totalBytesAllocated = 0;
|
|
2640
|
+
var maxMemoryUsageBytes = 0;
|
|
2641
|
+
function requestMemoryAllocation(increaseAmount = 0) {
|
|
2642
|
+
var totalMemoryImpactBytes = totalBytesAllocated + increaseAmount;
|
|
2643
|
+
if (totalMemoryImpactBytes > maxMemoryUsageBytes) {
|
|
2644
|
+
var exceededAmount = Math.ceil((totalMemoryImpactBytes - maxMemoryUsageBytes) / 1024 / 1024);
|
|
2645
|
+
throw new Error(`maxMemoryUsageInMB limit exceeded by at least ${exceededAmount}MB`);
|
|
2646
|
+
}
|
|
2647
|
+
totalBytesAllocated = totalMemoryImpactBytes;
|
|
2648
|
+
}
|
|
2649
|
+
constructor.resetMaxMemoryUsage = function(maxMemoryUsageBytes_) {
|
|
2650
|
+
totalBytesAllocated = 0;
|
|
2651
|
+
maxMemoryUsageBytes = maxMemoryUsageBytes_;
|
|
2652
|
+
};
|
|
2653
|
+
constructor.getBytesAllocated = function() {
|
|
2654
|
+
return totalBytesAllocated;
|
|
2655
|
+
};
|
|
2656
|
+
constructor.requestMemoryAllocation = requestMemoryAllocation;
|
|
2657
|
+
return constructor;
|
|
2658
|
+
})();
|
|
2659
|
+
if (typeof module !== "undefined") {
|
|
2660
|
+
module.exports = decode;
|
|
2661
|
+
} else if (typeof window !== "undefined") {
|
|
2662
|
+
window["jpeg-js"] = window["jpeg-js"] || {};
|
|
2663
|
+
window["jpeg-js"].decode = decode;
|
|
2664
|
+
}
|
|
2665
|
+
function decode(jpegData, userOpts = {}) {
|
|
2666
|
+
var defaultOpts = {
|
|
2667
|
+
// "undefined" means "Choose whether to transform colors based on the image’s color model."
|
|
2668
|
+
colorTransform: void 0,
|
|
2669
|
+
useTArray: false,
|
|
2670
|
+
formatAsRGBA: true,
|
|
2671
|
+
tolerantDecoding: true,
|
|
2672
|
+
maxResolutionInMP: 100,
|
|
2673
|
+
// Don't decode more than 100 megapixels
|
|
2674
|
+
maxMemoryUsageInMB: 512
|
|
2675
|
+
// Don't decode if memory footprint is more than 512MB
|
|
2676
|
+
};
|
|
2677
|
+
var opts = { ...defaultOpts, ...userOpts };
|
|
2678
|
+
var arr = new Uint8Array(jpegData);
|
|
2679
|
+
var decoder = new JpegImage();
|
|
2680
|
+
decoder.opts = opts;
|
|
2681
|
+
JpegImage.resetMaxMemoryUsage(opts.maxMemoryUsageInMB * 1024 * 1024);
|
|
2682
|
+
decoder.parse(arr);
|
|
2683
|
+
var channels = opts.formatAsRGBA ? 4 : 3;
|
|
2684
|
+
var bytesNeeded = decoder.width * decoder.height * channels;
|
|
2685
|
+
try {
|
|
2686
|
+
JpegImage.requestMemoryAllocation(bytesNeeded);
|
|
2687
|
+
var image = {
|
|
2688
|
+
width: decoder.width,
|
|
2689
|
+
height: decoder.height,
|
|
2690
|
+
exifBuffer: decoder.exifBuffer,
|
|
2691
|
+
data: opts.useTArray ? new Uint8Array(bytesNeeded) : Buffer.alloc(bytesNeeded)
|
|
2692
|
+
};
|
|
2693
|
+
if (decoder.comments.length > 0) {
|
|
2694
|
+
image["comments"] = decoder.comments;
|
|
2695
|
+
}
|
|
2696
|
+
} catch (err) {
|
|
2697
|
+
if (err instanceof RangeError) {
|
|
2698
|
+
throw new Error("Could not allocate enough memory for the image. Required: " + bytesNeeded);
|
|
2699
|
+
}
|
|
2700
|
+
if (err instanceof ReferenceError) {
|
|
2701
|
+
if (err.message === "Buffer is not defined") {
|
|
2702
|
+
throw new Error("Buffer is not globally defined in this environment. Consider setting useTArray to true");
|
|
2703
|
+
}
|
|
2704
|
+
}
|
|
2705
|
+
throw err;
|
|
2706
|
+
}
|
|
2707
|
+
decoder.copyToImageData(image, opts.formatAsRGBA);
|
|
2708
|
+
return image;
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
});
|
|
2712
|
+
|
|
2713
|
+
// node_modules/jpeg-js/index.js
|
|
2714
|
+
var require_jpeg_js = __commonJS({
|
|
2715
|
+
"node_modules/jpeg-js/index.js"(exports, module) {
|
|
2716
|
+
init_define_import_meta_env();
|
|
2717
|
+
var encode = require_encoder();
|
|
2718
|
+
var decode = require_decoder();
|
|
2719
|
+
module.exports = {
|
|
2720
|
+
encode,
|
|
2721
|
+
decode
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
});
|
|
2725
|
+
|
|
2726
|
+
// src/image_engine.ts
|
|
2727
|
+
init_define_import_meta_env();
|
|
2728
|
+
var import_jpeg_js = __toESM(require_jpeg_js(), 1);
|
|
2729
|
+
var import_omggif = __toESM(require_omggif(), 1);
|
|
2730
|
+
import * as zlib from "node:zlib";
|
|
2731
|
+
var MAX_DECODED_BYTES = 256 * 1024 * 1024;
|
|
2732
|
+
function assertDecodableSize(what, width, height, bytesPerPixel, frames = 1) {
|
|
2733
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0 || frames <= 0) {
|
|
2734
|
+
throw new Error(`Invalid ${what} dimensions: ${width}x${height} (${frames} frame(s))`);
|
|
2735
|
+
}
|
|
2736
|
+
const bytes = width * height * bytesPerPixel * frames;
|
|
2737
|
+
if (bytes > MAX_DECODED_BYTES) {
|
|
2738
|
+
throw new Error(
|
|
2739
|
+
`${what} would allocate ${Math.round(bytes / 1048576)}MB, over the ${MAX_DECODED_BYTES / 1048576}MB decode ceiling`
|
|
2740
|
+
);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
var CRC_TABLE = new Int32Array(256);
|
|
2744
|
+
for (let i = 0; i < 256; i++) {
|
|
2745
|
+
let c = i;
|
|
2746
|
+
for (let k = 0; k < 8; k++) {
|
|
2747
|
+
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
2748
|
+
}
|
|
2749
|
+
CRC_TABLE[i] = c;
|
|
2750
|
+
}
|
|
2751
|
+
function crc32(buf) {
|
|
2752
|
+
let crc = -1;
|
|
2753
|
+
for (let i = 0; i < buf.length; i++) {
|
|
2754
|
+
const byte = buf[i] ?? 0;
|
|
2755
|
+
crc = (CRC_TABLE[(crc ^ byte) & 255] ?? 0) ^ crc >>> 8;
|
|
2756
|
+
}
|
|
2757
|
+
return (crc ^ -1) >>> 0;
|
|
2758
|
+
}
|
|
2759
|
+
function paethPredictor(a, b, c) {
|
|
2760
|
+
const p = a + b - c;
|
|
2761
|
+
const pa = Math.abs(p - a);
|
|
2762
|
+
const pb = Math.abs(p - b);
|
|
2763
|
+
const pc = Math.abs(p - c);
|
|
2764
|
+
if (pa <= pb && pa <= pc) return a;
|
|
2765
|
+
if (pb <= pc) return b;
|
|
2766
|
+
return c;
|
|
2767
|
+
}
|
|
2768
|
+
function probeBufferMeta(buf) {
|
|
2769
|
+
if (buf.length < 8) return null;
|
|
2770
|
+
if (buf[0] === 137 && buf[1] === 80 && buf[2] === 78 && buf[3] === 71 && buf[4] === 13 && buf[5] === 10 && buf[6] === 26 && buf[7] === 10) {
|
|
2771
|
+
if (buf.length < 24) return null;
|
|
2772
|
+
const width = buf.readUInt32BE(16);
|
|
2773
|
+
const height = buf.readUInt32BE(20);
|
|
2774
|
+
return { width, height, format: "png", pages: 1 };
|
|
2775
|
+
}
|
|
2776
|
+
if (buf[0] === 255 && buf[1] === 216 && buf[2] === 255) {
|
|
2777
|
+
let pos = 2;
|
|
2778
|
+
let width = 0;
|
|
2779
|
+
let height = 0;
|
|
2780
|
+
let orientation = 1;
|
|
2781
|
+
while (pos < buf.length - 1) {
|
|
2782
|
+
if (buf[pos] !== 255) {
|
|
2783
|
+
pos++;
|
|
2784
|
+
continue;
|
|
2785
|
+
}
|
|
2786
|
+
const marker = buf[pos + 1];
|
|
2787
|
+
if (marker === void 0) break;
|
|
2788
|
+
pos += 2;
|
|
2789
|
+
if (marker === 216 || marker === 217 || marker === 0 || marker >= 208 && marker <= 215) {
|
|
2790
|
+
continue;
|
|
2791
|
+
}
|
|
2792
|
+
if (pos + 2 > buf.length) break;
|
|
2793
|
+
const length = buf.readUInt16BE(pos);
|
|
2794
|
+
if (length < 2 || pos + length > buf.length) break;
|
|
2795
|
+
if (marker === 225 && length >= 14) {
|
|
2796
|
+
const exifHeader = buf.toString("ascii", pos + 2, pos + 6);
|
|
2797
|
+
if (exifHeader === "Exif") {
|
|
2798
|
+
const tiffStart = pos + 8;
|
|
2799
|
+
if (tiffStart + 8 <= buf.length) {
|
|
2800
|
+
const isLE = buf[tiffStart] === 73 && buf[tiffStart + 1] === 73;
|
|
2801
|
+
const ifdOffset = isLE ? buf.readUInt32LE(tiffStart + 4) : buf.readUInt32BE(tiffStart + 4);
|
|
2802
|
+
let ifdPos = tiffStart + ifdOffset;
|
|
2803
|
+
if (ifdPos + 2 <= buf.length) {
|
|
2804
|
+
const numEntries = isLE ? buf.readUInt16LE(ifdPos) : buf.readUInt16BE(ifdPos);
|
|
2805
|
+
ifdPos += 2;
|
|
2806
|
+
for (let e = 0; e < numEntries && ifdPos + 12 <= buf.length; e++, ifdPos += 12) {
|
|
2807
|
+
const tag = isLE ? buf.readUInt16LE(ifdPos) : buf.readUInt16BE(ifdPos);
|
|
2808
|
+
if (tag === 274) {
|
|
2809
|
+
orientation = isLE ? buf.readUInt16LE(ifdPos + 8) : buf.readUInt16BE(ifdPos + 8);
|
|
2810
|
+
break;
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
const isSof = marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207;
|
|
2818
|
+
if (isSof && length >= 7) {
|
|
2819
|
+
height = buf.readUInt16BE(pos + 3);
|
|
2820
|
+
width = buf.readUInt16BE(pos + 5);
|
|
2821
|
+
break;
|
|
2822
|
+
}
|
|
2823
|
+
pos += length;
|
|
2824
|
+
}
|
|
2825
|
+
if (width > 0 && height > 0) {
|
|
2826
|
+
if (orientation >= 5 && orientation <= 8) {
|
|
2827
|
+
return { width: height, height: width, format: "jpeg", pages: 1, orientation };
|
|
2828
|
+
}
|
|
2829
|
+
return { width, height, format: "jpeg", pages: 1, orientation };
|
|
2830
|
+
}
|
|
2831
|
+
return null;
|
|
2832
|
+
}
|
|
2833
|
+
const gifSig = buf.toString("ascii", 0, 6);
|
|
2834
|
+
if (gifSig === "GIF87a" || gifSig === "GIF89a") {
|
|
2835
|
+
const width = buf.readUInt16LE(6);
|
|
2836
|
+
const height = buf.readUInt16LE(8);
|
|
2837
|
+
let pages;
|
|
2838
|
+
try {
|
|
2839
|
+
const reader = new import_omggif.default.GifReader(buf);
|
|
2840
|
+
pages = reader.numFrames();
|
|
2841
|
+
} catch {
|
|
2842
|
+
let count = 0;
|
|
2843
|
+
for (let i = 13; i < buf.length - 9; i++) {
|
|
2844
|
+
if (buf[i] === 44) count++;
|
|
2845
|
+
}
|
|
2846
|
+
pages = Math.max(1, count);
|
|
2847
|
+
}
|
|
2848
|
+
return { width, height, format: "gif", pages };
|
|
2849
|
+
}
|
|
2850
|
+
if (buf.toString("ascii", 0, 4) === "RIFF" && buf.toString("ascii", 8, 12) === "WEBP") {
|
|
2851
|
+
const chunkType = buf.toString("ascii", 12, 16);
|
|
2852
|
+
if (chunkType === "VP8 " && buf.length >= 30) {
|
|
2853
|
+
const width = buf.readUInt16LE(26) & 16383;
|
|
2854
|
+
const height = buf.readUInt16LE(28) & 16383;
|
|
2855
|
+
return { width, height, format: "webp", pages: 1 };
|
|
2856
|
+
}
|
|
2857
|
+
if (chunkType === "VP8L" && buf.length >= 25) {
|
|
2858
|
+
const b1 = buf[21] ?? 0;
|
|
2859
|
+
const b2 = buf[22] ?? 0;
|
|
2860
|
+
const b3 = buf[23] ?? 0;
|
|
2861
|
+
const b4 = buf[24] ?? 0;
|
|
2862
|
+
const width = 1 + ((b2 & 63) << 8 | b1);
|
|
2863
|
+
const height = 1 + ((b4 & 15) << 10 | b3 << 2 | (b2 & 192) >> 6);
|
|
2864
|
+
return { width, height, format: "webp", pages: 1 };
|
|
2865
|
+
}
|
|
2866
|
+
if (chunkType === "VP8X" && buf.length >= 30) {
|
|
2867
|
+
const b24 = buf[24] ?? 0;
|
|
2868
|
+
const b25 = buf[25] ?? 0;
|
|
2869
|
+
const b26 = buf[26] ?? 0;
|
|
2870
|
+
const b27 = buf[27] ?? 0;
|
|
2871
|
+
const b28 = buf[28] ?? 0;
|
|
2872
|
+
const b29 = buf[29] ?? 0;
|
|
2873
|
+
const b20 = buf[20] ?? 0;
|
|
2874
|
+
const width = 1 + (b24 | b25 << 8 | b26 << 16);
|
|
2875
|
+
const height = 1 + (b27 | b28 << 8 | b29 << 16);
|
|
2876
|
+
const isAnimated = (b20 & 2) !== 0;
|
|
2877
|
+
let pages = 1;
|
|
2878
|
+
if (isAnimated) {
|
|
2879
|
+
let count = 0;
|
|
2880
|
+
let pos = 30;
|
|
2881
|
+
while (pos < buf.length - 8) {
|
|
2882
|
+
const type = buf.toString("ascii", pos, pos + 4);
|
|
2883
|
+
const len = buf.readUInt32LE(pos + 4);
|
|
2884
|
+
if (type === "ANMF") count++;
|
|
2885
|
+
pos += 8 + len + (len & 1);
|
|
2886
|
+
}
|
|
2887
|
+
pages = Math.max(1, count);
|
|
2888
|
+
}
|
|
2889
|
+
return { width, height, format: "webp", pages };
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
if (buf[0] === 66 && buf[1] === 77 && buf.length >= 26) {
|
|
2893
|
+
const width = buf.readInt32LE(18);
|
|
2894
|
+
const height = Math.abs(buf.readInt32LE(22));
|
|
2895
|
+
return { width, height, format: "bmp", pages: 1 };
|
|
2896
|
+
}
|
|
2897
|
+
const isTiffLE = buf[0] === 73 && buf[1] === 73 && buf[2] === 42 && buf[3] === 0;
|
|
2898
|
+
const isTiffBE = buf[0] === 77 && buf[1] === 77 && buf[2] === 0 && buf[3] === 42;
|
|
2899
|
+
if (isTiffLE || isTiffBE) {
|
|
2900
|
+
const isLE = isTiffLE;
|
|
2901
|
+
let ifdOffset = isLE ? buf.readUInt32LE(4) : buf.readUInt32BE(4);
|
|
2902
|
+
let width = 0;
|
|
2903
|
+
let height = 0;
|
|
2904
|
+
let pages = 0;
|
|
2905
|
+
const seenIfdOffsets = /* @__PURE__ */ new Set();
|
|
2906
|
+
while (ifdOffset > 0 && ifdOffset + 2 <= buf.length) {
|
|
2907
|
+
if (seenIfdOffsets.has(ifdOffset)) break;
|
|
2908
|
+
seenIfdOffsets.add(ifdOffset);
|
|
2909
|
+
pages++;
|
|
2910
|
+
const numEntries = isLE ? buf.readUInt16LE(ifdOffset) : buf.readUInt16BE(ifdOffset);
|
|
2911
|
+
let ifdPos = ifdOffset + 2;
|
|
2912
|
+
for (let e = 0; e < numEntries && ifdPos + 12 <= buf.length; e++, ifdPos += 12) {
|
|
2913
|
+
const tag = isLE ? buf.readUInt16LE(ifdPos) : buf.readUInt16BE(ifdPos);
|
|
2914
|
+
if (tag === 256 && width === 0) {
|
|
2915
|
+
const type = isLE ? buf.readUInt16LE(ifdPos + 2) : buf.readUInt16BE(ifdPos + 2);
|
|
2916
|
+
width = type === 3 ? isLE ? buf.readUInt16LE(ifdPos + 8) : buf.readUInt16BE(ifdPos + 8) : isLE ? buf.readUInt32LE(ifdPos + 8) : buf.readUInt32BE(ifdPos + 8);
|
|
2917
|
+
} else if (tag === 257 && height === 0) {
|
|
2918
|
+
const type = isLE ? buf.readUInt16LE(ifdPos + 2) : buf.readUInt16BE(ifdPos + 2);
|
|
2919
|
+
height = type === 3 ? isLE ? buf.readUInt16LE(ifdPos + 8) : buf.readUInt16BE(ifdPos + 8) : isLE ? buf.readUInt32LE(ifdPos + 8) : buf.readUInt32BE(ifdPos + 8);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
const nextIfdPos = ifdOffset + 2 + numEntries * 12;
|
|
2923
|
+
if (nextIfdPos + 4 <= buf.length) {
|
|
2924
|
+
ifdOffset = isLE ? buf.readUInt32LE(nextIfdPos) : buf.readUInt32BE(nextIfdPos);
|
|
2925
|
+
} else {
|
|
2926
|
+
break;
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
if (width > 0 && height > 0) {
|
|
2930
|
+
return { width, height, format: "tiff", pages: Math.max(1, pages) };
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
const sample = buf.subarray(0, Math.min(buf.length, 4096)).toString("utf8");
|
|
2934
|
+
if (sample.includes("<svg")) {
|
|
2935
|
+
const widthMatch = /width=["']([0-9.]+)(px)?["']/i.exec(sample);
|
|
2936
|
+
const heightMatch = /height=["']([0-9.]+)(px)?["']/i.exec(sample);
|
|
2937
|
+
const viewBoxMatch = /viewBox=["']([0-9. -]+)["']/i.exec(sample);
|
|
2938
|
+
let width = widthMatch && widthMatch[1] ? parseFloat(widthMatch[1]) : 0;
|
|
2939
|
+
let height = heightMatch && heightMatch[1] ? parseFloat(heightMatch[1]) : 0;
|
|
2940
|
+
if ((!width || !height) && viewBoxMatch && viewBoxMatch[1]) {
|
|
2941
|
+
const parts = viewBoxMatch[1].trim().split(/[\s,]+/).map(parseFloat);
|
|
2942
|
+
if (parts.length === 4 && parts[2] !== void 0 && parts[3] !== void 0) {
|
|
2943
|
+
width = parts[2];
|
|
2944
|
+
height = parts[3];
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
if (width > 0 && height > 0) {
|
|
2948
|
+
return { width: Math.round(width), height: Math.round(height), format: "svg", pages: 1 };
|
|
2949
|
+
}
|
|
2950
|
+
return { width: 100, height: 100, format: "svg", pages: 1 };
|
|
2951
|
+
}
|
|
2952
|
+
return null;
|
|
2953
|
+
}
|
|
2954
|
+
function decodePng(buf) {
|
|
2955
|
+
if (buf.length < 8 || buf[0] !== 137 || buf[1] !== 80 || buf[2] !== 78 || buf[3] !== 71) {
|
|
2956
|
+
throw new Error("Invalid PNG signature");
|
|
2957
|
+
}
|
|
2958
|
+
let pos = 8;
|
|
2959
|
+
let width = 0;
|
|
2960
|
+
let height = 0;
|
|
2961
|
+
let colorType = 6;
|
|
2962
|
+
const idatChunks = [];
|
|
2963
|
+
let palette = null;
|
|
2964
|
+
let trns = null;
|
|
2965
|
+
while (pos < buf.length) {
|
|
2966
|
+
const len = buf.readUInt32BE(pos);
|
|
2967
|
+
const type = buf.toString("ascii", pos + 4, pos + 8);
|
|
2968
|
+
const data = buf.subarray(pos + 8, pos + 8 + len);
|
|
2969
|
+
pos += 8 + len + 4;
|
|
2970
|
+
if (type === "IHDR") {
|
|
2971
|
+
width = data.readUInt32BE(0);
|
|
2972
|
+
height = data.readUInt32BE(4);
|
|
2973
|
+
const bitDepth = data[8] ?? 8;
|
|
2974
|
+
colorType = data[9] ?? 6;
|
|
2975
|
+
if (bitDepth !== 8) {
|
|
2976
|
+
throw new Error("Unsupported PNG bit depth: " + bitDepth);
|
|
2977
|
+
}
|
|
2978
|
+
const interlace = data[12] ?? 0;
|
|
2979
|
+
if (interlace !== 0) {
|
|
2980
|
+
throw new Error("Unsupported PNG interlace method: " + interlace);
|
|
2981
|
+
}
|
|
2982
|
+
} else if (type === "PLTE") {
|
|
2983
|
+
palette = data;
|
|
2984
|
+
} else if (type === "tRNS") {
|
|
2985
|
+
trns = data;
|
|
2986
|
+
} else if (type === "IDAT") {
|
|
2987
|
+
idatChunks.push(data);
|
|
2988
|
+
} else if (type === "IEND") {
|
|
2989
|
+
break;
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
if (width === 0 || height === 0) {
|
|
2993
|
+
throw new Error("Missing PNG IHDR chunk");
|
|
2994
|
+
}
|
|
2995
|
+
let bpp = 4;
|
|
2996
|
+
if (colorType === 0) bpp = 1;
|
|
2997
|
+
else if (colorType === 2) bpp = 3;
|
|
2998
|
+
else if (colorType === 3) bpp = 1;
|
|
2999
|
+
else if (colorType === 4) bpp = 2;
|
|
3000
|
+
else if (colorType === 6) bpp = 4;
|
|
3001
|
+
assertDecodableSize("PNG", width, height, 4);
|
|
3002
|
+
const rowBytes = width * bpp;
|
|
3003
|
+
const rowSize = 1 + rowBytes;
|
|
3004
|
+
const maxRawBytes = height * rowSize;
|
|
3005
|
+
const compressed = Buffer.concat(idatChunks);
|
|
3006
|
+
let decompressed;
|
|
3007
|
+
try {
|
|
3008
|
+
decompressed = zlib.inflateSync(compressed, { maxOutputLength: maxRawBytes });
|
|
3009
|
+
} catch (err) {
|
|
3010
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3011
|
+
throw new Error(`PNG image data exceeds the ${maxRawBytes} bytes its ${width}x${height} header allows: ${msg}`, {
|
|
3012
|
+
cause: err
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
3015
|
+
const outRgba = Buffer.alloc(width * height * 4);
|
|
3016
|
+
const priorRow = Buffer.alloc(rowBytes);
|
|
3017
|
+
const currRow = Buffer.alloc(rowBytes);
|
|
3018
|
+
for (let y = 0; y < height; y++) {
|
|
3019
|
+
const filter = decompressed[y * rowSize] ?? 0;
|
|
3020
|
+
const rawOffset = y * rowSize + 1;
|
|
3021
|
+
for (let x = 0; x < rowBytes; x++) {
|
|
3022
|
+
const rawVal = decompressed[rawOffset + x] ?? 0;
|
|
3023
|
+
const a = x >= bpp ? currRow[x - bpp] ?? 0 : 0;
|
|
3024
|
+
const b = priorRow[x] ?? 0;
|
|
3025
|
+
const c = x >= bpp ? priorRow[x - bpp] ?? 0 : 0;
|
|
3026
|
+
let val = rawVal;
|
|
3027
|
+
if (filter === 0) {
|
|
3028
|
+
val = rawVal;
|
|
3029
|
+
} else if (filter === 1) {
|
|
3030
|
+
val = rawVal + a & 255;
|
|
3031
|
+
} else if (filter === 2) {
|
|
3032
|
+
val = rawVal + b & 255;
|
|
3033
|
+
} else if (filter === 3) {
|
|
3034
|
+
val = rawVal + Math.floor((a + b) / 2) & 255;
|
|
3035
|
+
} else if (filter === 4) {
|
|
3036
|
+
val = rawVal + paethPredictor(a, b, c) & 255;
|
|
3037
|
+
}
|
|
3038
|
+
currRow[x] = val;
|
|
3039
|
+
}
|
|
3040
|
+
for (let x = 0; x < width; x++) {
|
|
3041
|
+
const outIdx = (y * width + x) * 4;
|
|
3042
|
+
if (colorType === 6) {
|
|
3043
|
+
outRgba[outIdx] = currRow[x * 4] ?? 0;
|
|
3044
|
+
outRgba[outIdx + 1] = currRow[x * 4 + 1] ?? 0;
|
|
3045
|
+
outRgba[outIdx + 2] = currRow[x * 4 + 2] ?? 0;
|
|
3046
|
+
outRgba[outIdx + 3] = currRow[x * 4 + 3] ?? 255;
|
|
3047
|
+
} else if (colorType === 2) {
|
|
3048
|
+
outRgba[outIdx] = currRow[x * 3] ?? 0;
|
|
3049
|
+
outRgba[outIdx + 1] = currRow[x * 3 + 1] ?? 0;
|
|
3050
|
+
outRgba[outIdx + 2] = currRow[x * 3 + 2] ?? 0;
|
|
3051
|
+
outRgba[outIdx + 3] = 255;
|
|
3052
|
+
} else if (colorType === 0) {
|
|
3053
|
+
const g = currRow[x] ?? 0;
|
|
3054
|
+
outRgba[outIdx] = g;
|
|
3055
|
+
outRgba[outIdx + 1] = g;
|
|
3056
|
+
outRgba[outIdx + 2] = g;
|
|
3057
|
+
outRgba[outIdx + 3] = 255;
|
|
3058
|
+
} else if (colorType === 4) {
|
|
3059
|
+
const g = currRow[x * 2] ?? 0;
|
|
3060
|
+
outRgba[outIdx] = g;
|
|
3061
|
+
outRgba[outIdx + 1] = g;
|
|
3062
|
+
outRgba[outIdx + 2] = g;
|
|
3063
|
+
outRgba[outIdx + 3] = currRow[x * 2 + 1] ?? 255;
|
|
3064
|
+
} else if (colorType === 3 && palette) {
|
|
3065
|
+
const pVal = currRow[x] ?? 0;
|
|
3066
|
+
const pIdx = pVal * 3;
|
|
3067
|
+
outRgba[outIdx] = palette[pIdx] ?? 0;
|
|
3068
|
+
outRgba[outIdx + 1] = palette[pIdx + 1] ?? 0;
|
|
3069
|
+
outRgba[outIdx + 2] = palette[pIdx + 2] ?? 0;
|
|
3070
|
+
outRgba[outIdx + 3] = trns && trns.length > pVal ? trns[pVal] ?? 255 : 255;
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
currRow.copy(priorRow);
|
|
3074
|
+
}
|
|
3075
|
+
return { width, height, data: outRgba };
|
|
3076
|
+
}
|
|
3077
|
+
function makePngChunk(type, data) {
|
|
3078
|
+
const len = data.length;
|
|
3079
|
+
const chunk = Buffer.alloc(8 + len + 4);
|
|
3080
|
+
chunk.writeUInt32BE(len, 0);
|
|
3081
|
+
chunk.write(type, 4, 4, "ascii");
|
|
3082
|
+
Buffer.from(data.buffer, data.byteOffset, data.byteLength).copy(chunk, 8);
|
|
3083
|
+
const typeAndData = chunk.subarray(4, 8 + len);
|
|
3084
|
+
chunk.writeUInt32BE(crc32(typeAndData), 8 + len);
|
|
3085
|
+
return chunk;
|
|
3086
|
+
}
|
|
3087
|
+
function encodePng(width, height, rgba) {
|
|
3088
|
+
const ihdr = Buffer.alloc(13);
|
|
3089
|
+
ihdr.writeUInt32BE(width, 0);
|
|
3090
|
+
ihdr.writeUInt32BE(height, 4);
|
|
3091
|
+
ihdr[8] = 8;
|
|
3092
|
+
ihdr[9] = 6;
|
|
3093
|
+
ihdr[10] = 0;
|
|
3094
|
+
ihdr[11] = 0;
|
|
3095
|
+
ihdr[12] = 0;
|
|
3096
|
+
const rowSize = 1 + width * 4;
|
|
3097
|
+
const rawData = Buffer.alloc(rowSize * height);
|
|
3098
|
+
for (let y = 0; y < height; y++) {
|
|
3099
|
+
const rowOffset = y * rowSize;
|
|
3100
|
+
rawData[rowOffset] = 0;
|
|
3101
|
+
Buffer.from(rgba.buffer, rgba.byteOffset + y * width * 4, width * 4).copy(rawData, rowOffset + 1);
|
|
3102
|
+
}
|
|
3103
|
+
const idatData = zlib.deflateSync(rawData, { level: 6 });
|
|
3104
|
+
const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
3105
|
+
const ihdrChunk = makePngChunk("IHDR", ihdr);
|
|
3106
|
+
const idatChunk = makePngChunk("IDAT", idatData);
|
|
3107
|
+
const iendChunk = makePngChunk("IEND", Buffer.alloc(0));
|
|
3108
|
+
return Buffer.concat([signature, ihdrChunk, idatChunk, iendChunk]);
|
|
3109
|
+
}
|
|
3110
|
+
function decodeBmp(buf) {
|
|
3111
|
+
if (buf.length < 54 || buf[0] !== 66 || buf[1] !== 77) {
|
|
3112
|
+
throw new Error("Invalid BMP signature");
|
|
3113
|
+
}
|
|
3114
|
+
const pixelOffset = buf.readUInt32LE(10);
|
|
3115
|
+
const width = buf.readInt32LE(18);
|
|
3116
|
+
let height = buf.readInt32LE(22);
|
|
3117
|
+
const topDown = height < 0;
|
|
3118
|
+
height = Math.abs(height);
|
|
3119
|
+
const bpp = buf.readUInt16LE(28);
|
|
3120
|
+
const compression = buf.readUInt32LE(30);
|
|
3121
|
+
if (compression !== 0 && compression !== 3) {
|
|
3122
|
+
throw new Error("Unsupported BMP compression: " + compression);
|
|
3123
|
+
}
|
|
3124
|
+
if (bpp !== 24 && bpp !== 32) {
|
|
3125
|
+
throw new Error("Unsupported BMP bit depth: " + bpp);
|
|
3126
|
+
}
|
|
3127
|
+
assertDecodableSize("BMP", width, height, 4);
|
|
3128
|
+
const outRgba = Buffer.alloc(width * height * 4);
|
|
3129
|
+
const rowStride = Math.floor((bpp * width + 31) / 32) * 4;
|
|
3130
|
+
for (let y = 0; y < height; y++) {
|
|
3131
|
+
const srcY = topDown ? y : height - 1 - y;
|
|
3132
|
+
const rowOffset = pixelOffset + srcY * rowStride;
|
|
3133
|
+
for (let x = 0; x < width; x++) {
|
|
3134
|
+
const outIdx = (y * width + x) * 4;
|
|
3135
|
+
if (bpp === 24) {
|
|
3136
|
+
const pxOffset = rowOffset + x * 3;
|
|
3137
|
+
outRgba[outIdx] = buf[pxOffset + 2] ?? 0;
|
|
3138
|
+
outRgba[outIdx + 1] = buf[pxOffset + 1] ?? 0;
|
|
3139
|
+
outRgba[outIdx + 2] = buf[pxOffset] ?? 0;
|
|
3140
|
+
outRgba[outIdx + 3] = 255;
|
|
3141
|
+
} else if (bpp === 32) {
|
|
3142
|
+
const pxOffset = rowOffset + x * 4;
|
|
3143
|
+
outRgba[outIdx] = buf[pxOffset + 2] ?? 0;
|
|
3144
|
+
outRgba[outIdx + 1] = buf[pxOffset + 1] ?? 0;
|
|
3145
|
+
outRgba[outIdx + 2] = buf[pxOffset] ?? 0;
|
|
3146
|
+
outRgba[outIdx + 3] = buf[pxOffset + 3] ?? 255;
|
|
3147
|
+
}
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
return { width, height, data: outRgba };
|
|
3151
|
+
}
|
|
3152
|
+
function clearCanvasRect(canvas, canvasWidth, rect) {
|
|
3153
|
+
for (let row = 0; row < rect.height; row++) {
|
|
3154
|
+
const start = ((rect.y + row) * canvasWidth + rect.x) * 4;
|
|
3155
|
+
canvas.fill(0, start, start + rect.width * 4);
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
function decodeGif(buf, opts) {
|
|
3159
|
+
const reader = new import_omggif.default.GifReader(buf);
|
|
3160
|
+
const width = reader.width;
|
|
3161
|
+
const height = reader.height;
|
|
3162
|
+
const wanted = Math.min(reader.numFrames(), opts?.maxFrames ?? Number.POSITIVE_INFINITY);
|
|
3163
|
+
assertDecodableSize("GIF", width, height, 4, wanted);
|
|
3164
|
+
const frames = [];
|
|
3165
|
+
const canvas = Buffer.alloc(width * height * 4);
|
|
3166
|
+
let previous = null;
|
|
3167
|
+
let restore = null;
|
|
3168
|
+
for (let i = 0; i < wanted; i++) {
|
|
3169
|
+
if (previous?.disposal === 2) {
|
|
3170
|
+
clearCanvasRect(canvas, width, previous);
|
|
3171
|
+
} else if (previous?.disposal === 3 && restore) {
|
|
3172
|
+
restore.copy(canvas);
|
|
3173
|
+
}
|
|
3174
|
+
const frameInfo = reader.frameInfo(i);
|
|
3175
|
+
restore = frameInfo.disposal === 3 ? Buffer.from(canvas) : null;
|
|
3176
|
+
reader.decodeAndBlitFrameRGBA(i, canvas);
|
|
3177
|
+
previous = { x: frameInfo.x, y: frameInfo.y, width: frameInfo.width, height: frameInfo.height, disposal: frameInfo.disposal };
|
|
3178
|
+
frames.push({
|
|
3179
|
+
width,
|
|
3180
|
+
height,
|
|
3181
|
+
x: frameInfo.x,
|
|
3182
|
+
y: frameInfo.y,
|
|
3183
|
+
delay: frameInfo.delay,
|
|
3184
|
+
disposal: frameInfo.disposal,
|
|
3185
|
+
// A copy: pushing the canvas itself would alias every frame to the last one composited.
|
|
3186
|
+
data: Buffer.from(canvas)
|
|
3187
|
+
});
|
|
3188
|
+
}
|
|
3189
|
+
return { width, height, frames };
|
|
3190
|
+
}
|
|
3191
|
+
var GIF_WEB_PALETTE = (() => {
|
|
3192
|
+
const palette = [];
|
|
3193
|
+
for (let r = 0; r < 8; r++) {
|
|
3194
|
+
for (let g = 0; g < 8; g++) {
|
|
3195
|
+
for (let b = 0; b < 4; b++) {
|
|
3196
|
+
palette.push(Math.round(r / 7 * 255) << 16 | Math.round(g / 7 * 255) << 8 | Math.round(b / 3 * 255));
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
return palette;
|
|
3201
|
+
})();
|
|
3202
|
+
function quantizeRgbaToIndexed(rgba, width, height) {
|
|
3203
|
+
const palette = GIF_WEB_PALETTE;
|
|
3204
|
+
const numPixels = width * height;
|
|
3205
|
+
let transparentIndex = null;
|
|
3206
|
+
for (let i = 0; i < numPixels; i++) {
|
|
3207
|
+
if ((rgba[i * 4 + 3] ?? 255) < 128) {
|
|
3208
|
+
transparentIndex = 0;
|
|
3209
|
+
break;
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
const indexedPixels = new Array(numPixels);
|
|
3213
|
+
for (let i = 0; i < numPixels; i++) {
|
|
3214
|
+
if (transparentIndex !== null && (rgba[i * 4 + 3] ?? 255) < 128) {
|
|
3215
|
+
indexedPixels[i] = transparentIndex;
|
|
3216
|
+
continue;
|
|
3217
|
+
}
|
|
3218
|
+
const r = rgba[i * 4] ?? 0;
|
|
3219
|
+
const g = rgba[i * 4 + 1] ?? 0;
|
|
3220
|
+
const b = rgba[i * 4 + 2] ?? 0;
|
|
3221
|
+
const rIdx = Math.min(7, Math.floor(r / 256 * 8));
|
|
3222
|
+
const gIdx = Math.min(7, Math.floor(g / 256 * 8));
|
|
3223
|
+
const bIdx = Math.min(3, Math.floor(b / 256 * 4));
|
|
3224
|
+
const idx = rIdx << 5 | gIdx << 2 | bIdx;
|
|
3225
|
+
indexedPixels[i] = transparentIndex !== null && idx === transparentIndex ? 1 : idx;
|
|
3226
|
+
}
|
|
3227
|
+
return { indexedPixels, palette, transparentIndex };
|
|
3228
|
+
}
|
|
3229
|
+
function decodeJpeg(buf) {
|
|
3230
|
+
const decoded = import_jpeg_js.default.decode(buf, {
|
|
3231
|
+
useTArray: true,
|
|
3232
|
+
maxResolutionInMP: MAX_DECODED_BYTES / 4 / 1e6,
|
|
3233
|
+
maxMemoryUsageInMB: 512
|
|
3234
|
+
});
|
|
3235
|
+
return {
|
|
3236
|
+
width: decoded.width,
|
|
3237
|
+
height: decoded.height,
|
|
3238
|
+
data: Buffer.from(decoded.data)
|
|
3239
|
+
};
|
|
3240
|
+
}
|
|
3241
|
+
function encodeJpeg(width, height, rgba, quality = 80) {
|
|
3242
|
+
const encoded = import_jpeg_js.default.encode({
|
|
3243
|
+
data: Buffer.from(rgba.buffer, rgba.byteOffset, rgba.byteLength),
|
|
3244
|
+
width,
|
|
3245
|
+
height
|
|
3246
|
+
}, quality);
|
|
3247
|
+
return encoded.data;
|
|
3248
|
+
}
|
|
3249
|
+
var ORIENTATION_MAPS = [
|
|
3250
|
+
[-1, 0, 1, 0, 1, 0],
|
|
3251
|
+
[-1, 0, 1, 0, -1, 1],
|
|
3252
|
+
[1, 0, 0, 0, -1, 1],
|
|
3253
|
+
[0, 1, 0, 1, 0, 0],
|
|
3254
|
+
[0, 1, 0, -1, 0, 1],
|
|
3255
|
+
[0, -1, 1, -1, 0, 1],
|
|
3256
|
+
[0, -1, 1, 1, 0, 0]
|
|
3257
|
+
];
|
|
3258
|
+
function applyExifOrientation(rgba, width, height, orientation) {
|
|
3259
|
+
if (orientation === void 0 || orientation < 2 || orientation > 8) {
|
|
3260
|
+
return { data: rgba, width, height };
|
|
3261
|
+
}
|
|
3262
|
+
const map = ORIENTATION_MAPS[orientation - 2];
|
|
3263
|
+
if (map === void 0) return { data: rgba, width, height };
|
|
3264
|
+
const [a, b, cW, d, e, fH] = map;
|
|
3265
|
+
const transposed = orientation >= 5;
|
|
3266
|
+
const dstW = transposed ? height : width;
|
|
3267
|
+
const dstH = transposed ? width : height;
|
|
3268
|
+
const dst = Buffer.alloc(dstW * dstH * 4);
|
|
3269
|
+
for (let dy = 0; dy < dstH; dy++) {
|
|
3270
|
+
const sxRow = b * dy + cW * (width - 1);
|
|
3271
|
+
const syRow = e * dy + fH * (height - 1);
|
|
3272
|
+
for (let dx = 0; dx < dstW; dx++) {
|
|
3273
|
+
const si = ((d * dx + syRow) * width + (a * dx + sxRow)) * 4;
|
|
3274
|
+
const di = (dy * dstW + dx) * 4;
|
|
3275
|
+
dst[di] = rgba[si];
|
|
3276
|
+
dst[di + 1] = rgba[si + 1];
|
|
3277
|
+
dst[di + 2] = rgba[si + 2];
|
|
3278
|
+
dst[di + 3] = rgba[si + 3];
|
|
3279
|
+
}
|
|
3280
|
+
}
|
|
3281
|
+
return { data: dst, width: dstW, height: dstH };
|
|
3282
|
+
}
|
|
3283
|
+
function resizeRgba(srcRgba, srcW, srcH, dstW, dstH) {
|
|
3284
|
+
if (srcW === dstW && srcH === dstH) {
|
|
3285
|
+
return Buffer.from(srcRgba.buffer, srcRgba.byteOffset, srcRgba.byteLength);
|
|
3286
|
+
}
|
|
3287
|
+
const dst = Buffer.alloc(dstW * dstH * 4);
|
|
3288
|
+
const scaleX = srcW / dstW;
|
|
3289
|
+
const scaleY = srcH / dstH;
|
|
3290
|
+
for (let dy = 0; dy < dstH; dy++) {
|
|
3291
|
+
const srcY = (dy + 0.5) * scaleY - 0.5;
|
|
3292
|
+
const y0 = Math.max(0, Math.min(srcH - 1, Math.floor(srcY)));
|
|
3293
|
+
const y1 = Math.max(0, Math.min(srcH - 1, y0 + 1));
|
|
3294
|
+
const fy = Math.max(0, Math.min(1, srcY - y0));
|
|
3295
|
+
const fy1 = 1 - fy;
|
|
3296
|
+
const dstRowOffset = dy * dstW * 4;
|
|
3297
|
+
const srcRow0 = y0 * srcW * 4;
|
|
3298
|
+
const srcRow1 = y1 * srcW * 4;
|
|
3299
|
+
for (let dx = 0; dx < dstW; dx++) {
|
|
3300
|
+
const srcX = (dx + 0.5) * scaleX - 0.5;
|
|
3301
|
+
const x0 = Math.max(0, Math.min(srcW - 1, Math.floor(srcX)));
|
|
3302
|
+
const x1 = Math.max(0, Math.min(srcW - 1, x0 + 1));
|
|
3303
|
+
const fx = Math.max(0, Math.min(1, srcX - x0));
|
|
3304
|
+
const fx1 = 1 - fx;
|
|
3305
|
+
const w00 = fx1 * fy1;
|
|
3306
|
+
const w10 = fx * fy1;
|
|
3307
|
+
const w01 = fx1 * fy;
|
|
3308
|
+
const w11 = fx * fy;
|
|
3309
|
+
const idx00 = srcRow0 + x0 * 4;
|
|
3310
|
+
const idx10 = srcRow0 + x1 * 4;
|
|
3311
|
+
const idx01 = srcRow1 + x0 * 4;
|
|
3312
|
+
const idx11 = srcRow1 + x1 * 4;
|
|
3313
|
+
const p00_r = srcRgba[idx00] ?? 0;
|
|
3314
|
+
const p00_g = srcRgba[idx00 + 1] ?? 0;
|
|
3315
|
+
const p00_b = srcRgba[idx00 + 2] ?? 0;
|
|
3316
|
+
const p00_a = srcRgba[idx00 + 3] ?? 255;
|
|
3317
|
+
const p10_r = srcRgba[idx10] ?? 0;
|
|
3318
|
+
const p10_g = srcRgba[idx10 + 1] ?? 0;
|
|
3319
|
+
const p10_b = srcRgba[idx10 + 2] ?? 0;
|
|
3320
|
+
const p10_a = srcRgba[idx10 + 3] ?? 255;
|
|
3321
|
+
const p01_r = srcRgba[idx01] ?? 0;
|
|
3322
|
+
const p01_g = srcRgba[idx01 + 1] ?? 0;
|
|
3323
|
+
const p01_b = srcRgba[idx01 + 2] ?? 0;
|
|
3324
|
+
const p01_a = srcRgba[idx01 + 3] ?? 255;
|
|
3325
|
+
const p11_r = srcRgba[idx11] ?? 0;
|
|
3326
|
+
const p11_g = srcRgba[idx11 + 1] ?? 0;
|
|
3327
|
+
const p11_b = srcRgba[idx11 + 2] ?? 0;
|
|
3328
|
+
const p11_a = srcRgba[idx11 + 3] ?? 255;
|
|
3329
|
+
const dstIdx = dstRowOffset + dx * 4;
|
|
3330
|
+
dst[dstIdx] = Math.round(w00 * p00_r + w10 * p10_r + w01 * p01_r + w11 * p11_r);
|
|
3331
|
+
dst[dstIdx + 1] = Math.round(w00 * p00_g + w10 * p10_g + w01 * p01_g + w11 * p11_g);
|
|
3332
|
+
dst[dstIdx + 2] = Math.round(w00 * p00_b + w10 * p10_b + w01 * p01_b + w11 * p11_b);
|
|
3333
|
+
dst[dstIdx + 3] = Math.round(w00 * p00_a + w10 * p10_a + w01 * p01_a + w11 * p11_a);
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
return dst;
|
|
3337
|
+
}
|
|
3338
|
+
function calculateFitInside(width, height, maxDimension) {
|
|
3339
|
+
if (width <= maxDimension && height <= maxDimension) {
|
|
3340
|
+
return { width, height };
|
|
3341
|
+
}
|
|
3342
|
+
const scale = maxDimension / Math.max(width, height);
|
|
3343
|
+
return {
|
|
3344
|
+
width: Math.max(1, Math.round(width * scale)),
|
|
3345
|
+
height: Math.max(1, Math.round(height * scale))
|
|
3346
|
+
};
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
export {
|
|
3350
|
+
require_omggif,
|
|
3351
|
+
assertDecodableSize,
|
|
3352
|
+
probeBufferMeta,
|
|
3353
|
+
decodePng,
|
|
3354
|
+
encodePng,
|
|
3355
|
+
decodeBmp,
|
|
3356
|
+
decodeGif,
|
|
3357
|
+
GIF_WEB_PALETTE,
|
|
3358
|
+
quantizeRgbaToIndexed,
|
|
3359
|
+
decodeJpeg,
|
|
3360
|
+
encodeJpeg,
|
|
3361
|
+
applyExifOrientation,
|
|
3362
|
+
resizeRgba,
|
|
3363
|
+
calculateFitInside
|
|
3364
|
+
};
|