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-es/jpeg.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
See the License for the specific language governing permissions and
|
|
15
15
|
limitations under the License.
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
const dctZigZag = new Int32Array([
|
|
18
18
|
0,
|
|
19
19
|
1, 8,
|
|
20
20
|
16, 9, 2,
|
|
@@ -31,34 +31,34 @@ var dctZigZag = new Int32Array([
|
|
|
31
31
|
55, 62,
|
|
32
32
|
63
|
|
33
33
|
]);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
const dctCos1 = 4017; // cos(pi/16)
|
|
35
|
+
const dctSin1 = 799; // sin(pi/16)
|
|
36
|
+
const dctCos3 = 3406; // cos(3*pi/16)
|
|
37
|
+
const dctSin3 = 2276; // sin(3*pi/16)
|
|
38
|
+
const dctCos6 = 1567; // cos(6*pi/16)
|
|
39
|
+
const dctSin6 = 3784; // sin(6*pi/16)
|
|
40
|
+
const dctSqrt2 = 5793; // sqrt(2)
|
|
41
|
+
const dctSqrt1d2 = 2896; // sqrt(2) / 2
|
|
42
|
+
const maxResolutionInMP = 100; // Don't decode more than 100 megapixels
|
|
43
|
+
const maxMemoryUsageBytes = 64 * 1024 * 1024; // Don't decode if memory footprint is more than 64MB
|
|
44
|
+
let totalBytesAllocated = 0; // avoid unexpected OOMs from untrusted content.
|
|
45
45
|
function requestMemoryAllocation(increaseAmount) {
|
|
46
|
-
|
|
46
|
+
const totalMemoryImpactBytes = totalBytesAllocated + increaseAmount;
|
|
47
47
|
if (totalMemoryImpactBytes > maxMemoryUsageBytes) {
|
|
48
|
-
|
|
49
|
-
throw new Error(
|
|
48
|
+
const exceededAmount = Math.ceil((totalMemoryImpactBytes - maxMemoryUsageBytes) / 1024 / 1024);
|
|
49
|
+
throw new Error(`Max memory limit exceeded by at least ${exceededAmount}MB`);
|
|
50
50
|
}
|
|
51
51
|
totalBytesAllocated = totalMemoryImpactBytes;
|
|
52
52
|
}
|
|
53
53
|
function buildHuffmanTable(codeLengths, values) {
|
|
54
|
-
|
|
54
|
+
let length = 16;
|
|
55
55
|
while (length > 0 && !codeLengths[length - 1])
|
|
56
56
|
length--;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
for (
|
|
61
|
-
for (
|
|
57
|
+
const code = [{ children: [], index: 0 }];
|
|
58
|
+
let k = 0;
|
|
59
|
+
let p = code[0];
|
|
60
|
+
for (let i = 0; i < length; i++) {
|
|
61
|
+
for (let j = 0; j < codeLengths[i]; j++) {
|
|
62
62
|
p = code.pop();
|
|
63
63
|
p.children[p.index] = values[k];
|
|
64
64
|
while (p.index > 0) {
|
|
@@ -69,7 +69,7 @@ function buildHuffmanTable(codeLengths, values) {
|
|
|
69
69
|
p.index++;
|
|
70
70
|
code.push(p);
|
|
71
71
|
while (code.length <= i) {
|
|
72
|
-
|
|
72
|
+
const q = { children: [], index: 0 };
|
|
73
73
|
code.push(q);
|
|
74
74
|
p.children[p.index] = q.children;
|
|
75
75
|
p = q;
|
|
@@ -78,7 +78,7 @@ function buildHuffmanTable(codeLengths, values) {
|
|
|
78
78
|
}
|
|
79
79
|
if (i + 1 < length) {
|
|
80
80
|
// p here points to last code
|
|
81
|
-
|
|
81
|
+
const q = { children: [], index: 0 };
|
|
82
82
|
code.push(q);
|
|
83
83
|
p.children[p.index] = q.children;
|
|
84
84
|
p = q;
|
|
@@ -87,11 +87,11 @@ function buildHuffmanTable(codeLengths, values) {
|
|
|
87
87
|
return code[0].children;
|
|
88
88
|
}
|
|
89
89
|
function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
const mcusPerLine = frame.mcusPerLine;
|
|
91
|
+
const progressive = frame.progressive;
|
|
92
|
+
const startOffset = offset;
|
|
93
|
+
let bitsData = 0;
|
|
94
|
+
let bitsCount = 0;
|
|
95
95
|
function readBit() {
|
|
96
96
|
if (bitsCount > 0) {
|
|
97
97
|
bitsCount--;
|
|
@@ -99,16 +99,16 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
99
99
|
}
|
|
100
100
|
bitsData = data[offset++];
|
|
101
101
|
if (bitsData == 0xFF) {
|
|
102
|
-
|
|
102
|
+
const nextByte = data[offset++];
|
|
103
103
|
if (nextByte)
|
|
104
|
-
throw new Error(
|
|
104
|
+
throw new Error(`unexpected marker: ${((bitsData << 8) | nextByte).toString(16)}`);
|
|
105
105
|
// unstuff 0
|
|
106
106
|
}
|
|
107
107
|
bitsCount = 7;
|
|
108
108
|
return bitsData >>> 7;
|
|
109
109
|
}
|
|
110
110
|
function decodeHuffman(tree) {
|
|
111
|
-
|
|
111
|
+
let node = tree;
|
|
112
112
|
while (true) {
|
|
113
113
|
node = node[readBit()];
|
|
114
114
|
if (typeof node === 'number')
|
|
@@ -118,7 +118,7 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
function receive(length) {
|
|
121
|
-
|
|
121
|
+
let n = 0;
|
|
122
122
|
while (length > 0) {
|
|
123
123
|
n = (n << 1) | readBit();
|
|
124
124
|
length--;
|
|
@@ -126,20 +126,20 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
126
126
|
return n;
|
|
127
127
|
}
|
|
128
128
|
function receiveAndExtend(length) {
|
|
129
|
-
|
|
129
|
+
let n = receive(length);
|
|
130
130
|
if (n >= 1 << (length - 1))
|
|
131
131
|
return n;
|
|
132
132
|
return n + (-1 << length) + 1;
|
|
133
133
|
}
|
|
134
134
|
function decodeBaseline(component, zz) {
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
const t = decodeHuffman(component.huffmanTableDC);
|
|
136
|
+
const diff = t === 0 ? 0 : receiveAndExtend(t);
|
|
137
137
|
zz[0] = (component.pred += diff);
|
|
138
|
-
|
|
138
|
+
let k = 1;
|
|
139
139
|
while (k < 64) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
140
|
+
const rs = decodeHuffman(component.huffmanTableAC);
|
|
141
|
+
const s = rs & 15;
|
|
142
|
+
const r = rs >> 4;
|
|
143
143
|
if (s === 0) {
|
|
144
144
|
if (r < 15)
|
|
145
145
|
break;
|
|
@@ -147,30 +147,30 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
147
147
|
continue;
|
|
148
148
|
}
|
|
149
149
|
k += r;
|
|
150
|
-
|
|
150
|
+
const z = dctZigZag[k];
|
|
151
151
|
zz[z] = receiveAndExtend(s);
|
|
152
152
|
k++;
|
|
153
153
|
}
|
|
154
154
|
}
|
|
155
155
|
function decodeDCFirst(component, zz) {
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
const t = decodeHuffman(component.huffmanTableDC);
|
|
157
|
+
const diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
|
|
158
158
|
zz[0] = (component.pred += diff);
|
|
159
159
|
}
|
|
160
160
|
function decodeDCSuccessive(_component, zz) {
|
|
161
161
|
zz[0] |= readBit() << successive;
|
|
162
162
|
}
|
|
163
|
-
|
|
163
|
+
let eobrun = 0;
|
|
164
164
|
function decodeACFirst(component, zz) {
|
|
165
165
|
if (eobrun > 0) {
|
|
166
166
|
eobrun--;
|
|
167
167
|
return;
|
|
168
168
|
}
|
|
169
|
-
|
|
169
|
+
let k = spectralStart, e = spectralEnd;
|
|
170
170
|
while (k <= e) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
const rs = decodeHuffman(component.huffmanTableAC);
|
|
172
|
+
const s = rs & 15;
|
|
173
|
+
const r = rs >> 4;
|
|
174
174
|
if (s === 0) {
|
|
175
175
|
if (r < 15) {
|
|
176
176
|
eobrun = receive(r) + (1 << r) - 1;
|
|
@@ -180,24 +180,24 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
180
180
|
continue;
|
|
181
181
|
}
|
|
182
182
|
k += r;
|
|
183
|
-
|
|
183
|
+
const z = dctZigZag[k];
|
|
184
184
|
zz[z] = receiveAndExtend(s) * (1 << successive);
|
|
185
185
|
k++;
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
let successiveACState = 0;
|
|
189
|
+
let successiveACNextValue = 0;
|
|
190
190
|
function decodeACSuccessive(component, zz) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
let k = spectralStart;
|
|
192
|
+
let e = spectralEnd;
|
|
193
|
+
let r = 0;
|
|
194
194
|
while (k <= e) {
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
const z = dctZigZag[k];
|
|
196
|
+
const direction = zz[z] < 0 ? -1 : 1;
|
|
197
197
|
switch (successiveACState) {
|
|
198
198
|
case 0: // initial state
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
const rs = decodeHuffman(component.huffmanTableAC);
|
|
200
|
+
const s = rs & 15;
|
|
201
201
|
r = rs >> 4; // this was new variable in old code
|
|
202
202
|
if (s === 0) {
|
|
203
203
|
if (r < 15) {
|
|
@@ -251,26 +251,26 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
function decodeMcu(component, decode, mcu, row, col) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
254
|
+
const mcuRow = (mcu / mcusPerLine) | 0;
|
|
255
|
+
const mcuCol = mcu % mcusPerLine;
|
|
256
|
+
const blockRow = mcuRow * component.v + row;
|
|
257
|
+
const blockCol = mcuCol * component.h + col;
|
|
258
258
|
// If the block is missing, just skip it.
|
|
259
259
|
if (component.blocks[blockRow] === undefined)
|
|
260
260
|
return;
|
|
261
261
|
decode(component, component.blocks[blockRow][blockCol]);
|
|
262
262
|
}
|
|
263
263
|
function decodeBlock(component, decode, mcu) {
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
const blockRow = (mcu / component.blocksPerLine) | 0;
|
|
265
|
+
const blockCol = mcu % component.blocksPerLine;
|
|
266
266
|
// If the block is missing, just skip it.
|
|
267
267
|
if (component.blocks[blockRow] === undefined)
|
|
268
268
|
return;
|
|
269
269
|
decode(component, component.blocks[blockRow][blockCol]);
|
|
270
270
|
}
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
const componentsLength = components.length;
|
|
272
|
+
let component;
|
|
273
|
+
let decodeFn;
|
|
274
274
|
if (progressive) {
|
|
275
275
|
if (spectralStart === 0) {
|
|
276
276
|
decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
|
|
@@ -282,8 +282,8 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
282
282
|
else {
|
|
283
283
|
decodeFn = decodeBaseline;
|
|
284
284
|
}
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
let mcu = 0;
|
|
286
|
+
let mcuExpected;
|
|
287
287
|
if (componentsLength == 1) {
|
|
288
288
|
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
|
289
289
|
}
|
|
@@ -292,29 +292,29 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
292
292
|
}
|
|
293
293
|
if (!resetInterval)
|
|
294
294
|
resetInterval = mcuExpected;
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
295
|
+
let h;
|
|
296
|
+
let v;
|
|
297
|
+
let marker;
|
|
298
298
|
while (mcu < mcuExpected) {
|
|
299
299
|
// reset interval stuff
|
|
300
|
-
for (
|
|
300
|
+
for (let i = 0; i < componentsLength; i++)
|
|
301
301
|
components[i].pred = 0;
|
|
302
302
|
eobrun = 0;
|
|
303
303
|
if (componentsLength == 1) {
|
|
304
304
|
component = components[0];
|
|
305
|
-
for (
|
|
305
|
+
for (let n = 0; n < resetInterval; n++) {
|
|
306
306
|
decodeBlock(component, decodeFn, mcu);
|
|
307
307
|
mcu++;
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
else {
|
|
311
|
-
for (
|
|
312
|
-
for (
|
|
311
|
+
for (let n = 0; n < resetInterval; n++) {
|
|
312
|
+
for (let i = 0; i < componentsLength; i++) {
|
|
313
313
|
component = components[i];
|
|
314
314
|
h = component.h;
|
|
315
315
|
v = component.v;
|
|
316
|
-
for (
|
|
317
|
-
for (
|
|
316
|
+
for (let j = 0; j < v; j++) {
|
|
317
|
+
for (let k = 0; k < h; k++) {
|
|
318
318
|
decodeMcu(component, decodeFn, mcu, j, k);
|
|
319
319
|
}
|
|
320
320
|
}
|
|
@@ -351,54 +351,54 @@ function decodeScan(data, offset, frame, components, resetInterval, spectralStar
|
|
|
351
351
|
return offset - startOffset;
|
|
352
352
|
}
|
|
353
353
|
function buildComponentData(component) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
354
|
+
const lines = [];
|
|
355
|
+
const blocksPerLine = component.blocksPerLine;
|
|
356
|
+
const blocksPerColumn = component.blocksPerColumn;
|
|
357
|
+
const samplesPerLine = blocksPerLine << 3;
|
|
358
358
|
// Only 1 used per invocation of this function and garbage collected after invocation, so no need to account for its memory footprint.
|
|
359
|
-
|
|
360
|
-
|
|
359
|
+
const R = new Int32Array(64);
|
|
360
|
+
const r = new Uint8Array(64);
|
|
361
361
|
// A port of poppler's IDCT method which in turn is taken from:
|
|
362
362
|
// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
|
|
363
363
|
// "Practical Fast 1-D DCT Algorithms with 11 Multiplications",
|
|
364
364
|
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
|
365
365
|
// 988-991.
|
|
366
366
|
function quantizeAndInverse(zz, dataOut, dataIn) {
|
|
367
|
-
|
|
368
|
-
|
|
367
|
+
const qt = component.quantizationTable;
|
|
368
|
+
const p = dataIn;
|
|
369
369
|
// dequant
|
|
370
|
-
for (
|
|
370
|
+
for (let i = 0; i < 64; i++) {
|
|
371
371
|
p[i] = zz[i] * qt[i];
|
|
372
372
|
}
|
|
373
373
|
// inverse DCT on rows
|
|
374
|
-
for (
|
|
375
|
-
|
|
374
|
+
for (let i = 0; i < 8; ++i) {
|
|
375
|
+
const row = 8 * i;
|
|
376
376
|
// check for all-zero AC coefficients
|
|
377
377
|
if (p[1 + row] == 0 && p[2 + row] == 0 && p[3 + row] == 0 &&
|
|
378
378
|
p[4 + row] == 0 && p[5 + row] == 0 && p[6 + row] == 0 &&
|
|
379
379
|
p[7 + row] == 0) {
|
|
380
|
-
|
|
381
|
-
p[0 + row] =
|
|
382
|
-
p[1 + row] =
|
|
383
|
-
p[2 + row] =
|
|
384
|
-
p[3 + row] =
|
|
385
|
-
p[4 + row] =
|
|
386
|
-
p[5 + row] =
|
|
387
|
-
p[6 + row] =
|
|
388
|
-
p[7 + row] =
|
|
380
|
+
const t = (dctSqrt2 * p[0 + row] + 512) >> 10;
|
|
381
|
+
p[0 + row] = t;
|
|
382
|
+
p[1 + row] = t;
|
|
383
|
+
p[2 + row] = t;
|
|
384
|
+
p[3 + row] = t;
|
|
385
|
+
p[4 + row] = t;
|
|
386
|
+
p[5 + row] = t;
|
|
387
|
+
p[6 + row] = t;
|
|
388
|
+
p[7 + row] = t;
|
|
389
389
|
continue;
|
|
390
390
|
}
|
|
391
391
|
// stage 4
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
392
|
+
let v0 = (dctSqrt2 * p[0 + row] + 128) >> 8;
|
|
393
|
+
let v1 = (dctSqrt2 * p[4 + row] + 128) >> 8;
|
|
394
|
+
let v2 = p[2 + row];
|
|
395
|
+
let v3 = p[6 + row];
|
|
396
|
+
let v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8;
|
|
397
|
+
let v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8;
|
|
398
|
+
let v5 = p[3 + row] << 4;
|
|
399
|
+
let v6 = p[5 + row] << 4;
|
|
400
400
|
// stage 3
|
|
401
|
-
|
|
401
|
+
let t = (v0 - v1 + 1) >> 1;
|
|
402
402
|
v0 = (v0 + v1 + 1) >> 1;
|
|
403
403
|
v1 = t;
|
|
404
404
|
t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8;
|
|
@@ -434,34 +434,34 @@ function buildComponentData(component) {
|
|
|
434
434
|
p[4 + row] = v3 - v4;
|
|
435
435
|
}
|
|
436
436
|
// inverse DCT on columns
|
|
437
|
-
for (
|
|
438
|
-
|
|
437
|
+
for (let i = 0; i < 8; ++i) {
|
|
438
|
+
const col = i;
|
|
439
439
|
// check for all-zero AC coefficients
|
|
440
440
|
if (p[1 * 8 + col] == 0 && p[2 * 8 + col] == 0 && p[3 * 8 + col] == 0 &&
|
|
441
441
|
p[4 * 8 + col] == 0 && p[5 * 8 + col] == 0 && p[6 * 8 + col] == 0 &&
|
|
442
442
|
p[7 * 8 + col] == 0) {
|
|
443
|
-
|
|
444
|
-
p[0 * 8 + col] =
|
|
445
|
-
p[1 * 8 + col] =
|
|
446
|
-
p[2 * 8 + col] =
|
|
447
|
-
p[3 * 8 + col] =
|
|
448
|
-
p[4 * 8 + col] =
|
|
449
|
-
p[5 * 8 + col] =
|
|
450
|
-
p[6 * 8 + col] =
|
|
451
|
-
p[7 * 8 + col] =
|
|
443
|
+
const t = (dctSqrt2 * dataIn[i + 0] + 8192) >> 14;
|
|
444
|
+
p[0 * 8 + col] = t;
|
|
445
|
+
p[1 * 8 + col] = t;
|
|
446
|
+
p[2 * 8 + col] = t;
|
|
447
|
+
p[3 * 8 + col] = t;
|
|
448
|
+
p[4 * 8 + col] = t;
|
|
449
|
+
p[5 * 8 + col] = t;
|
|
450
|
+
p[6 * 8 + col] = t;
|
|
451
|
+
p[7 * 8 + col] = t;
|
|
452
452
|
continue;
|
|
453
453
|
}
|
|
454
454
|
// stage 4
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
455
|
+
let v0 = (dctSqrt2 * p[0 * 8 + col] + 2048) >> 12;
|
|
456
|
+
let v1 = (dctSqrt2 * p[4 * 8 + col] + 2048) >> 12;
|
|
457
|
+
let v2 = p[2 * 8 + col];
|
|
458
|
+
let v3 = p[6 * 8 + col];
|
|
459
|
+
let v4 = (dctSqrt1d2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048) >> 12;
|
|
460
|
+
let v7 = (dctSqrt1d2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048) >> 12;
|
|
461
|
+
let v5 = p[3 * 8 + col];
|
|
462
|
+
let v6 = p[5 * 8 + col];
|
|
463
463
|
// stage 3
|
|
464
|
-
|
|
464
|
+
let t = (v0 - v1 + 1) >> 1;
|
|
465
465
|
v0 = (v0 + v1 + 1) >> 1;
|
|
466
466
|
v1 = t;
|
|
467
467
|
t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12;
|
|
@@ -497,23 +497,23 @@ function buildComponentData(component) {
|
|
|
497
497
|
p[4 * 8 + col] = v3 - v4;
|
|
498
498
|
}
|
|
499
499
|
// convert to 8-bit integers
|
|
500
|
-
for (
|
|
501
|
-
|
|
500
|
+
for (let i = 0; i < 64; ++i) {
|
|
501
|
+
const sample = 128 + ((p[i] + 8) >> 4);
|
|
502
502
|
dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample;
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
requestMemoryAllocation(samplesPerLine * blocksPerColumn * 8);
|
|
506
|
-
for (
|
|
507
|
-
|
|
508
|
-
for (
|
|
506
|
+
for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
|
|
507
|
+
const scanLine = blockRow << 3;
|
|
508
|
+
for (let i = 0; i < 8; i++)
|
|
509
509
|
lines.push(new Uint8Array(samplesPerLine));
|
|
510
|
-
for (
|
|
510
|
+
for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
|
511
511
|
quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
for (
|
|
515
|
-
|
|
516
|
-
for (
|
|
512
|
+
let offset = 0;
|
|
513
|
+
const sample = blockCol << 3;
|
|
514
|
+
for (let j = 0; j < 8; j++) {
|
|
515
|
+
const line = lines[scanLine + j];
|
|
516
|
+
for (let i = 0; i < 8; i++)
|
|
517
517
|
line[sample + i] = r[offset++];
|
|
518
518
|
}
|
|
519
519
|
}
|
|
@@ -524,7 +524,7 @@ function clampTo8bit(a) {
|
|
|
524
524
|
return a < 0 ? 0 : a > 255 ? 255 : a;
|
|
525
525
|
}
|
|
526
526
|
function parse(data) {
|
|
527
|
-
|
|
527
|
+
const self = {
|
|
528
528
|
width: 0,
|
|
529
529
|
height: 0,
|
|
530
530
|
comments: [],
|
|
@@ -533,46 +533,46 @@ function parse(data) {
|
|
|
533
533
|
exifBuffer: undefined,
|
|
534
534
|
jfif: undefined,
|
|
535
535
|
};
|
|
536
|
-
|
|
537
|
-
|
|
536
|
+
const maxResolutionInPixels = maxResolutionInMP * 1000 * 1000;
|
|
537
|
+
let offset = 0;
|
|
538
538
|
function readUint16() {
|
|
539
|
-
|
|
539
|
+
const value = (data[offset] << 8) | data[offset + 1];
|
|
540
540
|
offset += 2;
|
|
541
541
|
return value;
|
|
542
542
|
}
|
|
543
543
|
function readDataBlock() {
|
|
544
|
-
|
|
545
|
-
|
|
544
|
+
const length = readUint16();
|
|
545
|
+
const array = data.subarray(offset, offset + length - 2);
|
|
546
546
|
offset += array.length;
|
|
547
547
|
return array;
|
|
548
548
|
}
|
|
549
549
|
function prepareComponents(frame) {
|
|
550
|
-
|
|
551
|
-
for (
|
|
550
|
+
let maxH = 0, maxV = 0;
|
|
551
|
+
for (let componentId in frame.components) {
|
|
552
552
|
if (frame.components.hasOwnProperty(componentId)) {
|
|
553
|
-
|
|
553
|
+
const component = frame.components[componentId];
|
|
554
554
|
if (maxH < component.h)
|
|
555
555
|
maxH = component.h;
|
|
556
556
|
if (maxV < component.v)
|
|
557
557
|
maxV = component.v;
|
|
558
558
|
}
|
|
559
559
|
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
for (
|
|
560
|
+
const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / maxH);
|
|
561
|
+
const mcusPerColumn = Math.ceil(frame.scanLines / 8 / maxV);
|
|
562
|
+
for (let componentId in frame.components) {
|
|
563
563
|
if (frame.components.hasOwnProperty(componentId)) {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
564
|
+
const component = frame.components[componentId];
|
|
565
|
+
const blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / maxH);
|
|
566
|
+
const blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / maxV);
|
|
567
|
+
const blocksPerLineForMcu = mcusPerLine * component.h;
|
|
568
|
+
const blocksPerColumnForMcu = mcusPerColumn * component.v;
|
|
569
|
+
const blocksToAllocate = blocksPerColumnForMcu * blocksPerLineForMcu;
|
|
570
|
+
const blocks = [];
|
|
571
571
|
// Each block is a Int32Array of length 64 (4 x 64 = 256 bytes)
|
|
572
572
|
requestMemoryAllocation(blocksToAllocate * 256);
|
|
573
|
-
for (
|
|
574
|
-
|
|
575
|
-
for (
|
|
573
|
+
for (let i = 0; i < blocksPerColumnForMcu; i++) {
|
|
574
|
+
const row = [];
|
|
575
|
+
for (let j = 0; j < blocksPerLineForMcu; j++) {
|
|
576
576
|
row.push(new Int32Array(64));
|
|
577
577
|
}
|
|
578
578
|
blocks.push(row);
|
|
@@ -587,16 +587,16 @@ function parse(data) {
|
|
|
587
587
|
frame.mcusPerLine = mcusPerLine;
|
|
588
588
|
frame.mcusPerColumn = mcusPerColumn;
|
|
589
589
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
590
|
+
let jfif = null;
|
|
591
|
+
let adobe = null;
|
|
592
|
+
let frame = undefined;
|
|
593
|
+
let resetInterval = 0;
|
|
594
|
+
let quantizationTables = [];
|
|
595
|
+
let frames = [];
|
|
596
|
+
let huffmanTablesAC = [];
|
|
597
|
+
let huffmanTablesDC = [];
|
|
598
|
+
let fileMarker = readUint16();
|
|
599
|
+
let malformedDataOffset = -1;
|
|
600
600
|
if (fileMarker != 0xFFD8) { // SOI (Start of Image)
|
|
601
601
|
throw new Error('SOI not found');
|
|
602
602
|
}
|
|
@@ -621,10 +621,10 @@ function parse(data) {
|
|
|
621
621
|
case 0xFFEE: // APP14
|
|
622
622
|
case 0xFFEF: // APP15
|
|
623
623
|
case 0xFFFE: { // COM (Comment)
|
|
624
|
-
|
|
624
|
+
const appData = readDataBlock();
|
|
625
625
|
if (fileMarker === 0xFFFE) {
|
|
626
|
-
|
|
627
|
-
for (
|
|
626
|
+
let comment = '';
|
|
627
|
+
for (let ii = 0; ii < appData.byteLength; ii++) {
|
|
628
628
|
comment += String.fromCharCode(appData[ii]);
|
|
629
629
|
}
|
|
630
630
|
self.comments.push(comment);
|
|
@@ -667,21 +667,21 @@ function parse(data) {
|
|
|
667
667
|
break;
|
|
668
668
|
}
|
|
669
669
|
case 0xFFDB: { // DQT (Define Quantization Tables)
|
|
670
|
-
|
|
671
|
-
|
|
670
|
+
const quantizationTablesLength = readUint16();
|
|
671
|
+
const quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
|
672
672
|
while (offset < quantizationTablesEnd) {
|
|
673
|
-
|
|
673
|
+
const quantizationTableSpec = data[offset++];
|
|
674
674
|
requestMemoryAllocation(64 * 4);
|
|
675
|
-
|
|
675
|
+
const tableData = new Int32Array(64);
|
|
676
676
|
if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
|
|
677
|
-
for (
|
|
678
|
-
|
|
677
|
+
for (let j = 0; j < 64; j++) {
|
|
678
|
+
const z = dctZigZag[j];
|
|
679
679
|
tableData[z] = data[offset++];
|
|
680
680
|
}
|
|
681
681
|
}
|
|
682
682
|
else if ((quantizationTableSpec >> 4) === 1) { //16 bit
|
|
683
|
-
for (
|
|
684
|
-
|
|
683
|
+
for (let j = 0; j < 64; j++) {
|
|
684
|
+
const z = dctZigZag[j];
|
|
685
685
|
tableData[z] = readUint16();
|
|
686
686
|
}
|
|
687
687
|
}
|
|
@@ -708,17 +708,17 @@ function parse(data) {
|
|
|
708
708
|
mcusPerLine: 0,
|
|
709
709
|
mcusPerColumn: 0,
|
|
710
710
|
};
|
|
711
|
-
|
|
711
|
+
const pixelsInFrame = frame.scanLines * frame.samplesPerLine;
|
|
712
712
|
if (pixelsInFrame > maxResolutionInPixels) {
|
|
713
|
-
|
|
714
|
-
throw new Error(
|
|
713
|
+
const exceededAmount = Math.ceil((pixelsInFrame - maxResolutionInPixels) / 1e6);
|
|
714
|
+
throw new Error(`maxResolutionInMP limit exceeded by ${exceededAmount}MP`);
|
|
715
715
|
}
|
|
716
|
-
|
|
717
|
-
for (
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
716
|
+
const componentsCount = data[offset++];
|
|
717
|
+
for (let i = 0; i < componentsCount; i++) {
|
|
718
|
+
const componentId = data[offset];
|
|
719
|
+
const h = data[offset + 1] >> 4;
|
|
720
|
+
const v = data[offset + 1] & 15;
|
|
721
|
+
const qId = data[offset + 2];
|
|
722
722
|
frame.componentsOrder.push(componentId);
|
|
723
723
|
frame.components[componentId] = {
|
|
724
724
|
h: h,
|
|
@@ -736,22 +736,22 @@ function parse(data) {
|
|
|
736
736
|
break;
|
|
737
737
|
}
|
|
738
738
|
case 0xFFC4: { // DHT (Define Huffman Tables)
|
|
739
|
-
|
|
740
|
-
for (
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
for (
|
|
739
|
+
const huffmanLength = readUint16();
|
|
740
|
+
for (let i = 2; i < huffmanLength;) {
|
|
741
|
+
const huffmanTableSpec = data[offset++];
|
|
742
|
+
const codeLengths = new Uint8Array(16);
|
|
743
|
+
let codeLengthSum = 0;
|
|
744
|
+
for (let j = 0; j < 16; j++, offset++) {
|
|
745
745
|
codeLengthSum += (codeLengths[j] = data[offset]);
|
|
746
746
|
}
|
|
747
747
|
requestMemoryAllocation(16 + codeLengthSum);
|
|
748
|
-
|
|
749
|
-
for (
|
|
748
|
+
const huffmanValues = new Uint8Array(codeLengthSum);
|
|
749
|
+
for (let j = 0; j < codeLengthSum; j++, offset++) {
|
|
750
750
|
huffmanValues[j] = data[offset];
|
|
751
751
|
}
|
|
752
752
|
i += 17 + codeLengthSum;
|
|
753
|
-
|
|
754
|
-
|
|
753
|
+
const index = huffmanTableSpec & 15;
|
|
754
|
+
const table = (huffmanTableSpec >> 4) === 0 ? huffmanTablesDC : huffmanTablesAC;
|
|
755
755
|
table[index] = buildHuffmanTable(codeLengths, huffmanValues);
|
|
756
756
|
}
|
|
757
757
|
break;
|
|
@@ -766,19 +766,19 @@ function parse(data) {
|
|
|
766
766
|
break;
|
|
767
767
|
case 0xFFDA: { // SOS (Start of Scan)
|
|
768
768
|
readUint16(); // skip data length
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
for (
|
|
772
|
-
|
|
773
|
-
|
|
769
|
+
const selectorsCount = data[offset++];
|
|
770
|
+
const components = [];
|
|
771
|
+
for (let i = 0; i < selectorsCount; i++) {
|
|
772
|
+
const component = frame.components[data[offset++]];
|
|
773
|
+
const tableSpec = data[offset++];
|
|
774
774
|
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
|
|
775
775
|
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
|
|
776
776
|
components.push(component);
|
|
777
777
|
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
778
|
+
const spectralStart = data[offset++];
|
|
779
|
+
const spectralEnd = data[offset++];
|
|
780
|
+
const successiveApproximation = data[offset++];
|
|
781
|
+
const processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15);
|
|
782
782
|
offset += processed;
|
|
783
783
|
break;
|
|
784
784
|
}
|
|
@@ -798,10 +798,10 @@ function parse(data) {
|
|
|
798
798
|
// Recover from malformed APP1 markers popular in some phone models.
|
|
799
799
|
// See https://github.com/eugeneware/jpeg-js/issues/82
|
|
800
800
|
if (malformedDataOffset !== -1) {
|
|
801
|
-
throw new Error(
|
|
801
|
+
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)}`);
|
|
802
802
|
}
|
|
803
803
|
malformedDataOffset = offset - 1;
|
|
804
|
-
|
|
804
|
+
const nextOffset = readUint16();
|
|
805
805
|
if (data[offset + nextOffset - 2] === 0xFF) {
|
|
806
806
|
offset += nextOffset - 2;
|
|
807
807
|
break;
|
|
@@ -815,9 +815,9 @@ function parse(data) {
|
|
|
815
815
|
if (frames.length != 1)
|
|
816
816
|
throw new Error('only single frame JPEGs supported');
|
|
817
817
|
// set each frame's components quantization table
|
|
818
|
-
for (
|
|
819
|
-
|
|
820
|
-
for (
|
|
818
|
+
for (let i = 0; i < frames.length; i++) {
|
|
819
|
+
const cp = frames[i].components;
|
|
820
|
+
for (let j in cp) { // TODO: don't use `in`
|
|
821
821
|
cp[j].quantizationTable = quantizationTables[cp[j].quantizationIdx];
|
|
822
822
|
delete cp[j].quantizationIdx; // TODO: why ???
|
|
823
823
|
}
|
|
@@ -827,8 +827,8 @@ function parse(data) {
|
|
|
827
827
|
self.jfif = jfif;
|
|
828
828
|
self.adobe = adobe;
|
|
829
829
|
self.components = [];
|
|
830
|
-
for (
|
|
831
|
-
|
|
830
|
+
for (let i = 0; i < frame.componentsOrder.length; i++) {
|
|
831
|
+
const component = frame.components[frame.componentsOrder[i]];
|
|
832
832
|
self.components.push({
|
|
833
833
|
lines: buildComponentData(component),
|
|
834
834
|
scaleX: component.h / frame.maxH,
|
|
@@ -838,20 +838,20 @@ function parse(data) {
|
|
|
838
838
|
return self;
|
|
839
839
|
}
|
|
840
840
|
function getData(decoded) {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
841
|
+
let offset = 0;
|
|
842
|
+
let colorTransform = false;
|
|
843
|
+
const width = decoded.width;
|
|
844
|
+
const height = decoded.height;
|
|
845
|
+
const dataLength = width * height * decoded.components.length;
|
|
846
846
|
requestMemoryAllocation(dataLength);
|
|
847
|
-
|
|
847
|
+
const data = new Uint8Array(dataLength);
|
|
848
848
|
switch (decoded.components.length) {
|
|
849
849
|
case 1: {
|
|
850
|
-
|
|
851
|
-
for (
|
|
852
|
-
|
|
853
|
-
for (
|
|
854
|
-
|
|
850
|
+
const component1 = decoded.components[0];
|
|
851
|
+
for (let y = 0; y < height; y++) {
|
|
852
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
853
|
+
for (let x = 0; x < width; x++) {
|
|
854
|
+
const Y = component1Line[0 | (x * component1.scaleX)];
|
|
855
855
|
data[offset++] = Y;
|
|
856
856
|
}
|
|
857
857
|
}
|
|
@@ -859,15 +859,15 @@ function getData(decoded) {
|
|
|
859
859
|
}
|
|
860
860
|
case 2: {
|
|
861
861
|
// PDF might compress two component data in custom colorspace
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
for (
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
for (
|
|
868
|
-
|
|
862
|
+
const component1 = decoded.components[0];
|
|
863
|
+
const component2 = decoded.components[1];
|
|
864
|
+
for (let y = 0; y < height; y++) {
|
|
865
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
866
|
+
const component2Line = component2.lines[0 | (y * component2.scaleY)];
|
|
867
|
+
for (let x = 0; x < width; x++) {
|
|
868
|
+
const Y1 = component1Line[0 | (x * component1.scaleX)];
|
|
869
869
|
data[offset++] = Y1;
|
|
870
|
-
|
|
870
|
+
const Y2 = component2Line[0 | (x * component2.scaleX)];
|
|
871
871
|
data[offset++] = Y2;
|
|
872
872
|
}
|
|
873
873
|
}
|
|
@@ -879,15 +879,15 @@ function getData(decoded) {
|
|
|
879
879
|
// The adobe transform marker overrides any previous setting
|
|
880
880
|
if (decoded.adobe && decoded.adobe.transformCode)
|
|
881
881
|
colorTransform = true;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
for (
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
for (
|
|
890
|
-
|
|
882
|
+
const component1 = decoded.components[0];
|
|
883
|
+
const component2 = decoded.components[1];
|
|
884
|
+
const component3 = decoded.components[2];
|
|
885
|
+
for (let y = 0; y < height; y++) {
|
|
886
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
887
|
+
const component2Line = component2.lines[0 | (y * component2.scaleY)];
|
|
888
|
+
const component3Line = component3.lines[0 | (y * component3.scaleY)];
|
|
889
|
+
for (let x = 0; x < width; x++) {
|
|
890
|
+
let Y, Cb, Cr, R, G, B;
|
|
891
891
|
if (!colorTransform) {
|
|
892
892
|
R = component1Line[0 | (x * component1.scaleX)];
|
|
893
893
|
G = component2Line[0 | (x * component2.scaleX)];
|
|
@@ -916,17 +916,17 @@ function getData(decoded) {
|
|
|
916
916
|
// The adobe transform marker overrides any previous setting
|
|
917
917
|
if (decoded.adobe && decoded.adobe.transformCode)
|
|
918
918
|
colorTransform = true;
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
for (
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
for (
|
|
929
|
-
|
|
919
|
+
const component1 = decoded.components[0];
|
|
920
|
+
const component2 = decoded.components[1];
|
|
921
|
+
const component3 = decoded.components[2];
|
|
922
|
+
const component4 = decoded.components[3];
|
|
923
|
+
for (let y = 0; y < height; y++) {
|
|
924
|
+
const component1Line = component1.lines[0 | (y * component1.scaleY)];
|
|
925
|
+
const component2Line = component2.lines[0 | (y * component2.scaleY)];
|
|
926
|
+
const component3Line = component3.lines[0 | (y * component3.scaleY)];
|
|
927
|
+
const component4Line = component4.lines[0 | (y * component4.scaleY)];
|
|
928
|
+
for (let x = 0; x < width; x++) {
|
|
929
|
+
let Y, Cb, Cr, K, C, M, Ye;
|
|
930
930
|
if (!colorTransform) {
|
|
931
931
|
C = component1Line[0 | (x * component1.scaleX)];
|
|
932
932
|
M = component2Line[0 | (x * component2.scaleX)];
|
|
@@ -959,20 +959,20 @@ export function decodeJpeg(encoded, createImageData) {
|
|
|
959
959
|
totalBytesAllocated = 0;
|
|
960
960
|
if (encoded.length === 0)
|
|
961
961
|
throw new Error('Empty jpeg buffer');
|
|
962
|
-
|
|
962
|
+
const decoded = parse(encoded);
|
|
963
963
|
requestMemoryAllocation(decoded.width * decoded.height * 4);
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
964
|
+
const data = getData(decoded);
|
|
965
|
+
const imageData = createImageData(decoded.width, decoded.height);
|
|
966
|
+
const width = imageData.width;
|
|
967
|
+
const height = imageData.height;
|
|
968
|
+
const imageDataArray = imageData.data;
|
|
969
|
+
let i = 0;
|
|
970
|
+
let j = 0;
|
|
971
971
|
switch (decoded.components.length) {
|
|
972
972
|
case 1:
|
|
973
|
-
for (
|
|
974
|
-
for (
|
|
975
|
-
|
|
973
|
+
for (let y = 0; y < height; y++) {
|
|
974
|
+
for (let x = 0; x < width; x++) {
|
|
975
|
+
const Y = data[i++];
|
|
976
976
|
imageDataArray[j++] = Y;
|
|
977
977
|
imageDataArray[j++] = Y;
|
|
978
978
|
imageDataArray[j++] = Y;
|
|
@@ -981,11 +981,11 @@ export function decodeJpeg(encoded, createImageData) {
|
|
|
981
981
|
}
|
|
982
982
|
break;
|
|
983
983
|
case 3:
|
|
984
|
-
for (
|
|
985
|
-
for (
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
984
|
+
for (let y = 0; y < height; y++) {
|
|
985
|
+
for (let x = 0; x < width; x++) {
|
|
986
|
+
const R = data[i++];
|
|
987
|
+
const G = data[i++];
|
|
988
|
+
const B = data[i++];
|
|
989
989
|
imageDataArray[j++] = R;
|
|
990
990
|
imageDataArray[j++] = G;
|
|
991
991
|
imageDataArray[j++] = B;
|
|
@@ -994,15 +994,15 @@ export function decodeJpeg(encoded, createImageData) {
|
|
|
994
994
|
}
|
|
995
995
|
break;
|
|
996
996
|
case 4:
|
|
997
|
-
for (
|
|
998
|
-
for (
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
997
|
+
for (let y = 0; y < height; y++) {
|
|
998
|
+
for (let x = 0; x < width; x++) {
|
|
999
|
+
const C = data[i++];
|
|
1000
|
+
const M = data[i++];
|
|
1001
|
+
const Y = data[i++];
|
|
1002
|
+
const K = data[i++];
|
|
1003
|
+
const R = 255 - clampTo8bit(C * (1 - K / 255) + K);
|
|
1004
|
+
const G = 255 - clampTo8bit(M * (1 - K / 255) + K);
|
|
1005
|
+
const B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
|
|
1006
1006
|
imageDataArray[j++] = R;
|
|
1007
1007
|
imageDataArray[j++] = G;
|
|
1008
1008
|
imageDataArray[j++] = B;
|