ag-psd 30.1.1 → 30.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.v8-cache/v24.13.1-x64-cf738c9d/017325ac +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/043c7b90 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/05135617 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/059f8558 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0706ecb8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0db754a7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1130885f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/15f0e479 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/20477c23 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/20dfa422 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2a19133e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2b069ee0 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2de09439 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2e44f5f0 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2fb229a9 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/3144b401 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/37481985 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4511bacf +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/49d22b79 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4f5702bd +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/514cc428 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/57d3380b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6024ce3f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/61735b23 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/63dbdb75 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6cbfc0ec +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6f08372c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7100ee08 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/71df9cb3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/75e41e43 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7ea06cea +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/8568576b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/87372817 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/87cf2209 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/932f0770 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/a79a40bb +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/a7e80865 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/acc36e66 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b3c2fab7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b69ed3a3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/bdff1628 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c0b789d2 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c314aece +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cfc49f4f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cff9434a +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/d02dd6f7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/dc86f000 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/de74e659 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e03e2acd +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e158d332 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6735171 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6745c2b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6b99945 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/eeeebdfe +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fbca6276 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fc97d72d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fd0a2987 +0 -0
- package/CHANGELOG.md +3 -0
- package/README.md +1 -1
- package/README_PSD.md +1 -1
- package/dist/abr.js +43 -56
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.js +770 -808
- package/dist/additionalInfo.js.map +1 -1
- package/dist/ase.js +21 -21
- package/dist/ase.js.map +1 -1
- package/dist/bundle.js +2592 -2778
- package/dist/csh.js +18 -29
- package/dist/csh.js.map +1 -1
- package/dist/descriptor.js +234 -269
- package/dist/descriptor.js.map +1 -1
- package/dist/effectsHelpers.js +91 -112
- package/dist/effectsHelpers.js.map +1 -1
- package/dist/engineData.js +45 -51
- package/dist/engineData.js.map +1 -1
- package/dist/engineData2.js +8 -9
- package/dist/engineData2.js.map +1 -1
- package/dist/helpers.js +75 -81
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.js +342 -381
- package/dist/imageResources.js.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/dist/initializeCanvas.js +2 -2
- package/dist/initializeCanvas.js.map +1 -1
- package/dist/jpeg.js +279 -279
- package/dist/jpeg.js.map +1 -1
- package/dist/psdReader.js +336 -347
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +2 -1
- package/dist/psdWriter.js +225 -206
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.js +98 -122
- package/dist/text.js.map +1 -1
- package/dist/utf8.js +22 -22
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.js +41 -54
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.js +765 -803
- package/dist-es/additionalInfo.js.map +1 -1
- package/dist-es/ase.js +20 -20
- package/dist-es/ase.js.map +1 -1
- package/dist-es/csh.js +16 -27
- package/dist-es/csh.js.map +1 -1
- package/dist-es/descriptor.js +284 -319
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/effectsHelpers.js +88 -109
- package/dist-es/effectsHelpers.js.map +1 -1
- package/dist-es/engineData.js +45 -51
- package/dist-es/engineData.js.map +1 -1
- package/dist-es/engineData2.js +8 -9
- package/dist-es/engineData2.js.map +1 -1
- package/dist-es/helpers.js +79 -85
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.js +338 -377
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/index.js +4 -4
- package/dist-es/index.js.map +1 -1
- package/dist-es/jpeg.js +279 -279
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psdReader.js +333 -344
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +2 -1
- package/dist-es/psdWriter.js +220 -202
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.js +98 -122
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.js +22 -22
- package/dist-es/utf8.js.map +1 -1
- package/package.json +1 -1
- package/publish.js +24 -0
- package/src/additionalInfo.ts +15 -11
- package/src/psdWriter.ts +76 -1
- package/tsconfig.json +4 -3
package/dist/jpeg.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.decodeJpeg = void 0;
|
|
20
|
-
|
|
20
|
+
const dctZigZag = new Int32Array([
|
|
21
21
|
0,
|
|
22
22
|
1, 8,
|
|
23
23
|
16, 9, 2,
|
|
@@ -34,34 +34,34 @@ var dctZigZag = new Int32Array([
|
|
|
34
34
|
55, 62,
|
|
35
35
|
63
|
|
36
36
|
]);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
const dctCos1 = 4017; // cos(pi/16)
|
|
38
|
+
const dctSin1 = 799; // sin(pi/16)
|
|
39
|
+
const dctCos3 = 3406; // cos(3*pi/16)
|
|
40
|
+
const dctSin3 = 2276; // sin(3*pi/16)
|
|
41
|
+
const dctCos6 = 1567; // cos(6*pi/16)
|
|
42
|
+
const dctSin6 = 3784; // sin(6*pi/16)
|
|
43
|
+
const dctSqrt2 = 5793; // sqrt(2)
|
|
44
|
+
const dctSqrt1d2 = 2896; // sqrt(2) / 2
|
|
45
|
+
const maxResolutionInMP = 100; // Don't decode more than 100 megapixels
|
|
46
|
+
const maxMemoryUsageBytes = 64 * 1024 * 1024; // Don't decode if memory footprint is more than 64MB
|
|
47
|
+
let totalBytesAllocated = 0; // avoid unexpected OOMs from untrusted content.
|
|
48
48
|
function requestMemoryAllocation(increaseAmount) {
|
|
49
|
-
|
|
49
|
+
const totalMemoryImpactBytes = totalBytesAllocated + increaseAmount;
|
|
50
50
|
if (totalMemoryImpactBytes > maxMemoryUsageBytes) {
|
|
51
|
-
|
|
52
|
-
throw new Error(
|
|
51
|
+
const exceededAmount = Math.ceil((totalMemoryImpactBytes - maxMemoryUsageBytes) / 1024 / 1024);
|
|
52
|
+
throw new Error(`Max memory limit exceeded by at least ${exceededAmount}MB`);
|
|
53
53
|
}
|
|
54
54
|
totalBytesAllocated = totalMemoryImpactBytes;
|
|
55
55
|
}
|
|
56
56
|
function buildHuffmanTable(codeLengths, values) {
|
|
57
|
-
|
|
57
|
+
let length = 16;
|
|
58
58
|
while (length > 0 && !codeLengths[length - 1])
|
|
59
59
|
length--;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
for (
|
|
64
|
-
for (
|
|
60
|
+
const code = [{ children: [], index: 0 }];
|
|
61
|
+
let k = 0;
|
|
62
|
+
let p = code[0];
|
|
63
|
+
for (let i = 0; i < length; i++) {
|
|
64
|
+
for (let j = 0; j < codeLengths[i]; j++) {
|
|
65
65
|
p = code.pop();
|
|
66
66
|
p.children[p.index] = values[k];
|
|
67
67
|
while (p.index > 0) {
|
|
@@ -72,7 +72,7 @@ function buildHuffmanTable(codeLengths, values) {
|
|
|
72
72
|
p.index++;
|
|
73
73
|
code.push(p);
|
|
74
74
|
while (code.length <= i) {
|
|
75
|
-
|
|
75
|
+
const q = { children: [], index: 0 };
|
|
76
76
|
code.push(q);
|
|
77
77
|
p.children[p.index] = q.children;
|
|
78
78
|
p = q;
|
|
@@ -81,7 +81,7 @@ function buildHuffmanTable(codeLengths, values) {
|
|
|
81
81
|
}
|
|
82
82
|
if (i + 1 < length) {
|
|
83
83
|
// p here points to last code
|
|
84
|
-
|
|
84
|
+
const q = { children: [], index: 0 };
|
|
85
85
|
code.push(q);
|
|
86
86
|
p.children[p.index] = q.children;
|
|
87
87
|
p = q;
|
|
@@ -90,11 +90,11 @@ function buildHuffmanTable(codeLengths, values) {
|
|
|
90
90
|
return code[0].children;
|
|
91
91
|
}
|
|
92
92
|
function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
const mcusPerLine = frame.mcusPerLine;
|
|
94
|
+
const progressive = frame.progressive;
|
|
95
|
+
const startOffset = offset;
|
|
96
|
+
let bitsData = 0;
|
|
97
|
+
let bitsCount = 0;
|
|
98
98
|
function readBit() {
|
|
99
99
|
if (bitsCount > 0) {
|
|
100
100
|
bitsCount--;
|
|
@@ -102,16 +102,16 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
102
102
|
}
|
|
103
103
|
bitsData = data[offset++];
|
|
104
104
|
if (bitsData == 0xFF) {
|
|
105
|
-
|
|
105
|
+
const nextByte = data[offset++];
|
|
106
106
|
if (nextByte)
|
|
107
|
-
throw new Error(
|
|
107
|
+
throw new Error(`unexpected marker: ${((bitsData << 8) | nextByte).toString(16)}`);
|
|
108
108
|
// unstuff 0
|
|
109
109
|
}
|
|
110
110
|
bitsCount = 7;
|
|
111
111
|
return bitsData >>> 7;
|
|
112
112
|
}
|
|
113
113
|
function decodeHuffman(tree) {
|
|
114
|
-
|
|
114
|
+
let node = tree;
|
|
115
115
|
while (true) {
|
|
116
116
|
node = node[readBit()];
|
|
117
117
|
if (typeof node === 'number')
|
|
@@ -121,7 +121,7 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
function receive(length) {
|
|
124
|
-
|
|
124
|
+
let n = 0;
|
|
125
125
|
while (length > 0) {
|
|
126
126
|
n = (n << 1) | readBit();
|
|
127
127
|
length--;
|
|
@@ -129,20 +129,20 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
129
129
|
return n;
|
|
130
130
|
}
|
|
131
131
|
function receiveAndExtend(length) {
|
|
132
|
-
|
|
132
|
+
let n = receive(length);
|
|
133
133
|
if (n >= 1 << (length - 1))
|
|
134
134
|
return n;
|
|
135
135
|
return n + (-1 << length) + 1;
|
|
136
136
|
}
|
|
137
137
|
function decodeBaseline(component, zz) {
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
const t = decodeHuffman(component.huffmanTableDC);
|
|
139
|
+
const diff = t === 0 ? 0 : receiveAndExtend(t);
|
|
140
140
|
zz[0] = (component.pred += diff);
|
|
141
|
-
|
|
141
|
+
let k = 1;
|
|
142
142
|
while (k < 64) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
const rs = decodeHuffman(component.huffmanTableAC);
|
|
144
|
+
const s = rs & 15;
|
|
145
|
+
const r = rs >> 4;
|
|
146
146
|
if (s === 0) {
|
|
147
147
|
if (r < 15)
|
|
148
148
|
break;
|
|
@@ -150,30 +150,30 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
150
150
|
continue;
|
|
151
151
|
}
|
|
152
152
|
k += r;
|
|
153
|
-
|
|
153
|
+
const z = dctZigZag[k];
|
|
154
154
|
zz[z] = receiveAndExtend(s);
|
|
155
155
|
k++;
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
function decodeDCFirst(component, zz) {
|
|
159
|
-
|
|
160
|
-
|
|
159
|
+
const t = decodeHuffman(component.huffmanTableDC);
|
|
160
|
+
const diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
|
|
161
161
|
zz[0] = (component.pred += diff);
|
|
162
162
|
}
|
|
163
163
|
function decodeDCSuccessive(_component, zz) {
|
|
164
164
|
zz[0] |= readBit() << successive;
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
let eobrun = 0;
|
|
167
167
|
function decodeACFirst(component, zz) {
|
|
168
168
|
if (eobrun > 0) {
|
|
169
169
|
eobrun--;
|
|
170
170
|
return;
|
|
171
171
|
}
|
|
172
|
-
|
|
172
|
+
let k = spectralStart, e = spectralEnd;
|
|
173
173
|
while (k <= e) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
const rs = decodeHuffman(component.huffmanTableAC);
|
|
175
|
+
const s = rs & 15;
|
|
176
|
+
const r = rs >> 4;
|
|
177
177
|
if (s === 0) {
|
|
178
178
|
if (r < 15) {
|
|
179
179
|
eobrun = receive(r) + (1 << r) - 1;
|
|
@@ -183,24 +183,24 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
183
183
|
continue;
|
|
184
184
|
}
|
|
185
185
|
k += r;
|
|
186
|
-
|
|
186
|
+
const z = dctZigZag[k];
|
|
187
187
|
zz[z] = receiveAndExtend(s) * (1 << successive);
|
|
188
188
|
k++;
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
|
|
192
|
-
|
|
191
|
+
let successiveACState = 0;
|
|
192
|
+
let successiveACNextValue = 0;
|
|
193
193
|
function decodeACSuccessive(component, zz) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
let k = spectralStart;
|
|
195
|
+
let e = spectralEnd;
|
|
196
|
+
let r = 0;
|
|
197
197
|
while (k <= e) {
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
const z = dctZigZag[k];
|
|
199
|
+
const direction = zz[z] < 0 ? -1 : 1;
|
|
200
200
|
switch (successiveACState) {
|
|
201
201
|
case 0: // initial state
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
const rs = decodeHuffman(component.huffmanTableAC);
|
|
203
|
+
const s = rs & 15;
|
|
204
204
|
r = rs >> 4; // this was new variable in old code
|
|
205
205
|
if (s === 0) {
|
|
206
206
|
if (r < 15) {
|
|
@@ -254,26 +254,26 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
function decodeMcu(component, decode, mcu, row, col) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
257
|
+
const mcuRow = (mcu / mcusPerLine) | 0;
|
|
258
|
+
const mcuCol = mcu % mcusPerLine;
|
|
259
|
+
const blockRow = mcuRow * component.v + row;
|
|
260
|
+
const blockCol = mcuCol * component.h + col;
|
|
261
261
|
// If the block is missing, just skip it.
|
|
262
262
|
if (component.blocks[blockRow] === undefined)
|
|
263
263
|
return;
|
|
264
264
|
decode(component, component.blocks[blockRow][blockCol]);
|
|
265
265
|
}
|
|
266
266
|
function decodeBlock(component, decode, mcu) {
|
|
267
|
-
|
|
268
|
-
|
|
267
|
+
const blockRow = (mcu / component.blocksPerLine) | 0;
|
|
268
|
+
const blockCol = mcu % component.blocksPerLine;
|
|
269
269
|
// If the block is missing, just skip it.
|
|
270
270
|
if (component.blocks[blockRow] === undefined)
|
|
271
271
|
return;
|
|
272
272
|
decode(component, component.blocks[blockRow][blockCol]);
|
|
273
273
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
274
|
+
const componentsLength = components.length;
|
|
275
|
+
let component;
|
|
276
|
+
let decodeFn;
|
|
277
277
|
if (progressive) {
|
|
278
278
|
if (spectralStart === 0) {
|
|
279
279
|
decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
|
|
@@ -285,8 +285,8 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
285
285
|
else {
|
|
286
286
|
decodeFn = decodeBaseline;
|
|
287
287
|
}
|
|
288
|
-
|
|
289
|
-
|
|
288
|
+
let mcu = 0;
|
|
289
|
+
let mcuExpected;
|
|
290
290
|
if (componentsLength == 1) {
|
|
291
291
|
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
|
292
292
|
}
|
|
@@ -295,29 +295,29 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
295
295
|
}
|
|
296
296
|
if (!resetInterval)
|
|
297
297
|
resetInterval = mcuExpected;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
298
|
+
let h;
|
|
299
|
+
let v;
|
|
300
|
+
let marker;
|
|
301
301
|
while (mcu < mcuExpected) {
|
|
302
302
|
// reset interval stuff
|
|
303
|
-
for (
|
|
303
|
+
for (let i = 0; i < componentsLength; i++)
|
|
304
304
|
components[i].pred = 0;
|
|
305
305
|
eobrun = 0;
|
|
306
306
|
if (componentsLength == 1) {
|
|
307
307
|
component = components[0];
|
|
308
|
-
for (
|
|
308
|
+
for (let n = 0; n < resetInterval; n++) {
|
|
309
309
|
decodeBlock(component, decodeFn, mcu);
|
|
310
310
|
mcu++;
|
|
311
311
|
}
|
|
312
312
|
}
|
|
313
313
|
else {
|
|
314
|
-
for (
|
|
315
|
-
for (
|
|
314
|
+
for (let n = 0; n < resetInterval; n++) {
|
|
315
|
+
for (let i = 0; i < componentsLength; i++) {
|
|
316
316
|
component = components[i];
|
|
317
317
|
h = component.h;
|
|
318
318
|
v = component.v;
|
|
319
|
-
for (
|
|
320
|
-
for (
|
|
319
|
+
for (let j = 0; j < v; j++) {
|
|
320
|
+
for (let k = 0; k < h; k++) {
|
|
321
321
|
decodeMcu(component, decodeFn, mcu, j, k);
|
|
322
322
|
}
|
|
323
323
|
}
|
|
@@ -354,54 +354,54 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
354
354
|
return offset - startOffset;
|
|
355
355
|
}
|
|
356
356
|
function buildComponentData(component) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
357
|
+
const lines = [];
|
|
358
|
+
const blocksPerLine = component.blocksPerLine;
|
|
359
|
+
const blocksPerColumn = component.blocksPerColumn;
|
|
360
|
+
const samplesPerLine = blocksPerLine << 3;
|
|
361
361
|
// Only 1 used per invocation of this function and garbage collected after invocation, so no need to account for its memory footprint.
|
|
362
|
-
|
|
363
|
-
|
|
362
|
+
const R = new Int32Array(64);
|
|
363
|
+
const r = new Uint8Array(64);
|
|
364
364
|
// A port of poppler's IDCT method which in turn is taken from:
|
|
365
365
|
// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
|
|
366
366
|
// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
|
|
367
367
|
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
|
368
368
|
// 988-991.
|
|
369
369
|
function quantizeAndInverse(zz, dataOut, dataIn) {
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
const qt = component.quantizationTable;
|
|
371
|
+
const p = dataIn;
|
|
372
372
|
// dequant
|
|
373
|
-
for (
|
|
373
|
+
for (let i = 0; i < 64; i++) {
|
|
374
374
|
p[i] = zz[i] * qt[i];
|
|
375
375
|
}
|
|
376
376
|
// inverse DCT on rows
|
|
377
|
-
for (
|
|
378
|
-
|
|
377
|
+
for (let i = 0; i < 8; ++i) {
|
|
378
|
+
const row = 8 * i;
|
|
379
379
|
// check for all-zero AC coefficients
|
|
380
380
|
if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
|
|
381
381
|
p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
|
|
382
382
|
p[7 + row] == 0) {
|
|
383
|
-
|
|
384
|
-
p[0 + row] =
|
|
385
|
-
p[1 + row] =
|
|
386
|
-
p[2 + row] =
|
|
387
|
-
p[3 + row] =
|
|
388
|
-
p[4 + row] =
|
|
389
|
-
p[5 + row] =
|
|
390
|
-
p[6 + row] =
|
|
391
|
-
p[7 + row] =
|
|
383
|
+
const t = (dctSqrt2 * p[0 + row] + 512) >> 10;
|
|
384
|
+
p[0 + row] = t;
|
|
385
|
+
p[1 + row] = t;
|
|
386
|
+
p[2 + row] = t;
|
|
387
|
+
p[3 + row] = t;
|
|
388
|
+
p[4 + row] = t;
|
|
389
|
+
p[5 + row] = t;
|
|
390
|
+
p[6 + row] = t;
|
|
391
|
+
p[7 + row] = t;
|
|
392
392
|
continue;
|
|
393
393
|
}
|
|
394
394
|
// stage 4
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
395
|
+
let v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
|
|
396
|
+
let v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
|
|
397
|
+
let v2 = p[2 + row];
|
|
398
|
+
let v3 = p[6 + row];
|
|
399
|
+
let v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
|
|
400
|
+
let v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
|
|
401
|
+
let v5 = p[3 + row] << 4;
|
|
402
|
+
let v6 = p[5 + row] << 4;
|
|
403
403
|
// stage 3
|
|
404
|
-
|
|
404
|
+
let t = (v0 - v1 + 1) >> 1;
|
|
405
405
|
v0 = (v0 + v1 + 1) >> 1;
|
|
406
406
|
v1 = t;
|
|
407
407
|
t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
|
|
@@ -437,34 +437,34 @@ function buildComponentData(component) {
|
|
|
437
437
|
p[4 + row] = v3 - v4;
|
|
438
438
|
}
|
|
439
439
|
// inverse DCT on columns
|
|
440
|
-
for (
|
|
441
|
-
|
|
440
|
+
for (let i = 0; i < 8; ++i) {
|
|
441
|
+
const col = i;
|
|
442
442
|
// check for all-zero AC coefficients
|
|
443
443
|
if (p[1 * 8 + col] == 0 && p[2 * 8 + col] == 0 && p[3 * 8 + col] == 0 &&
|
|
444
444
|
p[4 * 8 + col] == 0 && p[5 * 8 + col] == 0 && p[6 * 8 + col] == 0 &&
|
|
445
445
|
p[7 * 8 + col] == 0) {
|
|
446
|
-
|
|
447
|
-
p[0 * 8 + col] =
|
|
448
|
-
p[1 * 8 + col] =
|
|
449
|
-
p[2 * 8 + col] =
|
|
450
|
-
p[3 * 8 + col] =
|
|
451
|
-
p[4 * 8 + col] =
|
|
452
|
-
p[5 * 8 + col] =
|
|
453
|
-
p[6 * 8 + col] =
|
|
454
|
-
p[7 * 8 + col] =
|
|
446
|
+
const t = (dctSqrt2 * dataIn[i + 0] + 8192) >> 14;
|
|
447
|
+
p[0 * 8 + col] = t;
|
|
448
|
+
p[1 * 8 + col] = t;
|
|
449
|
+
p[2 * 8 + col] = t;
|
|
450
|
+
p[3 * 8 + col] = t;
|
|
451
|
+
p[4 * 8 + col] = t;
|
|
452
|
+
p[5 * 8 + col] = t;
|
|
453
|
+
p[6 * 8 + col] = t;
|
|
454
|
+
p[7 * 8 + col] = t;
|
|
455
455
|
continue;
|
|
456
456
|
}
|
|
457
457
|
// stage 4
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
458
|
+
let v0 = (dctSqrt2 * p[0 * 8 + col] + 2048) >> 12;
|
|
459
|
+
let v1 = (dctSqrt2 * p[4 * 8 + col] + 2048) >> 12;
|
|
460
|
+
let v2 = p[2 * 8 + col];
|
|
461
|
+
let v3 = p[6 * 8 + col];
|
|
462
|
+
let v4 = (dctSqrt1d2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048) >> 12;
|
|
463
|
+
let v7 = (dctSqrt1d2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048) >> 12;
|
|
464
|
+
let v5 = p[3 * 8 + col];
|
|
465
|
+
let v6 = p[5 * 8 + col];
|
|
466
466
|
// stage 3
|
|
467
|
-
|
|
467
|
+
let t = (v0 - v1 + 1) >> 1;
|
|
468
468
|
v0 = (v0 + v1 + 1) >> 1;
|
|
469
469
|
v1 = t;
|
|
470
470
|
t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
|
|
@@ -500,23 +500,23 @@ function buildComponentData(component) {
|
|
|
500
500
|
p[4 * 8 + col] = v3 - v4;
|
|
501
501
|
}
|
|
502
502
|
// convert to 8-bit integers
|
|
503
|
-
for (
|
|
504
|
-
|
|
503
|
+
for (let i = 0; i < 64; ++i) {
|
|
504
|
+
const sample = 128 + ((p[i] + 8) >> 4);
|
|
505
505
|
dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample;
|
|
506
506
|
}
|
|
507
507
|
}
|
|
508
508
|
requestMemoryAllocation(samplesPerLine * blocksPerColumn * 8);
|
|
509
|
-
for (
|
|
510
|
-
|
|
511
|
-
for (
|
|
509
|
+
for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
|
|
510
|
+
const scanLine = blockRow << 3;
|
|
511
|
+
for (let i = 0; i < 8; i++)
|
|
512
512
|
lines.push(new Uint8Array(samplesPerLine));
|
|
513
|
-
for (
|
|
513
|
+
for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
|
514
514
|
quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
for (
|
|
518
|
-
|
|
519
|
-
for (
|
|
515
|
+
let offset = 0;
|
|
516
|
+
const sample = blockCol << 3;
|
|
517
|
+
for (let j = 0; j < 8; j++) {
|
|
518
|
+
const line = lines[scanLine + j];
|
|
519
|
+
for (let i = 0; i < 8; i++)
|
|
520
520
|
line[sample + i] = r[offset++];
|
|
521
521
|
}
|
|
522
522
|
}
|
|
@@ -527,7 +527,7 @@ function clampTo8bit(a) {
|
|
|
527
527
|
return a < 0 ? 0 : a > 255 ? 255 : a;
|
|
528
528
|
}
|
|
529
529
|
function parse(data) {
|
|
530
|
-
|
|
530
|
+
const self = {
|
|
531
531
|
width: 0,
|
|
532
532
|
height: 0,
|
|
533
533
|
comments: [],
|
|
@@ -536,46 +536,46 @@ function parse(data) {
|
|
|
536
536
|
exifBuffer: undefined,
|
|
537
537
|
jfif: undefined,
|
|
538
538
|
};
|
|
539
|
-
|
|
540
|
-
|
|
539
|
+
const maxResolutionInPixels = maxResolutionInMP * 1000 * 1000;
|
|
540
|
+
let offset = 0;
|
|
541
541
|
function readUint16() {
|
|
542
|
-
|
|
542
|
+
const value = (data[offset] << 8) | data[offset + 1];
|
|
543
543
|
offset += 2;
|
|
544
544
|
return value;
|
|
545
545
|
}
|
|
546
546
|
function readDataBlock() {
|
|
547
|
-
|
|
548
|
-
|
|
547
|
+
const length = readUint16();
|
|
548
|
+
const array = data.subarray(offset, offset + length - 2);
|
|
549
549
|
offset += array.length;
|
|
550
550
|
return array;
|
|
551
551
|
}
|
|
552
552
|
function prepareComponents(frame) {
|
|
553
|
-
|
|
554
|
-
for (
|
|
553
|
+
let maxH = 0, maxV = 0;
|
|
554
|
+
for (let componentId in frame.components) {
|
|
555
555
|
if (frame.components.hasOwnProperty(componentId)) {
|
|
556
|
-
|
|
556
|
+
const component = frame.components[componentId];
|
|
557
557
|
if (maxH < component.h)
|
|
558
558
|
maxH = component.h;
|
|
559
559
|
if (maxV < component.v)
|
|
560
560
|
maxV = component.v;
|
|
561
561
|
}
|
|
562
562
|
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
for (
|
|
563
|
+
const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH);
|
|
564
|
+
const mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV);
|
|
565
|
+
for (let componentId in frame.components) {
|
|
566
566
|
if (frame.components.hasOwnProperty(componentId)) {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
567
|
+
const component = frame.components[componentId];
|
|
568
|
+
const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH);
|
|
569
|
+
const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / maxV);
|
|
570
|
+
const blocksPerLineForMcu = mcusPerLine * component.h;
|
|
571
|
+
const blocksPerColumnForMcu = mcusPerColumn * component.v;
|
|
572
|
+
const blocksToAllocate = blocksPerColumnForMcu * blocksPerLineForMcu;
|
|
573
|
+
const blocks = [];
|
|
574
574
|
// Each block is a Int32Array of length 64 (4 x 64 = 256 bytes)
|
|
575
575
|
requestMemoryAllocation(blocksToAllocate * 256);
|
|
576
|
-
for (
|
|
577
|
-
|
|
578
|
-
for (
|
|
576
|
+
for (let i = 0; i < blocksPerColumnForMcu; i++) {
|
|
577
|
+
const row = [];
|
|
578
|
+
for (let j = 0; j < blocksPerLineForMcu; j++) {
|
|
579
579
|
row.push(new Int32Array(64));
|
|
580
580
|
}
|
|
581
581
|
blocks.push(row);
|
|
@@ -590,16 +590,16 @@ function parse(data) {
|
|
|
590
590
|
frame.mcusPerLine = mcusPerLine;
|
|
591
591
|
frame.mcusPerColumn = mcusPerColumn;
|
|
592
592
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
593
|
+
let jfif = null;
|
|
594
|
+
let adobe = null;
|
|
595
|
+
let frame = undefined;
|
|
596
|
+
let resetInterval = 0;
|
|
597
|
+
let quantizationTables = [];
|
|
598
|
+
let frames = [];
|
|
599
|
+
let huffmanTablesAC = [];
|
|
600
|
+
let huffmanTablesDC = [];
|
|
601
|
+
let fileMarker = readUint16();
|
|
602
|
+
let malformedDataOffset = -1;
|
|
603
603
|
if (fileMarker != 0xFFD8) { // SOI (Start of Image)
|
|
604
604
|
throw new Error('SOI not found');
|
|
605
605
|
}
|
|
@@ -624,10 +624,10 @@ function parse(data) {
|
|
|
624
624
|
case 0xFFEE: // APP14
|
|
625
625
|
case 0xFFEF: // APP15
|
|
626
626
|
case 0xFFFE: { // COM (Comment)
|
|
627
|
-
|
|
627
|
+
const appData = readDataBlock();
|
|
628
628
|
if (fileMarker === 0xFFFE) {
|
|
629
|
-
|
|
630
|
-
for (
|
|
629
|
+
let comment = '';
|
|
630
|
+
for (let ii = 0; ii < appData.byteLength; ii++) {
|
|
631
631
|
comment += String.fromCharCode(appData[ii]);
|
|
632
632
|
}
|
|
633
633
|
self.comments.push(comment);
|
|
@@ -670,21 +670,21 @@ function parse(data) {
|
|
|
670
670
|
break;
|
|
671
671
|
}
|
|
672
672
|
case 0xFFDB: { // DQT (Define Quantization Tables)
|
|
673
|
-
|
|
674
|
-
|
|
673
|
+
const quantizationTablesLength = readUint16();
|
|
674
|
+
const quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
|
675
675
|
while (offset < quantizationTablesEnd) {
|
|
676
|
-
|
|
676
|
+
const quantizationTableSpec = data[offset++];
|
|
677
677
|
requestMemoryAllocation(64 * 4);
|
|
678
|
-
|
|
678
|
+
const tableData = new Int32Array(64);
|
|
679
679
|
if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
|
|
680
|
-
for (
|
|
681
|
-
|
|
680
|
+
for (let j = 0; j < 64; j++) {
|
|
681
|
+
const z = dctZigZag[j];
|
|
682
682
|
tableData[z] = data[offset++];
|
|
683
683
|
}
|
|
684
684
|
}
|
|
685
685
|
else if ((quantizationTableSpec >> 4) === 1) { //16 bit
|
|
686
|
-
for (
|
|
687
|
-
|
|
686
|
+
for (let j = 0; j < 64; j++) {
|
|
687
|
+
const z = dctZigZag[j];
|
|
688
688
|
tableData[z] = readUint16();
|
|
689
689
|
}
|
|
690
690
|
}
|
|
@@ -711,17 +711,17 @@ function parse(data) {
|
|
|
711
711
|
mcusPerLine: 0,
|
|
712
712
|
mcusPerColumn: 0,
|
|
713
713
|
};
|
|
714
|
-
|
|
714
|
+
const pixelsInFrame = frame.scanLines * frame.samplesPerLine;
|
|
715
715
|
if (pixelsInFrame > maxResolutionInPixels) {
|
|
716
|
-
|
|
717
|
-
throw new Error(
|
|
716
|
+
const exceededAmount = Math.ceil((pixelsInFrame - maxResolutionInPixels) / 1e6);
|
|
717
|
+
throw new Error(`maxResolutionInMP limit exceeded by ${exceededAmount}MP`);
|
|
718
718
|
}
|
|
719
|
-
|
|
720
|
-
for (
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
719
|
+
const componentsCount = data[offset++];
|
|
720
|
+
for (let i = 0; i < componentsCount; i++) {
|
|
721
|
+
const componentId = data[offset];
|
|
722
|
+
const h = data[offset + 1] >> 4;
|
|
723
|
+
const v = data[offset + 1] & 15;
|
|
724
|
+
const qId = data[offset + 2];
|
|
725
725
|
frame.componentsOrder.push(componentId);
|
|
726
726
|
frame.components[componentId] = {
|
|
727
727
|
h: h,
|
|
@@ -739,22 +739,22 @@ function parse(data) {
|
|
|
739
739
|
break;
|
|
740
740
|
}
|
|
741
741
|
case 0xFFC4: { // DHT (Define Huffman Tables)
|
|
742
|
-
|
|
743
|
-
for (
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
for (
|
|
742
|
+
const huffmanLength = readUint16();
|
|
743
|
+
for (let i = 2; i < huffmanLength;) {
|
|
744
|
+
const huffmanTableSpec = data[offset++];
|
|
745
|
+
const codeLengths = new Uint8Array(16);
|
|
746
|
+
let codeLengthSum = 0;
|
|
747
|
+
for (let j = 0; j < 16; j++, offset++) {
|
|
748
748
|
codeLengthSum += (codeLengths[j] = data[offset]);
|
|
749
749
|
}
|
|
750
750
|
requestMemoryAllocation(16 + codeLengthSum);
|
|
751
|
-
|
|
752
|
-
for (
|
|
751
|
+
const huffmanValues = new Uint8Array(codeLengthSum);
|
|
752
|
+
for (let j = 0; j < codeLengthSum; j++, offset++) {
|
|
753
753
|
huffmanValues[j] = data[offset];
|
|
754
754
|
}
|
|
755
755
|
i += 17 + codeLengthSum;
|
|
756
|
-
|
|
757
|
-
|
|
756
|
+
const index = huffmanTableSpec & 15;
|
|
757
|
+
const table = (huffmanTableSpec >> 4) === 0 ? huffmanTablesDC : huffmanTablesAC;
|
|
758
758
|
table[index] = buildHuffmanTable(codeLengths, huffmanValues);
|
|
759
759
|
}
|
|
760
760
|
break;
|
|
@@ -769,19 +769,19 @@ function parse(data) {
|
|
|
769
769
|
break;
|
|
770
770
|
case 0xFFDA: { // SOS (Start of Scan)
|
|
771
771
|
readUint16(); // skip data length
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
for (
|
|
775
|
-
|
|
776
|
-
|
|
772
|
+
const selectorsCount = data[offset++];
|
|
773
|
+
const components = [];
|
|
774
|
+
for (let i = 0; i < selectorsCount; i++) {
|
|
775
|
+
const component = frame.components[data[offset++]];
|
|
776
|
+
const tableSpec = data[offset++];
|
|
777
777
|
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
|
|
778
778
|
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
|
|
779
779
|
components.push(component);
|
|
780
780
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
781
|
+
const spectralStart = data[offset++];
|
|
782
|
+
const spectralEnd = data[offset++];
|
|
783
|
+
const successiveApproximation = data[offset++];
|
|
784
|
+
const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15);
|
|
785
785
|
offset += processed;
|
|
786
786
|
break;
|
|
787
787
|
}
|
|
@@ -801,10 +801,10 @@ function parse(data) {
|
|
|
801
801
|
// Recover from malformed APP1 markers popular in some phone models.
|
|
802
802
|
// See https://github.com/eugeneware/jpeg-js/issues/82
|
|
803
803
|
if (malformedDataOffset !== -1) {
|
|
804
|
-
throw new Error(
|
|
804
|
+
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)}`);
|
|
805
805
|
}
|
|
806
806
|
malformedDataOffset = offset - 1;
|
|
807
|
-
|
|
807
|
+
const nextOffset = readUint16();
|
|
808
808
|
if (data[offset + nextOffset - 2] === 0xFF) {
|
|
809
809
|
offset += nextOffset - 2;
|
|
810
810
|
break;
|
|
@@ -818,9 +818,9 @@ function parse(data) {
|
|
|
818
818
|
if (frames.length != 1)
|
|
819
819
|
throw new Error('only single frame JPEGs supported');
|
|
820
820
|
// set each frame's components quantization table
|
|
821
|
-
for (
|
|
822
|
-
|
|
823
|
-
for (
|
|
821
|
+
for (let i = 0; i < frames.length; i++) {
|
|
822
|
+
const cp = frames[i].components;
|
|
823
|
+
for (let j in cp) { // TODO: don't use `in`
|
|
824
824
|
cp[j].quantizationTable = quantizationTables[cp[j].quantizationIdx];
|
|
825
825
|
delete cp[j].quantizationIdx; // TODO: why ???
|
|
826
826
|
}
|
|
@@ -830,8 +830,8 @@ function parse(data) {
|
|
|
830
830
|
self.jfif = jfif;
|
|
831
831
|
self.adobe = adobe;
|
|
832
832
|
self.components = [];
|
|
833
|
-
for (
|
|
834
|
-
|
|
833
|
+
for (let i = 0; i < frame.componentsOrder.length; i++) {
|
|
834
|
+
const component = frame.components[frame.componentsOrder[i]];
|
|
835
835
|
self.components.push({
|
|
836
836
|
lines: buildComponentData(component),
|
|
837
837
|
scaleX: component.h / frame.maxH,
|
|
@@ -841,20 +841,20 @@ function parse(data) {
|
|
|
841
841
|
return self;
|
|
842
842
|
}
|
|
843
843
|
function getData(decoded) {
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
844
|
+
let offset = 0;
|
|
845
|
+
let colorTransform = false;
|
|
846
|
+
const width = decoded.width;
|
|
847
|
+
const height = decoded.height;
|
|
848
|
+
const dataLength = width * height * decoded.components.length;
|
|
849
849
|
requestMemoryAllocation(dataLength);
|
|
850
|
-
|
|
850
|
+
const data = new Uint8Array(dataLength);
|
|
851
851
|
switch (decoded.components.length) {
|
|
852
852
|
case 1: {
|
|
853
|
-
|
|
854
|
-
for (
|
|
855
|
-
|
|
856
|
-
for (
|
|
857
|
-
|
|
853
|
+
const component1 = decoded.components[0];
|
|
854
|
+
for (let y = 0; y < height; y++) {
|
|
855
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
856
|
+
for (let x = 0; x < width; x++) {
|
|
857
|
+
const Y = component1Line[0 | (x * component1.scaleX)];
|
|
858
858
|
data[offset++] = Y;
|
|
859
859
|
}
|
|
860
860
|
}
|
|
@@ -862,15 +862,15 @@ function getData(decoded) {
|
|
|
862
862
|
}
|
|
863
863
|
case 2: {
|
|
864
864
|
// PDF might compress two component data in custom colorspace
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
for (
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
for (
|
|
871
|
-
|
|
865
|
+
const component1 = decoded.components[0];
|
|
866
|
+
const component2 = decoded.components[1];
|
|
867
|
+
for (let y = 0; y < height; y++) {
|
|
868
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
869
|
+
const component2Line = component2.lines[0 | (y * component2.scaleY)];
|
|
870
|
+
for (let x = 0; x < width; x++) {
|
|
871
|
+
const Y1 = component1Line[0 | (x * component1.scaleX)];
|
|
872
872
|
data[offset++] = Y1;
|
|
873
|
-
|
|
873
|
+
const Y2 = component2Line[0 | (x * component2.scaleX)];
|
|
874
874
|
data[offset++] = Y2;
|
|
875
875
|
}
|
|
876
876
|
}
|
|
@@ -882,15 +882,15 @@ function getData(decoded) {
|
|
|
882
882
|
// The adobe transform marker overrides any previous setting
|
|
883
883
|
if (decoded.adobe && decoded.adobe.transformCode)
|
|
884
884
|
colorTransform = true;
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
for (
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
for (
|
|
893
|
-
|
|
885
|
+
const component1 = decoded.components[0];
|
|
886
|
+
const component2 = decoded.components[1];
|
|
887
|
+
const component3 = decoded.components[2];
|
|
888
|
+
for (let y = 0; y < height; y++) {
|
|
889
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
890
|
+
const component2Line = component2.lines[0 | (y * component2.scaleY)];
|
|
891
|
+
const component3Line = component3.lines[0 | (y * component3.scaleY)];
|
|
892
|
+
for (let x = 0; x < width; x++) {
|
|
893
|
+
let Y, Cb, Cr, R, G, B;
|
|
894
894
|
if (!colorTransform) {
|
|
895
895
|
R = component1Line[0 | (x * component1.scaleX)];
|
|
896
896
|
G = component2Line[0 | (x * component2.scaleX)];
|
|
@@ -919,17 +919,17 @@ function getData(decoded) {
|
|
|
919
919
|
// The adobe transform marker overrides any previous setting
|
|
920
920
|
if (decoded.adobe && decoded.adobe.transformCode)
|
|
921
921
|
colorTransform = true;
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
for (
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
for (
|
|
932
|
-
|
|
922
|
+
const component1 = decoded.components[0];
|
|
923
|
+
const component2 = decoded.components[1];
|
|
924
|
+
const component3 = decoded.components[2];
|
|
925
|
+
const component4 = decoded.components[3];
|
|
926
|
+
for (let y = 0; y < height; y++) {
|
|
927
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
928
|
+
const component2Line = component2.lines[0 | (y * component2.scaleY)];
|
|
929
|
+
const component3Line = component3.lines[0 | (y * component3.scaleY)];
|
|
930
|
+
const component4Line = component4.lines[0 | (y * component4.scaleY)];
|
|
931
|
+
for (let x = 0; x < width; x++) {
|
|
932
|
+
let Y, Cb, Cr, K, C, M, Ye;
|
|
933
933
|
if (!colorTransform) {
|
|
934
934
|
C = component1Line[0 | (x * component1.scaleX)];
|
|
935
935
|
M = component2Line[0 | (x * component2.scaleX)];
|
|
@@ -962,20 +962,20 @@ function decodeJpeg(encoded, createImageData) {
|
|
|
962
962
|
totalBytesAllocated = 0;
|
|
963
963
|
if (encoded.length === 0)
|
|
964
964
|
throw new Error('Empty jpeg buffer');
|
|
965
|
-
|
|
965
|
+
const decoded = parse(encoded);
|
|
966
966
|
requestMemoryAllocation(decoded.width * decoded.height * 4);
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
967
|
+
const data = getData(decoded);
|
|
968
|
+
const imageData = createImageData(decoded.width, decoded.height);
|
|
969
|
+
const width = imageData.width;
|
|
970
|
+
const height = imageData.height;
|
|
971
|
+
const imageDataArray = imageData.data;
|
|
972
|
+
let i = 0;
|
|
973
|
+
let j = 0;
|
|
974
974
|
switch (decoded.components.length) {
|
|
975
975
|
case 1:
|
|
976
|
-
for (
|
|
977
|
-
for (
|
|
978
|
-
|
|
976
|
+
for (let y = 0; y < height; y++) {
|
|
977
|
+
for (let x = 0; x < width; x++) {
|
|
978
|
+
const Y = data[i++];
|
|
979
979
|
imageDataArray[j++] = Y;
|
|
980
980
|
imageDataArray[j++] = Y;
|
|
981
981
|
imageDataArray[j++] = Y;
|
|
@@ -984,11 +984,11 @@ function decodeJpeg(encoded, createImageData) {
|
|
|
984
984
|
}
|
|
985
985
|
break;
|
|
986
986
|
case 3:
|
|
987
|
-
for (
|
|
988
|
-
for (
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
987
|
+
for (let y = 0; y < height; y++) {
|
|
988
|
+
for (let x = 0; x < width; x++) {
|
|
989
|
+
const R = data[i++];
|
|
990
|
+
const G = data[i++];
|
|
991
|
+
const B = data[i++];
|
|
992
992
|
imageDataArray[j++] = R;
|
|
993
993
|
imageDataArray[j++] = G;
|
|
994
994
|
imageDataArray[j++] = B;
|
|
@@ -997,15 +997,15 @@ function decodeJpeg(encoded, createImageData) {
|
|
|
997
997
|
}
|
|
998
998
|
break;
|
|
999
999
|
case 4:
|
|
1000
|
-
for (
|
|
1001
|
-
for (
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1000
|
+
for (let y = 0; y < height; y++) {
|
|
1001
|
+
for (let x = 0; x < width; x++) {
|
|
1002
|
+
const C = data[i++];
|
|
1003
|
+
const M = data[i++];
|
|
1004
|
+
const Y = data[i++];
|
|
1005
|
+
const K = data[i++];
|
|
1006
|
+
const R = 255 - clampTo8bit(C * (1 - K / 255) + K);
|
|
1007
|
+
const G = 255 - clampTo8bit(M * (1 - K / 255) + K);
|
|
1008
|
+
const B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
|
|
1009
1009
|
imageDataArray[j++] = R;
|
|
1010
1010
|
imageDataArray[j++] = G;
|
|
1011
1011
|
imageDataArray[j++] = B;
|