pdf-parser.js 5.2.26 → 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.d.cts +2 -2
- package/dist/annotations.d.ts +2 -2
- package/dist/annotations.js +5 -3
- package/dist/attachments.d.cts +2 -2
- package/dist/attachments.d.ts +2 -2
- 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 +73 -45
- package/dist/cff-bounds.js +73 -45
- 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-read.d.cts +1 -1
- package/dist/content-read.d.ts +1 -1
- package/dist/content-write.cjs +21 -14
- package/dist/content-write.d.cts +2 -2
- package/dist/content-write.d.ts +2 -2
- package/dist/content-write.js +21 -14
- 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/document.cjs +17 -11
- package/dist/document.d.cts +1 -1
- package/dist/document.d.ts +1 -1
- package/dist/document.js +17 -11
- package/dist/{embedded-font-Bnhh4juV.d.ts → embedded-font-ByD7ZiQS.d.ts} +1 -1
- package/dist/{embedded-font-CEf-zBCA.d.cts → embedded-font-DgVBedw6.d.cts} +1 -1
- package/dist/embedded-font-write.d.cts +2 -2
- package/dist/embedded-font-write.d.ts +2 -2
- package/dist/embedded-font.cjs +4 -2
- package/dist/embedded-font.d.cts +1 -1
- package/dist/embedded-font.d.ts +1 -1
- 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.d.cts +1 -1
- package/dist/encrypt-write.d.ts +1 -1
- package/dist/encrypt-write.js +25 -21
- package/dist/encrypt.cjs +43 -64
- package/dist/encrypt.d.cts +1 -1
- package/dist/encrypt.d.ts +1 -1
- package/dist/encrypt.js +43 -64
- package/dist/filters.cjs +46 -26
- package/dist/filters.d.cts +1 -1
- package/dist/filters.d.ts +1 -1
- package/dist/filters.js +46 -26
- 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.d.cts +1 -1
- package/dist/font-read.d.ts +1 -1
- package/dist/font-read.js +12 -6
- package/dist/font-registry.d.cts +3 -3
- package/dist/font-registry.d.ts +3 -3
- package/dist/font-tables.cjs +55 -28
- package/dist/font-tables.js +55 -28
- package/dist/form.cjs +13 -8
- package/dist/form.d.cts +2 -2
- package/dist/form.d.ts +2 -2
- package/dist/form.js +13 -8
- package/dist/gdef-table.cjs +6 -3
- package/dist/gdef-table.js +6 -3
- package/dist/{glyf-contours-C0epBNqP.d.ts → glyf-contours-B1PsI9oA.d.ts} +1 -1
- package/dist/{glyf-contours-BRpvd0rt.d.cts → glyf-contours-NHBpgks-.d.cts} +1 -1
- package/dist/glyf-contours.cjs +3 -1
- package/dist/glyf-contours.d.cts +1 -1
- package/dist/glyf-contours.d.ts +1 -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 +40 -25
- package/dist/gsub-table.js +40 -25
- 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 +61 -32
- package/dist/image/jpeg2000-codestream.js +61 -32
- 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.d.cts +2 -2
- package/dist/images-read.d.ts +2 -2
- package/dist/images-read.js +41 -36
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/interpret.cjs +68 -40
- package/dist/interpret.d.cts +1 -1
- package/dist/interpret.d.ts +1 -1
- package/dist/interpret.js +68 -40
- 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.d.cts +1 -1
- package/dist/math-font-write.d.ts +1 -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/names.cjs +7 -7
- package/dist/names.d.cts +2 -2
- package/dist/names.d.ts +2 -2
- package/dist/names.js +7 -7
- package/dist/navigation.cjs +16 -12
- package/dist/navigation.d.cts +4 -4
- package/dist/navigation.d.ts +4 -4
- package/dist/navigation.js +16 -12
- package/dist/{objects-B7HdMeWS.d.cts → objects-e2RS3-yT.d.cts} +3 -3
- package/dist/{objects-B7HdMeWS.d.ts → objects-e2RS3-yT.d.ts} +3 -3
- package/dist/objects.d.cts +1 -1
- package/dist/objects.d.ts +1 -1
- package/dist/optional-content.d.cts +2 -2
- package/dist/optional-content.d.ts +2 -2
- package/dist/ot-layout-common.cjs +22 -15
- package/dist/ot-layout-common.js +22 -15
- package/dist/parse.cjs +7 -5
- package/dist/parse.d.cts +1 -1
- package/dist/parse.d.ts +1 -1
- 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.d.cts +1 -1
- package/dist/predictors.d.ts +1 -1
- package/dist/predictors.js +14 -9
- package/dist/raster.cjs +30 -19
- package/dist/raster.d.cts +8 -8
- package/dist/raster.d.ts +8 -8
- package/dist/raster.js +30 -19
- package/dist/read.cjs +29 -16
- package/dist/read.js +29 -16
- package/dist/serialize.cjs +6 -2
- package/dist/serialize.d.cts +1 -1
- package/dist/serialize.d.ts +1 -1
- package/dist/serialize.js +6 -2
- package/dist/sfnt-subset.cjs +25 -13
- package/dist/sfnt-subset.d.cts +1 -1
- package/dist/sfnt-subset.d.ts +1 -1
- package/dist/sfnt-subset.js +25 -13
- package/dist/sfnt.cjs +20 -10
- package/dist/sfnt.js +20 -10
- package/dist/structure.d.cts +2 -2
- package/dist/structure.d.ts +2 -2
- package/dist/text-group.cjs +0 -1
- package/dist/text-group.js +0 -1
- package/dist/text-layout.d.cts +1 -1
- package/dist/text-layout.d.ts +1 -1
- package/dist/tounicode.cjs +4 -2
- package/dist/tounicode.d.cts +1 -1
- package/dist/tounicode.d.ts +1 -1
- 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.d.cts +1 -1
- package/dist/write.d.ts +1 -1
- package/dist/write.js +20 -12
- package/dist/xref.cjs +5 -2
- package/dist/xref.d.cts +1 -1
- package/dist/xref.d.ts +1 -1
- 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 {
|
|
@@ -201,11 +217,20 @@ function freezeHeader(header) {
|
|
|
201
217
|
};
|
|
202
218
|
return base;
|
|
203
219
|
}
|
|
220
|
+
var CodestreamComments = class {
|
|
221
|
+
#texts = [];
|
|
222
|
+
add(text) {
|
|
223
|
+
this.#texts.push(text);
|
|
224
|
+
}
|
|
225
|
+
texts() {
|
|
226
|
+
return this.#texts;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
204
229
|
function readHeaderSegment(marker, cursor, header, componentCount, comments) {
|
|
205
230
|
const length = cursor.uint16();
|
|
206
|
-
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`);
|
|
207
232
|
const segmentEnd = cursor.position + length - 2;
|
|
208
|
-
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`);
|
|
209
234
|
if (marker === MARKER_COD) header.cod = readCodingDefaults(cursor);
|
|
210
235
|
else if (marker === MARKER_COC) {
|
|
211
236
|
const component = readComponentIndex(cursor, componentCount);
|
|
@@ -220,7 +245,7 @@ function readHeaderSegment(marker, cursor, header, componentCount, comments) {
|
|
|
220
245
|
else if (marker === MARKER_COM) {
|
|
221
246
|
const registration = cursor.uint16();
|
|
222
247
|
const body = cursor.bytes(segmentEnd - cursor.position);
|
|
223
|
-
if (registration === 1) comments.
|
|
248
|
+
if (registration === 1) comments.add(Array.from(body, (byte) => String.fromCharCode(byte)).join(""));
|
|
224
249
|
}
|
|
225
250
|
cursor.position = segmentEnd;
|
|
226
251
|
}
|
|
@@ -228,15 +253,16 @@ function validateMainHeader(header) {
|
|
|
228
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");
|
|
229
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");
|
|
230
255
|
}
|
|
256
|
+
const MIN_HEADER_BYTES = 4;
|
|
231
257
|
function parseJpeg2000Codestream(data) {
|
|
232
258
|
const cursor = new MarkerCursor(data);
|
|
233
|
-
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");
|
|
234
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");
|
|
235
261
|
const sizLength = cursor.uint16();
|
|
236
262
|
const sizEnd = cursor.position + sizLength - 2;
|
|
237
263
|
const siz = readImageSize(cursor, sizEnd);
|
|
238
264
|
cursor.position = sizEnd;
|
|
239
|
-
const comments =
|
|
265
|
+
const comments = new CodestreamComments();
|
|
240
266
|
const main = emptyHeader();
|
|
241
267
|
const tileParts = [];
|
|
242
268
|
let sawEoc = false;
|
|
@@ -250,10 +276,10 @@ function parseJpeg2000Codestream(data) {
|
|
|
250
276
|
if (marker === MARKER_PPM) throw new require_image_jpeg2000_errors.Jpeg2000UnsupportedError("the codestream carries a PPM marker (packed packet headers in the main header), an organisation this decoder does not reassemble");
|
|
251
277
|
if (marker === MARKER_SOT) {
|
|
252
278
|
cursor.position -= 2;
|
|
253
|
-
readTilePart(cursor, siz.components.length,
|
|
279
|
+
tileParts.push(readTilePart(cursor, siz.components.length, comments));
|
|
254
280
|
continue;
|
|
255
281
|
}
|
|
256
|
-
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`);
|
|
257
283
|
readHeaderSegment(marker, cursor, main, siz.components.length, comments);
|
|
258
284
|
}
|
|
259
285
|
validateMainHeader(main);
|
|
@@ -264,17 +290,18 @@ function parseJpeg2000Codestream(data) {
|
|
|
264
290
|
siz,
|
|
265
291
|
main: freezeHeader(main),
|
|
266
292
|
tileParts,
|
|
267
|
-
comments,
|
|
293
|
+
comments: comments.texts(),
|
|
268
294
|
numTilesWide,
|
|
269
295
|
numTilesHigh,
|
|
270
296
|
truncated: !sawEoc
|
|
271
297
|
};
|
|
272
298
|
}
|
|
273
|
-
|
|
299
|
+
const SOT_SEGMENT_LENGTH = 10;
|
|
300
|
+
function readTilePart(cursor, componentCount, comments) {
|
|
274
301
|
const sotStart = cursor.position;
|
|
275
302
|
cursor.uint16();
|
|
276
303
|
const lsot = cursor.uint16();
|
|
277
|
-
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`);
|
|
278
305
|
const tileIndex = cursor.uint16();
|
|
279
306
|
const psot = cursor.uint32();
|
|
280
307
|
const partIndex = cursor.uint8();
|
|
@@ -284,7 +311,7 @@ function readTilePart(cursor, componentCount, tileParts, comments) {
|
|
|
284
311
|
if (cursor.remaining < 2) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a tile-part header ended without an SOD marker");
|
|
285
312
|
const marker = cursor.uint16();
|
|
286
313
|
if (marker === MARKER_SOD) break;
|
|
287
|
-
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`);
|
|
288
315
|
readHeaderSegment(marker, cursor, header, componentCount, comments);
|
|
289
316
|
}
|
|
290
317
|
const dataStart = cursor.position;
|
|
@@ -292,17 +319,19 @@ function readTilePart(cursor, componentCount, tileParts, comments) {
|
|
|
292
319
|
const dataEnd = Math.min(declaredEnd, cursor.data.length);
|
|
293
320
|
if (dataEnd < dataStart) throw new require_image_jpeg2000_errors.Jpeg2000ParseError("a tile-part declares a Psot shorter than its own header");
|
|
294
321
|
const trimmedEnd = trimTrailingEoc(cursor.data, dataEnd);
|
|
295
|
-
|
|
322
|
+
cursor.position = dataEnd;
|
|
323
|
+
return {
|
|
296
324
|
tileIndex,
|
|
297
325
|
partIndex,
|
|
298
326
|
header: freezeHeader(header),
|
|
299
327
|
dataStart,
|
|
300
328
|
dataEnd: trimmedEnd
|
|
301
|
-
}
|
|
302
|
-
cursor.position = dataEnd;
|
|
329
|
+
};
|
|
303
330
|
}
|
|
331
|
+
const MARKER_EOC_HIGH_BYTE = 255;
|
|
332
|
+
const MARKER_EOC_LOW_BYTE = 217;
|
|
304
333
|
function trimTrailingEoc(data, end) {
|
|
305
|
-
if (data[end - 2] ===
|
|
334
|
+
if (data[end - 2] === MARKER_EOC_HIGH_BYTE && data[end - 1] === MARKER_EOC_LOW_BYTE) return end - 2;
|
|
306
335
|
return end;
|
|
307
336
|
}
|
|
308
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 {
|
|
@@ -200,11 +216,20 @@ function freezeHeader(header) {
|
|
|
200
216
|
};
|
|
201
217
|
return base;
|
|
202
218
|
}
|
|
219
|
+
var CodestreamComments = class {
|
|
220
|
+
#texts = [];
|
|
221
|
+
add(text) {
|
|
222
|
+
this.#texts.push(text);
|
|
223
|
+
}
|
|
224
|
+
texts() {
|
|
225
|
+
return this.#texts;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
203
228
|
function readHeaderSegment(marker, cursor, header, componentCount, comments) {
|
|
204
229
|
const length = cursor.uint16();
|
|
205
|
-
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`);
|
|
206
231
|
const segmentEnd = cursor.position + length - 2;
|
|
207
|
-
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`);
|
|
208
233
|
if (marker === MARKER_COD) header.cod = readCodingDefaults(cursor);
|
|
209
234
|
else if (marker === MARKER_COC) {
|
|
210
235
|
const component = readComponentIndex(cursor, componentCount);
|
|
@@ -219,7 +244,7 @@ function readHeaderSegment(marker, cursor, header, componentCount, comments) {
|
|
|
219
244
|
else if (marker === MARKER_COM) {
|
|
220
245
|
const registration = cursor.uint16();
|
|
221
246
|
const body = cursor.bytes(segmentEnd - cursor.position);
|
|
222
|
-
if (registration === 1) comments.
|
|
247
|
+
if (registration === 1) comments.add(Array.from(body, (byte) => String.fromCharCode(byte)).join(""));
|
|
223
248
|
}
|
|
224
249
|
cursor.position = segmentEnd;
|
|
225
250
|
}
|
|
@@ -227,15 +252,16 @@ function validateMainHeader(header) {
|
|
|
227
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");
|
|
228
253
|
if (header.qcd === void 0) throw new Jpeg2000ParseError("the main header carries no QCD marker, so no quantization is defined for any tile");
|
|
229
254
|
}
|
|
255
|
+
const MIN_HEADER_BYTES = 4;
|
|
230
256
|
function parseJpeg2000Codestream(data) {
|
|
231
257
|
const cursor = new MarkerCursor(data);
|
|
232
|
-
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");
|
|
233
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");
|
|
234
260
|
const sizLength = cursor.uint16();
|
|
235
261
|
const sizEnd = cursor.position + sizLength - 2;
|
|
236
262
|
const siz = readImageSize(cursor, sizEnd);
|
|
237
263
|
cursor.position = sizEnd;
|
|
238
|
-
const comments =
|
|
264
|
+
const comments = new CodestreamComments();
|
|
239
265
|
const main = emptyHeader();
|
|
240
266
|
const tileParts = [];
|
|
241
267
|
let sawEoc = false;
|
|
@@ -249,10 +275,10 @@ function parseJpeg2000Codestream(data) {
|
|
|
249
275
|
if (marker === MARKER_PPM) throw new Jpeg2000UnsupportedError("the codestream carries a PPM marker (packed packet headers in the main header), an organisation this decoder does not reassemble");
|
|
250
276
|
if (marker === MARKER_SOT) {
|
|
251
277
|
cursor.position -= 2;
|
|
252
|
-
readTilePart(cursor, siz.components.length,
|
|
278
|
+
tileParts.push(readTilePart(cursor, siz.components.length, comments));
|
|
253
279
|
continue;
|
|
254
280
|
}
|
|
255
|
-
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`);
|
|
256
282
|
readHeaderSegment(marker, cursor, main, siz.components.length, comments);
|
|
257
283
|
}
|
|
258
284
|
validateMainHeader(main);
|
|
@@ -263,17 +289,18 @@ function parseJpeg2000Codestream(data) {
|
|
|
263
289
|
siz,
|
|
264
290
|
main: freezeHeader(main),
|
|
265
291
|
tileParts,
|
|
266
|
-
comments,
|
|
292
|
+
comments: comments.texts(),
|
|
267
293
|
numTilesWide,
|
|
268
294
|
numTilesHigh,
|
|
269
295
|
truncated: !sawEoc
|
|
270
296
|
};
|
|
271
297
|
}
|
|
272
|
-
|
|
298
|
+
const SOT_SEGMENT_LENGTH = 10;
|
|
299
|
+
function readTilePart(cursor, componentCount, comments) {
|
|
273
300
|
const sotStart = cursor.position;
|
|
274
301
|
cursor.uint16();
|
|
275
302
|
const lsot = cursor.uint16();
|
|
276
|
-
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`);
|
|
277
304
|
const tileIndex = cursor.uint16();
|
|
278
305
|
const psot = cursor.uint32();
|
|
279
306
|
const partIndex = cursor.uint8();
|
|
@@ -283,7 +310,7 @@ function readTilePart(cursor, componentCount, tileParts, comments) {
|
|
|
283
310
|
if (cursor.remaining < 2) throw new Jpeg2000ParseError("a tile-part header ended without an SOD marker");
|
|
284
311
|
const marker = cursor.uint16();
|
|
285
312
|
if (marker === MARKER_SOD) break;
|
|
286
|
-
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`);
|
|
287
314
|
readHeaderSegment(marker, cursor, header, componentCount, comments);
|
|
288
315
|
}
|
|
289
316
|
const dataStart = cursor.position;
|
|
@@ -291,17 +318,19 @@ function readTilePart(cursor, componentCount, tileParts, comments) {
|
|
|
291
318
|
const dataEnd = Math.min(declaredEnd, cursor.data.length);
|
|
292
319
|
if (dataEnd < dataStart) throw new Jpeg2000ParseError("a tile-part declares a Psot shorter than its own header");
|
|
293
320
|
const trimmedEnd = trimTrailingEoc(cursor.data, dataEnd);
|
|
294
|
-
|
|
321
|
+
cursor.position = dataEnd;
|
|
322
|
+
return {
|
|
295
323
|
tileIndex,
|
|
296
324
|
partIndex,
|
|
297
325
|
header: freezeHeader(header),
|
|
298
326
|
dataStart,
|
|
299
327
|
dataEnd: trimmedEnd
|
|
300
|
-
}
|
|
301
|
-
cursor.position = dataEnd;
|
|
328
|
+
};
|
|
302
329
|
}
|
|
330
|
+
const MARKER_EOC_HIGH_BYTE = 255;
|
|
331
|
+
const MARKER_EOC_LOW_BYTE = 217;
|
|
303
332
|
function trimTrailingEoc(data, end) {
|
|
304
|
-
if (data[end - 2] ===
|
|
333
|
+
if (data[end - 2] === MARKER_EOC_HIGH_BYTE && data[end - 1] === MARKER_EOC_LOW_BYTE) return end - 2;
|
|
305
334
|
return end;
|
|
306
335
|
}
|
|
307
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
|
};
|