pdf-parser.js 5.2.27 → 5.2.28
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/{afm-widths-BYiX2L9D.cjs → afm-widths-BHD2HZIL.cjs} +553 -642
- package/dist/{afm-widths-blUDDjlI.js → afm-widths-B_IGbGky.js} +553 -642
- package/dist/afm-widths.cjs +1 -1
- package/dist/afm-widths.js +1 -1
- package/dist/annotations.cjs +5 -3
- package/dist/annotations.js +5 -3
- package/dist/builtin-encoding.cjs +17 -6
- package/dist/builtin-encoding.js +17 -6
- package/dist/bytes/crc32.cjs +5 -3
- package/dist/bytes/crc32.js +5 -3
- package/dist/bytes/flate.cjs +0 -1
- package/dist/bytes/flate.js +0 -1
- package/dist/cff-bounds.cjs +42 -24
- package/dist/cff-bounds.js +42 -24
- package/dist/cff.cjs +13 -6
- package/dist/cff.js +13 -6
- package/dist/cmap-table.cjs +54 -26
- package/dist/cmap-table.js +54 -26
- package/dist/cmap.cjs +5 -3
- package/dist/cmap.js +5 -3
- package/dist/content-write.cjs +3 -2
- package/dist/content-write.js +3 -2
- package/dist/crypto/aes.cjs +76 -55
- package/dist/crypto/aes.js +76 -55
- package/dist/crypto/md5.cjs +345 -149
- package/dist/crypto/md5.js +345 -149
- package/dist/crypto/rc4.cjs +5 -4
- package/dist/crypto/rc4.js +5 -4
- package/dist/crypto/sha2.cjs +92 -43
- package/dist/crypto/sha2.js +92 -43
- package/dist/embedded-font.cjs +4 -2
- package/dist/embedded-font.js +4 -2
- package/dist/encoding.cjs +1 -1
- package/dist/encoding.js +1 -1
- package/dist/encrypt-write.cjs +25 -21
- package/dist/encrypt-write.js +25 -21
- package/dist/encrypt.cjs +43 -64
- package/dist/encrypt.js +43 -64
- package/dist/filters.cjs +40 -20
- package/dist/filters.js +40 -20
- package/dist/font-face.cjs +2 -1
- package/dist/font-face.js +2 -1
- package/dist/font-read.cjs +12 -6
- package/dist/font-read.js +12 -6
- package/dist/font-tables.cjs +55 -28
- package/dist/font-tables.js +55 -28
- package/dist/gdef-table.cjs +6 -3
- package/dist/gdef-table.js +6 -3
- package/dist/glyf-contours.cjs +3 -1
- package/dist/glyf-contours.js +3 -1
- package/dist/glyf.cjs +22 -11
- package/dist/glyf.js +22 -11
- package/dist/gpos-table.cjs +37 -19
- package/dist/gpos-table.js +37 -19
- package/dist/gsub-table.cjs +28 -17
- package/dist/gsub-table.js +28 -17
- package/dist/hmtx-table.cjs +5 -3
- package/dist/hmtx-table.js +5 -3
- package/dist/image/ccitt-encode.cjs +8 -5
- package/dist/image/ccitt-encode.js +8 -5
- package/dist/image/ccitt.cjs +801 -209
- package/dist/image/ccitt.js +801 -209
- package/dist/image/jbig2-arith.cjs +340 -306
- package/dist/image/jbig2-arith.js +340 -306
- package/dist/image/jbig2-bitmap.cjs +8 -5
- package/dist/image/jbig2-bitmap.js +8 -5
- package/dist/image/jbig2-generic.cjs +240 -69
- package/dist/image/jbig2-generic.js +240 -69
- package/dist/image/jbig2-text.cjs +4 -2
- package/dist/image/jbig2-text.js +4 -2
- package/dist/image/jbig2.cjs +69 -31
- package/dist/image/jbig2.js +69 -31
- package/dist/image/jp2-boxes.cjs +52 -27
- package/dist/image/jp2-boxes.js +52 -27
- package/dist/image/jpeg-info.cjs +29 -24
- package/dist/image/jpeg-info.js +29 -24
- package/dist/image/jpeg2000-codestream.cjs +44 -24
- package/dist/image/jpeg2000-codestream.js +44 -24
- package/dist/image/jpeg2000-dwt.cjs +2 -1
- package/dist/image/jpeg2000-dwt.js +2 -1
- package/dist/image/jpeg2000-t1.cjs +21 -11
- package/dist/image/jpeg2000-t1.js +21 -11
- package/dist/image/jpeg2000-t2.cjs +12 -5
- package/dist/image/jpeg2000-t2.js +12 -5
- package/dist/image/jpeg2000-tagtree.cjs +8 -4
- package/dist/image/jpeg2000-tagtree.js +8 -4
- package/dist/image/jpeg2000.cjs +11 -6
- package/dist/image/jpeg2000.js +11 -6
- package/dist/image/png-decode.cjs +62 -39
- package/dist/image/png-decode.d.cts +3 -2
- package/dist/image/png-decode.d.ts +3 -2
- package/dist/image/png-decode.js +62 -39
- package/dist/image/png-filter.cjs +23 -15
- package/dist/image/png-filter.js +23 -15
- package/dist/images-read.cjs +41 -36
- package/dist/images-read.js +41 -36
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/interpret.cjs +39 -24
- package/dist/interpret.js +39 -24
- package/dist/lexer.cjs +86 -51
- package/dist/lexer.js +86 -51
- package/dist/math-content-write.cjs +9 -5
- package/dist/math-content-write.js +9 -5
- package/dist/math-font-write.cjs +2 -1
- package/dist/math-font-write.js +2 -1
- package/dist/math-font.cjs +16 -7
- package/dist/math-font.js +16 -7
- package/dist/math-table.cjs +25 -13
- package/dist/math-table.js +25 -13
- package/dist/matrix.cjs +3 -2
- package/dist/matrix.js +3 -2
- package/dist/measure.cjs +1 -1
- package/dist/measure.js +1 -1
- package/dist/navigation.cjs +10 -5
- package/dist/navigation.js +10 -5
- package/dist/ot-layout-common.cjs +4 -2
- package/dist/ot-layout-common.js +4 -2
- package/dist/parse.cjs +7 -5
- package/dist/parse.js +7 -5
- package/dist/pdf-text.cjs +5 -2
- package/dist/pdf-text.js +5 -2
- package/dist/predictors.cjs +14 -9
- package/dist/predictors.js +14 -9
- package/dist/raster.cjs +30 -19
- package/dist/raster.js +30 -19
- package/dist/read.cjs +17 -8
- package/dist/read.js +17 -8
- package/dist/serialize.cjs +6 -2
- package/dist/serialize.js +6 -2
- package/dist/sfnt-subset.cjs +25 -13
- package/dist/sfnt-subset.js +25 -13
- package/dist/sfnt.cjs +20 -10
- package/dist/sfnt.js +20 -10
- package/dist/text-group.cjs +0 -1
- package/dist/text-group.js +0 -1
- package/dist/tounicode.cjs +4 -2
- package/dist/tounicode.js +4 -2
- package/dist/winansi.cjs +1 -1
- package/dist/winansi.js +1 -1
- package/dist/write.cjs +20 -12
- package/dist/write.js +20 -12
- package/dist/xref.cjs +5 -2
- package/dist/xref.js +5 -2
- package/package.json +1 -1
|
@@ -15,6 +15,11 @@ const MARKER_COM = 65380;
|
|
|
15
15
|
const MARKER_SOT = 65424;
|
|
16
16
|
const MARKER_SOD = 65427;
|
|
17
17
|
const MARKER_EOC = 65497;
|
|
18
|
+
const BITS_PER_BYTE = 8;
|
|
19
|
+
const HEX_RADIX = 16;
|
|
20
|
+
const NIBBLE_MASK = 15;
|
|
21
|
+
const NIBBLE_BITS = 4;
|
|
22
|
+
const UINT16_MODULUS = 65536;
|
|
18
23
|
var MarkerCursor = class {
|
|
19
24
|
data;
|
|
20
25
|
position;
|
|
@@ -32,10 +37,10 @@ var MarkerCursor = class {
|
|
|
32
37
|
return value;
|
|
33
38
|
}
|
|
34
39
|
uint16() {
|
|
35
|
-
return this.uint8() <<
|
|
40
|
+
return this.uint8() << BITS_PER_BYTE | this.uint8();
|
|
36
41
|
}
|
|
37
42
|
uint32() {
|
|
38
|
-
return this.uint16() *
|
|
43
|
+
return this.uint16() * UINT16_MODULUS + this.uint16();
|
|
39
44
|
}
|
|
40
45
|
bytes(length) {
|
|
41
46
|
if (length < 0 || this.position + length > this.data.length) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a JPEG 2000 marker segment declares more data than the codestream carries");
|
|
@@ -44,6 +49,9 @@ var MarkerCursor = class {
|
|
|
44
49
|
return slice;
|
|
45
50
|
}
|
|
46
51
|
};
|
|
52
|
+
const SIZ_COMPONENT_RECORD_SIZE = 3;
|
|
53
|
+
const SSIZ_SIGNED_BIT = 128;
|
|
54
|
+
const SSIZ_BIT_DEPTH_MASK = 127;
|
|
47
55
|
function readImageSize(cursor, segmentEnd) {
|
|
48
56
|
cursor.uint16();
|
|
49
57
|
const xsiz = cursor.uint32();
|
|
@@ -56,13 +64,13 @@ function readImageSize(cursor, segmentEnd) {
|
|
|
56
64
|
const ytosiz = cursor.uint32();
|
|
57
65
|
const count = cursor.uint16();
|
|
58
66
|
if (count === 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("SIZ declares zero components");
|
|
59
|
-
if (cursor.position + count *
|
|
67
|
+
if (cursor.position + count * SIZ_COMPONENT_RECORD_SIZE > segmentEnd) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SIZ declares ${String(count)} components but its own length leaves room for fewer`);
|
|
60
68
|
const components = [];
|
|
61
69
|
for (let i = 0; i < count; i++) {
|
|
62
70
|
const ssiz = cursor.uint8();
|
|
63
71
|
components.push({
|
|
64
|
-
signed: (ssiz &
|
|
65
|
-
bitDepth: (ssiz &
|
|
72
|
+
signed: (ssiz & SSIZ_SIGNED_BIT) !== 0,
|
|
73
|
+
bitDepth: (ssiz & SSIZ_BIT_DEPTH_MASK) + 1,
|
|
66
74
|
dx: cursor.uint8(),
|
|
67
75
|
dy: cursor.uint8()
|
|
68
76
|
});
|
|
@@ -82,20 +90,21 @@ function readImageSize(cursor, segmentEnd) {
|
|
|
82
90
|
};
|
|
83
91
|
}
|
|
84
92
|
const DEFAULT_PRECINCT_EXPONENT = 15;
|
|
93
|
+
const CODE_BLOCK_AREA_EXPONENT_MAX = 12;
|
|
85
94
|
function readCodingStyleParameters(cursor, explicitPrecincts) {
|
|
86
95
|
const decompositionLevels = cursor.uint8();
|
|
87
|
-
const codeBlockWidthExp = (cursor.uint8() &
|
|
88
|
-
const codeBlockHeightExp = (cursor.uint8() &
|
|
96
|
+
const codeBlockWidthExp = (cursor.uint8() & NIBBLE_MASK) + 2;
|
|
97
|
+
const codeBlockHeightExp = (cursor.uint8() & NIBBLE_MASK) + 2;
|
|
89
98
|
const codeBlockStyle = cursor.uint8();
|
|
90
99
|
const transformCode = cursor.uint8();
|
|
91
100
|
if (transformCode !== 0 && transformCode !== 1) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SPcod/SPcoc declares transformation ${String(transformCode)}, which is neither of the two ISO/IEC 15444-1 defines`);
|
|
92
|
-
if (codeBlockWidthExp + codeBlockHeightExp >
|
|
101
|
+
if (codeBlockWidthExp + codeBlockHeightExp > CODE_BLOCK_AREA_EXPONENT_MAX) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`code-block size 2^${String(codeBlockWidthExp)} by 2^${String(codeBlockHeightExp)} is outside the range ISO/IEC 15444-1 Table A.18 permits`);
|
|
93
102
|
const precinctSizes = [];
|
|
94
103
|
if (explicitPrecincts) for (let r = 0; r <= decompositionLevels; r++) {
|
|
95
104
|
const packed = cursor.uint8();
|
|
96
105
|
precinctSizes.push({
|
|
97
|
-
ppx: packed &
|
|
98
|
-
ppy: packed >>
|
|
106
|
+
ppx: packed & NIBBLE_MASK,
|
|
107
|
+
ppy: packed >> NIBBLE_BITS & NIBBLE_MASK
|
|
99
108
|
});
|
|
100
109
|
}
|
|
101
110
|
else for (let r = 0; r <= decompositionLevels; r++) precinctSizes.push({
|
|
@@ -111,6 +120,7 @@ function readCodingStyleParameters(cursor, explicitPrecincts) {
|
|
|
111
120
|
precinctSizes
|
|
112
121
|
};
|
|
113
122
|
}
|
|
123
|
+
const SCOD_USE_EPH_BIT = 4;
|
|
114
124
|
function readCodingDefaults(cursor) {
|
|
115
125
|
const progressionOrders = [
|
|
116
126
|
"LRCP",
|
|
@@ -131,17 +141,22 @@ function readCodingDefaults(cursor) {
|
|
|
131
141
|
layers,
|
|
132
142
|
multipleComponentTransform,
|
|
133
143
|
useSop: (scod & 2) !== 0,
|
|
134
|
-
useEph: (scod &
|
|
144
|
+
useEph: (scod & SCOD_USE_EPH_BIT) !== 0
|
|
135
145
|
};
|
|
136
146
|
}
|
|
147
|
+
const SQCD_GUARD_BITS_SHIFT = 5;
|
|
148
|
+
const SQCD_STYLE_MASK = 31;
|
|
149
|
+
const SPQCD_NONE_EXPONENT_SHIFT = 3;
|
|
150
|
+
const SPQCD_EXPONENT_SHIFT = 11;
|
|
151
|
+
const SPQCD_MANTISSA_MASK = 2047;
|
|
137
152
|
function readQuantization(cursor, segmentEnd) {
|
|
138
153
|
const sq = cursor.uint8();
|
|
139
|
-
const guardBits = sq >>
|
|
140
|
-
const styleCode = sq &
|
|
154
|
+
const guardBits = sq >> SQCD_GUARD_BITS_SHIFT;
|
|
155
|
+
const styleCode = sq & SQCD_STYLE_MASK;
|
|
141
156
|
const stepSizes = [];
|
|
142
157
|
if (styleCode === 0) {
|
|
143
158
|
while (cursor.position < segmentEnd) stepSizes.push({
|
|
144
|
-
exponent: cursor.uint8() >>
|
|
159
|
+
exponent: cursor.uint8() >> SPQCD_NONE_EXPONENT_SHIFT,
|
|
145
160
|
mantissa: 0
|
|
146
161
|
});
|
|
147
162
|
return {
|
|
@@ -154,8 +169,8 @@ function readQuantization(cursor, segmentEnd) {
|
|
|
154
169
|
while (cursor.position + 1 < segmentEnd) {
|
|
155
170
|
const packed = cursor.uint16();
|
|
156
171
|
stepSizes.push({
|
|
157
|
-
exponent: packed >>
|
|
158
|
-
mantissa: packed &
|
|
172
|
+
exponent: packed >> SPQCD_EXPONENT_SHIFT,
|
|
173
|
+
mantissa: packed & SPQCD_MANTISSA_MASK
|
|
159
174
|
});
|
|
160
175
|
}
|
|
161
176
|
return {
|
|
@@ -166,8 +181,9 @@ function readQuantization(cursor, segmentEnd) {
|
|
|
166
181
|
}
|
|
167
182
|
throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`QCD/QCC declares quantization style ${String(styleCode)}, which ISO/IEC 15444-1 Table A.28 does not define`);
|
|
168
183
|
}
|
|
184
|
+
const COMPONENT_INDEX_WIDTH_THRESHOLD = 257;
|
|
169
185
|
function readComponentIndex(cursor, componentCount) {
|
|
170
|
-
return componentCount <
|
|
186
|
+
return componentCount < COMPONENT_INDEX_WIDTH_THRESHOLD ? cursor.uint8() : cursor.uint16();
|
|
171
187
|
}
|
|
172
188
|
function emptyHeader() {
|
|
173
189
|
return {
|
|
@@ -212,9 +228,9 @@ var CodestreamComments = class {
|
|
|
212
228
|
};
|
|
213
229
|
function readHeaderSegment(marker, cursor, header, componentCount, comments) {
|
|
214
230
|
const length = cursor.uint16();
|
|
215
|
-
if (length < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(
|
|
231
|
+
if (length < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares a length of ${String(length)}, which is shorter than the length field itself`);
|
|
216
232
|
const segmentEnd = cursor.position + length - 2;
|
|
217
|
-
if (segmentEnd > cursor.data.length) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(
|
|
233
|
+
if (segmentEnd > cursor.data.length) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares more data than the codestream carries`);
|
|
218
234
|
if (marker === MARKER_COD) header.cod = readCodingDefaults(cursor);
|
|
219
235
|
else if (marker === MARKER_COC) {
|
|
220
236
|
const component = readComponentIndex(cursor, componentCount);
|
|
@@ -237,9 +253,10 @@ function validateMainHeader(header) {
|
|
|
237
253
|
if (header.cod === void 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the main header carries no COD marker, so no coding style is defined for any tile");
|
|
238
254
|
if (header.qcd === void 0) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the main header carries no QCD marker, so no quantization is defined for any tile");
|
|
239
255
|
}
|
|
256
|
+
const MIN_HEADER_BYTES = 4;
|
|
240
257
|
function parseJpeg2000Codestream(data) {
|
|
241
258
|
const cursor = new MarkerCursor(data);
|
|
242
|
-
if (cursor.remaining <
|
|
259
|
+
if (cursor.remaining < MIN_HEADER_BYTES || cursor.uint16() !== MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("codestream does not begin with an SOC marker");
|
|
243
260
|
if (cursor.uint16() !== MARKER_SIZ) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("the SOC marker is not immediately followed by SIZ, which ISO/IEC 15444-1 A.3 requires");
|
|
244
261
|
const sizLength = cursor.uint16();
|
|
245
262
|
const sizEnd = cursor.position + sizLength - 2;
|
|
@@ -262,7 +279,7 @@ function parseJpeg2000Codestream(data) {
|
|
|
262
279
|
tileParts.push(readTilePart(cursor, siz.components.length, comments));
|
|
263
280
|
continue;
|
|
264
281
|
}
|
|
265
|
-
if (marker === MARKER_SOD || marker === MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`unexpected marker 0x${marker.toString(
|
|
282
|
+
if (marker === MARKER_SOD || marker === MARKER_SOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`unexpected marker 0x${marker.toString(HEX_RADIX)} in the main header`);
|
|
266
283
|
readHeaderSegment(marker, cursor, main, siz.components.length, comments);
|
|
267
284
|
}
|
|
268
285
|
validateMainHeader(main);
|
|
@@ -279,11 +296,12 @@ function parseJpeg2000Codestream(data) {
|
|
|
279
296
|
truncated: !sawEoc
|
|
280
297
|
};
|
|
281
298
|
}
|
|
299
|
+
const SOT_SEGMENT_LENGTH = 10;
|
|
282
300
|
function readTilePart(cursor, componentCount, comments) {
|
|
283
301
|
const sotStart = cursor.position;
|
|
284
302
|
cursor.uint16();
|
|
285
303
|
const lsot = cursor.uint16();
|
|
286
|
-
if (lsot !==
|
|
304
|
+
if (lsot !== SOT_SEGMENT_LENGTH) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`SOT declares a length of ${String(lsot)}, but ISO/IEC 15444-1 A.4.2 fixes it at 10`);
|
|
287
305
|
const tileIndex = cursor.uint16();
|
|
288
306
|
const psot = cursor.uint32();
|
|
289
307
|
const partIndex = cursor.uint8();
|
|
@@ -293,7 +311,7 @@ function readTilePart(cursor, componentCount, comments) {
|
|
|
293
311
|
if (cursor.remaining < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a tile-part header ended without an SOD marker");
|
|
294
312
|
const marker = cursor.uint16();
|
|
295
313
|
if (marker === MARKER_SOD) break;
|
|
296
|
-
if (marker === MARKER_SOT || marker === MARKER_EOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(
|
|
314
|
+
if (marker === MARKER_SOT || marker === MARKER_EOC) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(HEX_RADIX)} rather than at SOD`);
|
|
297
315
|
readHeaderSegment(marker, cursor, header, componentCount, comments);
|
|
298
316
|
}
|
|
299
317
|
const dataStart = cursor.position;
|
|
@@ -310,8 +328,10 @@ function readTilePart(cursor, componentCount, comments) {
|
|
|
310
328
|
dataEnd: trimmedEnd
|
|
311
329
|
};
|
|
312
330
|
}
|
|
331
|
+
const MARKER_EOC_HIGH_BYTE = 255;
|
|
332
|
+
const MARKER_EOC_LOW_BYTE = 217;
|
|
313
333
|
function trimTrailingEoc(data, end) {
|
|
314
|
-
if (data[end - 2] ===
|
|
334
|
+
if (data[end - 2] === MARKER_EOC_HIGH_BYTE && data[end - 1] === MARKER_EOC_LOW_BYTE) return end - 2;
|
|
315
335
|
return end;
|
|
316
336
|
}
|
|
317
337
|
//#endregion
|
|
@@ -14,6 +14,11 @@ const MARKER_COM = 65380;
|
|
|
14
14
|
const MARKER_SOT = 65424;
|
|
15
15
|
const MARKER_SOD = 65427;
|
|
16
16
|
const MARKER_EOC = 65497;
|
|
17
|
+
const BITS_PER_BYTE = 8;
|
|
18
|
+
const HEX_RADIX = 16;
|
|
19
|
+
const NIBBLE_MASK = 15;
|
|
20
|
+
const NIBBLE_BITS = 4;
|
|
21
|
+
const UINT16_MODULUS = 65536;
|
|
17
22
|
var MarkerCursor = class {
|
|
18
23
|
data;
|
|
19
24
|
position;
|
|
@@ -31,10 +36,10 @@ var MarkerCursor = class {
|
|
|
31
36
|
return value;
|
|
32
37
|
}
|
|
33
38
|
uint16() {
|
|
34
|
-
return this.uint8() <<
|
|
39
|
+
return this.uint8() << BITS_PER_BYTE | this.uint8();
|
|
35
40
|
}
|
|
36
41
|
uint32() {
|
|
37
|
-
return this.uint16() *
|
|
42
|
+
return this.uint16() * UINT16_MODULUS + this.uint16();
|
|
38
43
|
}
|
|
39
44
|
bytes(length) {
|
|
40
45
|
if (length < 0 || this.position + length > this.data.length) throw new Jpeg2000ParseError("a JPEG 2000 marker segment declares more data than the codestream carries");
|
|
@@ -43,6 +48,9 @@ var MarkerCursor = class {
|
|
|
43
48
|
return slice;
|
|
44
49
|
}
|
|
45
50
|
};
|
|
51
|
+
const SIZ_COMPONENT_RECORD_SIZE = 3;
|
|
52
|
+
const SSIZ_SIGNED_BIT = 128;
|
|
53
|
+
const SSIZ_BIT_DEPTH_MASK = 127;
|
|
46
54
|
function readImageSize(cursor, segmentEnd) {
|
|
47
55
|
cursor.uint16();
|
|
48
56
|
const xsiz = cursor.uint32();
|
|
@@ -55,13 +63,13 @@ function readImageSize(cursor, segmentEnd) {
|
|
|
55
63
|
const ytosiz = cursor.uint32();
|
|
56
64
|
const count = cursor.uint16();
|
|
57
65
|
if (count === 0) throw new Jpeg2000ParseError("SIZ declares zero components");
|
|
58
|
-
if (cursor.position + count *
|
|
66
|
+
if (cursor.position + count * SIZ_COMPONENT_RECORD_SIZE > segmentEnd) throw new Jpeg2000ParseError(`SIZ declares ${String(count)} components but its own length leaves room for fewer`);
|
|
59
67
|
const components = [];
|
|
60
68
|
for (let i = 0; i < count; i++) {
|
|
61
69
|
const ssiz = cursor.uint8();
|
|
62
70
|
components.push({
|
|
63
|
-
signed: (ssiz &
|
|
64
|
-
bitDepth: (ssiz &
|
|
71
|
+
signed: (ssiz & SSIZ_SIGNED_BIT) !== 0,
|
|
72
|
+
bitDepth: (ssiz & SSIZ_BIT_DEPTH_MASK) + 1,
|
|
65
73
|
dx: cursor.uint8(),
|
|
66
74
|
dy: cursor.uint8()
|
|
67
75
|
});
|
|
@@ -81,20 +89,21 @@ function readImageSize(cursor, segmentEnd) {
|
|
|
81
89
|
};
|
|
82
90
|
}
|
|
83
91
|
const DEFAULT_PRECINCT_EXPONENT = 15;
|
|
92
|
+
const CODE_BLOCK_AREA_EXPONENT_MAX = 12;
|
|
84
93
|
function readCodingStyleParameters(cursor, explicitPrecincts) {
|
|
85
94
|
const decompositionLevels = cursor.uint8();
|
|
86
|
-
const codeBlockWidthExp = (cursor.uint8() &
|
|
87
|
-
const codeBlockHeightExp = (cursor.uint8() &
|
|
95
|
+
const codeBlockWidthExp = (cursor.uint8() & NIBBLE_MASK) + 2;
|
|
96
|
+
const codeBlockHeightExp = (cursor.uint8() & NIBBLE_MASK) + 2;
|
|
88
97
|
const codeBlockStyle = cursor.uint8();
|
|
89
98
|
const transformCode = cursor.uint8();
|
|
90
99
|
if (transformCode !== 0 && transformCode !== 1) throw new Jpeg2000ParseError(`SPcod/SPcoc declares transformation ${String(transformCode)}, which is neither of the two ISO/IEC 15444-1 defines`);
|
|
91
|
-
if (codeBlockWidthExp + codeBlockHeightExp >
|
|
100
|
+
if (codeBlockWidthExp + codeBlockHeightExp > CODE_BLOCK_AREA_EXPONENT_MAX) throw new Jpeg2000ParseError(`code-block size 2^${String(codeBlockWidthExp)} by 2^${String(codeBlockHeightExp)} is outside the range ISO/IEC 15444-1 Table A.18 permits`);
|
|
92
101
|
const precinctSizes = [];
|
|
93
102
|
if (explicitPrecincts) for (let r = 0; r <= decompositionLevels; r++) {
|
|
94
103
|
const packed = cursor.uint8();
|
|
95
104
|
precinctSizes.push({
|
|
96
|
-
ppx: packed &
|
|
97
|
-
ppy: packed >>
|
|
105
|
+
ppx: packed & NIBBLE_MASK,
|
|
106
|
+
ppy: packed >> NIBBLE_BITS & NIBBLE_MASK
|
|
98
107
|
});
|
|
99
108
|
}
|
|
100
109
|
else for (let r = 0; r <= decompositionLevels; r++) precinctSizes.push({
|
|
@@ -110,6 +119,7 @@ function readCodingStyleParameters(cursor, explicitPrecincts) {
|
|
|
110
119
|
precinctSizes
|
|
111
120
|
};
|
|
112
121
|
}
|
|
122
|
+
const SCOD_USE_EPH_BIT = 4;
|
|
113
123
|
function readCodingDefaults(cursor) {
|
|
114
124
|
const progressionOrders = [
|
|
115
125
|
"LRCP",
|
|
@@ -130,17 +140,22 @@ function readCodingDefaults(cursor) {
|
|
|
130
140
|
layers,
|
|
131
141
|
multipleComponentTransform,
|
|
132
142
|
useSop: (scod & 2) !== 0,
|
|
133
|
-
useEph: (scod &
|
|
143
|
+
useEph: (scod & SCOD_USE_EPH_BIT) !== 0
|
|
134
144
|
};
|
|
135
145
|
}
|
|
146
|
+
const SQCD_GUARD_BITS_SHIFT = 5;
|
|
147
|
+
const SQCD_STYLE_MASK = 31;
|
|
148
|
+
const SPQCD_NONE_EXPONENT_SHIFT = 3;
|
|
149
|
+
const SPQCD_EXPONENT_SHIFT = 11;
|
|
150
|
+
const SPQCD_MANTISSA_MASK = 2047;
|
|
136
151
|
function readQuantization(cursor, segmentEnd) {
|
|
137
152
|
const sq = cursor.uint8();
|
|
138
|
-
const guardBits = sq >>
|
|
139
|
-
const styleCode = sq &
|
|
153
|
+
const guardBits = sq >> SQCD_GUARD_BITS_SHIFT;
|
|
154
|
+
const styleCode = sq & SQCD_STYLE_MASK;
|
|
140
155
|
const stepSizes = [];
|
|
141
156
|
if (styleCode === 0) {
|
|
142
157
|
while (cursor.position < segmentEnd) stepSizes.push({
|
|
143
|
-
exponent: cursor.uint8() >>
|
|
158
|
+
exponent: cursor.uint8() >> SPQCD_NONE_EXPONENT_SHIFT,
|
|
144
159
|
mantissa: 0
|
|
145
160
|
});
|
|
146
161
|
return {
|
|
@@ -153,8 +168,8 @@ function readQuantization(cursor, segmentEnd) {
|
|
|
153
168
|
while (cursor.position + 1 < segmentEnd) {
|
|
154
169
|
const packed = cursor.uint16();
|
|
155
170
|
stepSizes.push({
|
|
156
|
-
exponent: packed >>
|
|
157
|
-
mantissa: packed &
|
|
171
|
+
exponent: packed >> SPQCD_EXPONENT_SHIFT,
|
|
172
|
+
mantissa: packed & SPQCD_MANTISSA_MASK
|
|
158
173
|
});
|
|
159
174
|
}
|
|
160
175
|
return {
|
|
@@ -165,8 +180,9 @@ function readQuantization(cursor, segmentEnd) {
|
|
|
165
180
|
}
|
|
166
181
|
throw new Jpeg2000ParseError(`QCD/QCC declares quantization style ${String(styleCode)}, which ISO/IEC 15444-1 Table A.28 does not define`);
|
|
167
182
|
}
|
|
183
|
+
const COMPONENT_INDEX_WIDTH_THRESHOLD = 257;
|
|
168
184
|
function readComponentIndex(cursor, componentCount) {
|
|
169
|
-
return componentCount <
|
|
185
|
+
return componentCount < COMPONENT_INDEX_WIDTH_THRESHOLD ? cursor.uint8() : cursor.uint16();
|
|
170
186
|
}
|
|
171
187
|
function emptyHeader() {
|
|
172
188
|
return {
|
|
@@ -211,9 +227,9 @@ var CodestreamComments = class {
|
|
|
211
227
|
};
|
|
212
228
|
function readHeaderSegment(marker, cursor, header, componentCount, comments) {
|
|
213
229
|
const length = cursor.uint16();
|
|
214
|
-
if (length < 2) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(
|
|
230
|
+
if (length < 2) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares a length of ${String(length)}, which is shorter than the length field itself`);
|
|
215
231
|
const segmentEnd = cursor.position + length - 2;
|
|
216
|
-
if (segmentEnd > cursor.data.length) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(
|
|
232
|
+
if (segmentEnd > cursor.data.length) throw new Jpeg2000ParseError(`marker segment 0x${marker.toString(HEX_RADIX)} declares more data than the codestream carries`);
|
|
217
233
|
if (marker === MARKER_COD) header.cod = readCodingDefaults(cursor);
|
|
218
234
|
else if (marker === MARKER_COC) {
|
|
219
235
|
const component = readComponentIndex(cursor, componentCount);
|
|
@@ -236,9 +252,10 @@ function validateMainHeader(header) {
|
|
|
236
252
|
if (header.cod === void 0) throw new Jpeg2000ParseError("the main header carries no COD marker, so no coding style is defined for any tile");
|
|
237
253
|
if (header.qcd === void 0) throw new Jpeg2000ParseError("the main header carries no QCD marker, so no quantization is defined for any tile");
|
|
238
254
|
}
|
|
255
|
+
const MIN_HEADER_BYTES = 4;
|
|
239
256
|
function parseJpeg2000Codestream(data) {
|
|
240
257
|
const cursor = new MarkerCursor(data);
|
|
241
|
-
if (cursor.remaining <
|
|
258
|
+
if (cursor.remaining < MIN_HEADER_BYTES || cursor.uint16() !== MARKER_SOC) throw new Jpeg2000ParseError("codestream does not begin with an SOC marker");
|
|
242
259
|
if (cursor.uint16() !== MARKER_SIZ) throw new Jpeg2000ParseError("the SOC marker is not immediately followed by SIZ, which ISO/IEC 15444-1 A.3 requires");
|
|
243
260
|
const sizLength = cursor.uint16();
|
|
244
261
|
const sizEnd = cursor.position + sizLength - 2;
|
|
@@ -261,7 +278,7 @@ function parseJpeg2000Codestream(data) {
|
|
|
261
278
|
tileParts.push(readTilePart(cursor, siz.components.length, comments));
|
|
262
279
|
continue;
|
|
263
280
|
}
|
|
264
|
-
if (marker === MARKER_SOD || marker === MARKER_SOC) throw new Jpeg2000ParseError(`unexpected marker 0x${marker.toString(
|
|
281
|
+
if (marker === MARKER_SOD || marker === MARKER_SOC) throw new Jpeg2000ParseError(`unexpected marker 0x${marker.toString(HEX_RADIX)} in the main header`);
|
|
265
282
|
readHeaderSegment(marker, cursor, main, siz.components.length, comments);
|
|
266
283
|
}
|
|
267
284
|
validateMainHeader(main);
|
|
@@ -278,11 +295,12 @@ function parseJpeg2000Codestream(data) {
|
|
|
278
295
|
truncated: !sawEoc
|
|
279
296
|
};
|
|
280
297
|
}
|
|
298
|
+
const SOT_SEGMENT_LENGTH = 10;
|
|
281
299
|
function readTilePart(cursor, componentCount, comments) {
|
|
282
300
|
const sotStart = cursor.position;
|
|
283
301
|
cursor.uint16();
|
|
284
302
|
const lsot = cursor.uint16();
|
|
285
|
-
if (lsot !==
|
|
303
|
+
if (lsot !== SOT_SEGMENT_LENGTH) throw new Jpeg2000ParseError(`SOT declares a length of ${String(lsot)}, but ISO/IEC 15444-1 A.4.2 fixes it at 10`);
|
|
286
304
|
const tileIndex = cursor.uint16();
|
|
287
305
|
const psot = cursor.uint32();
|
|
288
306
|
const partIndex = cursor.uint8();
|
|
@@ -292,7 +310,7 @@ function readTilePart(cursor, componentCount, comments) {
|
|
|
292
310
|
if (cursor.remaining < 2) throw new Jpeg2000ParseError("a tile-part header ended without an SOD marker");
|
|
293
311
|
const marker = cursor.uint16();
|
|
294
312
|
if (marker === MARKER_SOD) break;
|
|
295
|
-
if (marker === MARKER_SOT || marker === MARKER_EOC) throw new Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(
|
|
313
|
+
if (marker === MARKER_SOT || marker === MARKER_EOC) throw new Jpeg2000ParseError(`a tile-part header ended at marker 0x${marker.toString(HEX_RADIX)} rather than at SOD`);
|
|
296
314
|
readHeaderSegment(marker, cursor, header, componentCount, comments);
|
|
297
315
|
}
|
|
298
316
|
const dataStart = cursor.position;
|
|
@@ -309,8 +327,10 @@ function readTilePart(cursor, componentCount, comments) {
|
|
|
309
327
|
dataEnd: trimmedEnd
|
|
310
328
|
};
|
|
311
329
|
}
|
|
330
|
+
const MARKER_EOC_HIGH_BYTE = 255;
|
|
331
|
+
const MARKER_EOC_LOW_BYTE = 217;
|
|
312
332
|
function trimTrailingEoc(data, end) {
|
|
313
|
-
if (data[end - 2] ===
|
|
333
|
+
if (data[end - 2] === MARKER_EOC_HIGH_BYTE && data[end - 1] === MARKER_EOC_LOW_BYTE) return end - 2;
|
|
314
334
|
return end;
|
|
315
335
|
}
|
|
316
336
|
//#endregion
|
|
@@ -30,13 +30,14 @@ function interleave(source, bounds, write) {
|
|
|
30
30
|
for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.llU0; u < sub.llU1; u++) write(2 * u, 2 * v + 1, source.lh(u, v));
|
|
31
31
|
for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.hU0; u < sub.hU1; u++) write(2 * u + 1, 2 * v + 1, source.hh(u, v));
|
|
32
32
|
}
|
|
33
|
+
const LOW_PASS_UPDATE_DIVISOR = 4;
|
|
33
34
|
function inverse53Filter(buffer, i0, i1) {
|
|
34
35
|
const base = EXTENSION_MARGIN - i0;
|
|
35
36
|
const first = Math.floor(i0 / 2) - 1;
|
|
36
37
|
const last = Math.floor(i1 / 2) + 1;
|
|
37
38
|
for (let n = first; n <= last; n++) {
|
|
38
39
|
const index = base + 2 * n;
|
|
39
|
-
buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) /
|
|
40
|
+
buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) / LOW_PASS_UPDATE_DIVISOR);
|
|
40
41
|
}
|
|
41
42
|
for (let n = first; n < last; n++) {
|
|
42
43
|
const index = base + 2 * n + 1;
|
|
@@ -29,13 +29,14 @@ function interleave(source, bounds, write) {
|
|
|
29
29
|
for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.llU0; u < sub.llU1; u++) write(2 * u, 2 * v + 1, source.lh(u, v));
|
|
30
30
|
for (let v = sub.hV0; v < sub.hV1; v++) for (let u = sub.hU0; u < sub.hU1; u++) write(2 * u + 1, 2 * v + 1, source.hh(u, v));
|
|
31
31
|
}
|
|
32
|
+
const LOW_PASS_UPDATE_DIVISOR = 4;
|
|
32
33
|
function inverse53Filter(buffer, i0, i1) {
|
|
33
34
|
const base = EXTENSION_MARGIN - i0;
|
|
34
35
|
const first = Math.floor(i0 / 2) - 1;
|
|
35
36
|
const last = Math.floor(i1 / 2) + 1;
|
|
36
37
|
for (let n = first; n <= last; n++) {
|
|
37
38
|
const index = base + 2 * n;
|
|
38
|
-
buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) /
|
|
39
|
+
buffer[index] = (buffer[index] ?? 0) - Math.floor(((buffer[index - 1] ?? 0) + (buffer[index + 1] ?? 0) + 2) / LOW_PASS_UPDATE_DIVISOR);
|
|
39
40
|
}
|
|
40
41
|
for (let n = first; n < last; n++) {
|
|
41
42
|
const index = base + 2 * n + 1;
|
|
@@ -15,7 +15,9 @@ const STYLE_TERMINATE_ALL = 4;
|
|
|
15
15
|
const STYLE_VERTICALLY_CAUSAL = 8;
|
|
16
16
|
const STYLE_SEGMENTATION_SYMBOLS = 32;
|
|
17
17
|
const SEGMENTATION_SYMBOL = 10;
|
|
18
|
+
const SEGMENTATION_SYMBOL_MSB_SHIFT = 3;
|
|
18
19
|
const STRIPE_HEIGHT = 4;
|
|
20
|
+
const HEX_RADIX = 16;
|
|
19
21
|
const PASS_SIGNIFICANCE = 0;
|
|
20
22
|
const PASS_REFINEMENT = 1;
|
|
21
23
|
const PASS_CLEANUP = 2;
|
|
@@ -23,25 +25,33 @@ function throwForUnsupportedStyle(style) {
|
|
|
23
25
|
if ((style & STYLE_SELECTIVE_BYPASS) !== 0) throw new require_image_jpeg2000_errors.Jpeg2000UnsupportedError("the code-block style enables selective arithmetic coding bypass (lazy mode), which splits a code-block into raw and arithmetically coded segments this decoder does not read");
|
|
24
26
|
if ((style & STYLE_TERMINATE_ALL) !== 0) throw new require_image_jpeg2000_errors.Jpeg2000UnsupportedError("the code-block style terminates the arithmetic coder on every coding pass, which splits a code-block into one segment per pass this decoder does not read");
|
|
25
27
|
}
|
|
28
|
+
const ZC_CONTEXT_3 = 3;
|
|
29
|
+
const ZC_CONTEXT_4 = 4;
|
|
30
|
+
const ZC_CONTEXT_5 = 5;
|
|
31
|
+
const ZC_CONTEXT_6 = 6;
|
|
32
|
+
const ZC_CONTEXT_7 = 7;
|
|
33
|
+
const ZC_CONTEXT_8 = 8;
|
|
34
|
+
const HH_DIAGONAL_NEIGHBOURS_HIGH = 3;
|
|
26
35
|
function zeroCodingContext(subband, horizontal, vertical, diagonal) {
|
|
27
36
|
if (subband === "HH") {
|
|
28
37
|
const straight = horizontal + vertical;
|
|
29
|
-
if (diagonal >=
|
|
30
|
-
if (diagonal === 2) return straight >= 1 ?
|
|
31
|
-
if (diagonal === 1) return straight >= 2 ?
|
|
38
|
+
if (diagonal >= HH_DIAGONAL_NEIGHBOURS_HIGH) return ZC_CONTEXT_8;
|
|
39
|
+
if (diagonal === 2) return straight >= 1 ? ZC_CONTEXT_7 : ZC_CONTEXT_6;
|
|
40
|
+
if (diagonal === 1) return straight >= 2 ? ZC_CONTEXT_5 : straight === 1 ? ZC_CONTEXT_4 : ZC_CONTEXT_3;
|
|
32
41
|
return straight >= 2 ? 2 : straight === 1 ? 1 : 0;
|
|
33
42
|
}
|
|
34
43
|
const primary = subband === "HL" ? vertical : horizontal;
|
|
35
44
|
const secondary = subband === "HL" ? horizontal : vertical;
|
|
36
|
-
if (primary === 2) return
|
|
45
|
+
if (primary === 2) return ZC_CONTEXT_8;
|
|
37
46
|
if (primary === 1) {
|
|
38
|
-
if (secondary >= 1) return
|
|
39
|
-
return diagonal >= 1 ?
|
|
47
|
+
if (secondary >= 1) return ZC_CONTEXT_7;
|
|
48
|
+
return diagonal >= 1 ? ZC_CONTEXT_6 : ZC_CONTEXT_5;
|
|
40
49
|
}
|
|
41
|
-
if (secondary === 2) return
|
|
42
|
-
if (secondary === 1) return
|
|
50
|
+
if (secondary === 2) return ZC_CONTEXT_4;
|
|
51
|
+
if (secondary === 1) return ZC_CONTEXT_3;
|
|
43
52
|
return diagonal >= 2 ? 2 : diagonal === 1 ? 1 : 0;
|
|
44
53
|
}
|
|
54
|
+
const SIGN_CONTEXT_TABLE_ROW_STRIDE = 3;
|
|
45
55
|
const SIGN_XOR_FLAG = 8;
|
|
46
56
|
const SIGN_CONTEXT_TABLE = [
|
|
47
57
|
12,
|
|
@@ -102,7 +112,7 @@ function decodeJpeg2000CodeBlock(options) {
|
|
|
102
112
|
const below = belowVisible(y, stripeEnd);
|
|
103
113
|
const horizontal = clampToUnit(contribution(n - 1) + contribution(n + 1));
|
|
104
114
|
const vertical = clampToUnit(contribution(n - stride) + (below ? contribution(n + stride) : 0));
|
|
105
|
-
const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) *
|
|
115
|
+
const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * SIGN_CONTEXT_TABLE_ROW_STRIDE + (vertical + 1)] ?? 0;
|
|
106
116
|
const decision = mq.decode(contexts, SIGN_CONTEXT_BASE + (packed & -9));
|
|
107
117
|
negative[n] = decision ^ ((packed & SIGN_XOR_FLAG) !== 0 ? 1 : 0);
|
|
108
118
|
};
|
|
@@ -160,8 +170,8 @@ function decodeJpeg2000CodeBlock(options) {
|
|
|
160
170
|
}
|
|
161
171
|
}
|
|
162
172
|
if (segmentationSymbols) {
|
|
163
|
-
const symbol = mq.decode(contexts, UNIFORM_CONTEXT) <<
|
|
164
|
-
if (symbol !== SEGMENTATION_SYMBOL) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(
|
|
173
|
+
const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << SEGMENTATION_SYMBOL_MSB_SHIFT | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
|
|
174
|
+
if (symbol !== SEGMENTATION_SYMBOL) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(HEX_RADIX)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
|
|
165
175
|
}
|
|
166
176
|
codedThisPlane.fill(0);
|
|
167
177
|
};
|
|
@@ -14,7 +14,9 @@ const STYLE_TERMINATE_ALL = 4;
|
|
|
14
14
|
const STYLE_VERTICALLY_CAUSAL = 8;
|
|
15
15
|
const STYLE_SEGMENTATION_SYMBOLS = 32;
|
|
16
16
|
const SEGMENTATION_SYMBOL = 10;
|
|
17
|
+
const SEGMENTATION_SYMBOL_MSB_SHIFT = 3;
|
|
17
18
|
const STRIPE_HEIGHT = 4;
|
|
19
|
+
const HEX_RADIX = 16;
|
|
18
20
|
const PASS_SIGNIFICANCE = 0;
|
|
19
21
|
const PASS_REFINEMENT = 1;
|
|
20
22
|
const PASS_CLEANUP = 2;
|
|
@@ -22,25 +24,33 @@ function throwForUnsupportedStyle(style) {
|
|
|
22
24
|
if ((style & STYLE_SELECTIVE_BYPASS) !== 0) throw new Jpeg2000UnsupportedError("the code-block style enables selective arithmetic coding bypass (lazy mode), which splits a code-block into raw and arithmetically coded segments this decoder does not read");
|
|
23
25
|
if ((style & STYLE_TERMINATE_ALL) !== 0) throw new Jpeg2000UnsupportedError("the code-block style terminates the arithmetic coder on every coding pass, which splits a code-block into one segment per pass this decoder does not read");
|
|
24
26
|
}
|
|
27
|
+
const ZC_CONTEXT_3 = 3;
|
|
28
|
+
const ZC_CONTEXT_4 = 4;
|
|
29
|
+
const ZC_CONTEXT_5 = 5;
|
|
30
|
+
const ZC_CONTEXT_6 = 6;
|
|
31
|
+
const ZC_CONTEXT_7 = 7;
|
|
32
|
+
const ZC_CONTEXT_8 = 8;
|
|
33
|
+
const HH_DIAGONAL_NEIGHBOURS_HIGH = 3;
|
|
25
34
|
function zeroCodingContext(subband, horizontal, vertical, diagonal) {
|
|
26
35
|
if (subband === "HH") {
|
|
27
36
|
const straight = horizontal + vertical;
|
|
28
|
-
if (diagonal >=
|
|
29
|
-
if (diagonal === 2) return straight >= 1 ?
|
|
30
|
-
if (diagonal === 1) return straight >= 2 ?
|
|
37
|
+
if (diagonal >= HH_DIAGONAL_NEIGHBOURS_HIGH) return ZC_CONTEXT_8;
|
|
38
|
+
if (diagonal === 2) return straight >= 1 ? ZC_CONTEXT_7 : ZC_CONTEXT_6;
|
|
39
|
+
if (diagonal === 1) return straight >= 2 ? ZC_CONTEXT_5 : straight === 1 ? ZC_CONTEXT_4 : ZC_CONTEXT_3;
|
|
31
40
|
return straight >= 2 ? 2 : straight === 1 ? 1 : 0;
|
|
32
41
|
}
|
|
33
42
|
const primary = subband === "HL" ? vertical : horizontal;
|
|
34
43
|
const secondary = subband === "HL" ? horizontal : vertical;
|
|
35
|
-
if (primary === 2) return
|
|
44
|
+
if (primary === 2) return ZC_CONTEXT_8;
|
|
36
45
|
if (primary === 1) {
|
|
37
|
-
if (secondary >= 1) return
|
|
38
|
-
return diagonal >= 1 ?
|
|
46
|
+
if (secondary >= 1) return ZC_CONTEXT_7;
|
|
47
|
+
return diagonal >= 1 ? ZC_CONTEXT_6 : ZC_CONTEXT_5;
|
|
39
48
|
}
|
|
40
|
-
if (secondary === 2) return
|
|
41
|
-
if (secondary === 1) return
|
|
49
|
+
if (secondary === 2) return ZC_CONTEXT_4;
|
|
50
|
+
if (secondary === 1) return ZC_CONTEXT_3;
|
|
42
51
|
return diagonal >= 2 ? 2 : diagonal === 1 ? 1 : 0;
|
|
43
52
|
}
|
|
53
|
+
const SIGN_CONTEXT_TABLE_ROW_STRIDE = 3;
|
|
44
54
|
const SIGN_XOR_FLAG = 8;
|
|
45
55
|
const SIGN_CONTEXT_TABLE = [
|
|
46
56
|
12,
|
|
@@ -101,7 +111,7 @@ function decodeJpeg2000CodeBlock(options) {
|
|
|
101
111
|
const below = belowVisible(y, stripeEnd);
|
|
102
112
|
const horizontal = clampToUnit(contribution(n - 1) + contribution(n + 1));
|
|
103
113
|
const vertical = clampToUnit(contribution(n - stride) + (below ? contribution(n + stride) : 0));
|
|
104
|
-
const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) *
|
|
114
|
+
const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * SIGN_CONTEXT_TABLE_ROW_STRIDE + (vertical + 1)] ?? 0;
|
|
105
115
|
const decision = mq.decode(contexts, SIGN_CONTEXT_BASE + (packed & -9));
|
|
106
116
|
negative[n] = decision ^ ((packed & SIGN_XOR_FLAG) !== 0 ? 1 : 0);
|
|
107
117
|
};
|
|
@@ -159,8 +169,8 @@ function decodeJpeg2000CodeBlock(options) {
|
|
|
159
169
|
}
|
|
160
170
|
}
|
|
161
171
|
if (segmentationSymbols) {
|
|
162
|
-
const symbol = mq.decode(contexts, UNIFORM_CONTEXT) <<
|
|
163
|
-
if (symbol !== SEGMENTATION_SYMBOL) throw new Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(
|
|
172
|
+
const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << SEGMENTATION_SYMBOL_MSB_SHIFT | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
|
|
173
|
+
if (symbol !== SEGMENTATION_SYMBOL) throw new Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(HEX_RADIX)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
|
|
164
174
|
}
|
|
165
175
|
codedThisPlane.fill(0);
|
|
166
176
|
};
|
|
@@ -63,8 +63,9 @@ function bandCoordinate(componentCoordinate, levels, orientation) {
|
|
|
63
63
|
const half = 2 ** (levels - 1);
|
|
64
64
|
return Math.ceil((componentCoordinate - half * orientation) / (2 * half));
|
|
65
65
|
}
|
|
66
|
+
const SUBBANDS_PER_RESOLUTION_LEVEL = 3;
|
|
66
67
|
function quantizationIndex(resolution, bandIndex) {
|
|
67
|
-
return resolution === 0 ? 0 :
|
|
68
|
+
return resolution === 0 ? 0 : SUBBANDS_PER_RESOLUTION_LEVEL * (resolution - 1) + bandIndex + 1;
|
|
68
69
|
}
|
|
69
70
|
function stepSizeFor(quantization, resolution, bandIndex) {
|
|
70
71
|
if (quantization.style === "derived") {
|
|
@@ -203,14 +204,20 @@ function buildTileGeometry(siz, tileX, tileY, codingPerComponent, quantizationPe
|
|
|
203
204
|
function subbandGainLog2(type) {
|
|
204
205
|
return SUBBAND_GAIN_LOG2[type];
|
|
205
206
|
}
|
|
207
|
+
const CODING_PASSES_RANGE_3_5_BASE = 3;
|
|
208
|
+
const CODING_PASSES_5_BIT_FIELD_WIDTH = 5;
|
|
209
|
+
const CODING_PASSES_5_BIT_FIELD_ESCAPE = 31;
|
|
210
|
+
const CODING_PASSES_RANGE_6_36_BASE = 6;
|
|
211
|
+
const CODING_PASSES_RANGE_37_164_BASE = 37;
|
|
212
|
+
const CODING_PASSES_7_BIT_FIELD_WIDTH = 7;
|
|
206
213
|
function readCodingPasses(reader) {
|
|
207
214
|
if (reader.readBit() === 0) return 1;
|
|
208
215
|
if (reader.readBit() === 0) return 2;
|
|
209
216
|
const twoBit = reader.readBits(2);
|
|
210
|
-
if (twoBit <
|
|
211
|
-
const fiveBit = reader.readBits(
|
|
212
|
-
if (fiveBit <
|
|
213
|
-
return
|
|
217
|
+
if (twoBit < CODING_PASSES_RANGE_3_5_BASE) return CODING_PASSES_RANGE_3_5_BASE + twoBit;
|
|
218
|
+
const fiveBit = reader.readBits(CODING_PASSES_5_BIT_FIELD_WIDTH);
|
|
219
|
+
if (fiveBit < CODING_PASSES_5_BIT_FIELD_ESCAPE) return CODING_PASSES_RANGE_6_36_BASE + fiveBit;
|
|
220
|
+
return CODING_PASSES_RANGE_37_164_BASE + reader.readBits(CODING_PASSES_7_BIT_FIELD_WIDTH);
|
|
214
221
|
}
|
|
215
222
|
function buildPacketSequence(tile, order, layers) {
|
|
216
223
|
const maxResolutions = Math.max(...tile.components.map((component) => component.resolutions.length));
|
|
@@ -62,8 +62,9 @@ function bandCoordinate(componentCoordinate, levels, orientation) {
|
|
|
62
62
|
const half = 2 ** (levels - 1);
|
|
63
63
|
return Math.ceil((componentCoordinate - half * orientation) / (2 * half));
|
|
64
64
|
}
|
|
65
|
+
const SUBBANDS_PER_RESOLUTION_LEVEL = 3;
|
|
65
66
|
function quantizationIndex(resolution, bandIndex) {
|
|
66
|
-
return resolution === 0 ? 0 :
|
|
67
|
+
return resolution === 0 ? 0 : SUBBANDS_PER_RESOLUTION_LEVEL * (resolution - 1) + bandIndex + 1;
|
|
67
68
|
}
|
|
68
69
|
function stepSizeFor(quantization, resolution, bandIndex) {
|
|
69
70
|
if (quantization.style === "derived") {
|
|
@@ -202,14 +203,20 @@ function buildTileGeometry(siz, tileX, tileY, codingPerComponent, quantizationPe
|
|
|
202
203
|
function subbandGainLog2(type) {
|
|
203
204
|
return SUBBAND_GAIN_LOG2[type];
|
|
204
205
|
}
|
|
206
|
+
const CODING_PASSES_RANGE_3_5_BASE = 3;
|
|
207
|
+
const CODING_PASSES_5_BIT_FIELD_WIDTH = 5;
|
|
208
|
+
const CODING_PASSES_5_BIT_FIELD_ESCAPE = 31;
|
|
209
|
+
const CODING_PASSES_RANGE_6_36_BASE = 6;
|
|
210
|
+
const CODING_PASSES_RANGE_37_164_BASE = 37;
|
|
211
|
+
const CODING_PASSES_7_BIT_FIELD_WIDTH = 7;
|
|
205
212
|
function readCodingPasses(reader) {
|
|
206
213
|
if (reader.readBit() === 0) return 1;
|
|
207
214
|
if (reader.readBit() === 0) return 2;
|
|
208
215
|
const twoBit = reader.readBits(2);
|
|
209
|
-
if (twoBit <
|
|
210
|
-
const fiveBit = reader.readBits(
|
|
211
|
-
if (fiveBit <
|
|
212
|
-
return
|
|
216
|
+
if (twoBit < CODING_PASSES_RANGE_3_5_BASE) return CODING_PASSES_RANGE_3_5_BASE + twoBit;
|
|
217
|
+
const fiveBit = reader.readBits(CODING_PASSES_5_BIT_FIELD_WIDTH);
|
|
218
|
+
if (fiveBit < CODING_PASSES_5_BIT_FIELD_ESCAPE) return CODING_PASSES_RANGE_6_36_BASE + fiveBit;
|
|
219
|
+
return CODING_PASSES_RANGE_37_164_BASE + reader.readBits(CODING_PASSES_7_BIT_FIELD_WIDTH);
|
|
213
220
|
}
|
|
214
221
|
function buildPacketSequence(tile, order, layers) {
|
|
215
222
|
const maxResolutions = Math.max(...tile.components.map((component) => component.resolutions.length));
|