pdf-codec 1.6.0 → 1.7.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.
Files changed (112) hide show
  1. package/README.md +67 -9
  2. package/dist/cff-bounds.cjs +432 -0
  3. package/dist/cff-bounds.d.cts +9 -0
  4. package/dist/cff-bounds.d.ts +9 -0
  5. package/dist/cff-bounds.js +431 -0
  6. package/dist/cff-probe.cjs +8 -106
  7. package/dist/cff-probe.js +9 -107
  8. package/dist/cff.cjs +158 -0
  9. package/dist/cff.d.cts +17 -0
  10. package/dist/cff.d.ts +17 -0
  11. package/dist/cff.js +150 -0
  12. package/dist/filters.cjs +45 -2
  13. package/dist/filters.d.cts +4 -3
  14. package/dist/filters.d.ts +4 -3
  15. package/dist/filters.js +45 -2
  16. package/dist/formula.d.cts +1 -1
  17. package/dist/formula.d.ts +1 -1
  18. package/dist/glyf.cjs +62 -6
  19. package/dist/glyf.d.cts +2 -0
  20. package/dist/glyf.d.ts +2 -0
  21. package/dist/glyf.js +62 -6
  22. package/dist/glyph-bounds-BV_Z40KS.d.cts +10 -0
  23. package/dist/glyph-bounds-BV_Z40KS.d.ts +10 -0
  24. package/dist/glyph-bounds.cjs +12 -0
  25. package/dist/glyph-bounds.d.cts +2 -0
  26. package/dist/glyph-bounds.d.ts +2 -0
  27. package/dist/glyph-bounds.js +11 -0
  28. package/dist/image/jbig2-arith.cjs +432 -0
  29. package/dist/image/jbig2-arith.d.cts +23 -0
  30. package/dist/image/jbig2-arith.d.ts +23 -0
  31. package/dist/image/jbig2-arith.js +426 -0
  32. package/dist/image/jbig2-bitmap.cjs +80 -0
  33. package/dist/image/jbig2-bitmap.d.cts +20 -0
  34. package/dist/image/jbig2-bitmap.d.ts +20 -0
  35. package/dist/image/jbig2-bitmap.js +72 -0
  36. package/dist/image/jbig2-errors.cjs +17 -0
  37. package/dist/image/jbig2-errors.d.cts +2 -0
  38. package/dist/image/jbig2-errors.d.ts +2 -0
  39. package/dist/image/jbig2-errors.js +15 -0
  40. package/dist/image/jbig2-generic.cjs +242 -0
  41. package/dist/image/jbig2-generic.d.cts +27 -0
  42. package/dist/image/jbig2-generic.d.ts +27 -0
  43. package/dist/image/jbig2-generic.js +237 -0
  44. package/dist/image/jbig2-text.cjs +175 -0
  45. package/dist/image/jbig2-text.d.cts +58 -0
  46. package/dist/image/jbig2-text.d.ts +58 -0
  47. package/dist/image/jbig2-text.js +170 -0
  48. package/dist/image/jbig2.cjs +333 -0
  49. package/dist/image/jbig2.d.cts +15 -0
  50. package/dist/image/jbig2.d.ts +15 -0
  51. package/dist/image/jbig2.js +332 -0
  52. package/dist/image/jp2-boxes.cjs +148 -0
  53. package/dist/image/jp2-boxes.d.cts +26 -0
  54. package/dist/image/jp2-boxes.d.ts +26 -0
  55. package/dist/image/jp2-boxes.js +146 -0
  56. package/dist/image/jpeg2000-codestream.cjs +309 -0
  57. package/dist/image/jpeg2000-codestream.d.cts +78 -0
  58. package/dist/image/jpeg2000-codestream.d.ts +78 -0
  59. package/dist/image/jpeg2000-codestream.js +308 -0
  60. package/dist/image/jpeg2000-dwt.cjs +148 -0
  61. package/dist/image/jpeg2000-dwt.d.cts +34 -0
  62. package/dist/image/jpeg2000-dwt.d.ts +34 -0
  63. package/dist/image/jpeg2000-dwt.js +145 -0
  64. package/dist/image/jpeg2000-errors.cjs +17 -0
  65. package/dist/image/jpeg2000-errors.d.cts +9 -0
  66. package/dist/image/jpeg2000-errors.d.ts +9 -0
  67. package/dist/image/jpeg2000-errors.js +15 -0
  68. package/dist/image/jpeg2000-t1.cjs +254 -0
  69. package/dist/image/jpeg2000-t1.d.cts +18 -0
  70. package/dist/image/jpeg2000-t1.d.ts +18 -0
  71. package/dist/image/jpeg2000-t1.js +253 -0
  72. package/dist/image/jpeg2000-t2.cjs +316 -0
  73. package/dist/image/jpeg2000-t2.d.cts +79 -0
  74. package/dist/image/jpeg2000-t2.d.ts +79 -0
  75. package/dist/image/jpeg2000-t2.js +311 -0
  76. package/dist/image/jpeg2000-tagtree.cjs +105 -0
  77. package/dist/image/jpeg2000-tagtree.d.cts +29 -0
  78. package/dist/image/jpeg2000-tagtree.d.ts +29 -0
  79. package/dist/image/jpeg2000-tagtree.js +103 -0
  80. package/dist/image/jpeg2000.cjs +322 -0
  81. package/dist/image/jpeg2000.d.cts +54 -0
  82. package/dist/image/jpeg2000.d.ts +54 -0
  83. package/dist/image/jpeg2000.js +320 -0
  84. package/dist/images-read.cjs +78 -1
  85. package/dist/images-read.js +78 -1
  86. package/dist/index.cjs +17 -0
  87. package/dist/index.d.cts +11 -2
  88. package/dist/index.d.ts +11 -2
  89. package/dist/index.js +7 -1
  90. package/dist/jbig2-errors-Bj6MPxrx.d.cts +9 -0
  91. package/dist/jbig2-errors-Bj6MPxrx.d.ts +9 -0
  92. package/dist/math-font.cjs +43 -18
  93. package/dist/math-font.d.cts +8 -1
  94. package/dist/math-font.d.ts +8 -1
  95. package/dist/math-font.js +43 -18
  96. package/dist/math-stretch-Bwk_bxh1.d.ts +24 -0
  97. package/dist/math-stretch-DXWjs8gL.d.cts +24 -0
  98. package/dist/math-stretch.cjs +96 -0
  99. package/dist/math-stretch.d.cts +2 -0
  100. package/dist/math-stretch.d.ts +2 -0
  101. package/dist/math-stretch.js +94 -0
  102. package/dist/math-table-DhPrNoPa.d.ts +70 -0
  103. package/dist/math-table-gFNB8DmQ.d.cts +70 -0
  104. package/dist/math-table.cjs +69 -1
  105. package/dist/math-table.d.cts +2 -45
  106. package/dist/math-table.d.ts +2 -45
  107. package/dist/math-table.js +69 -1
  108. package/dist/{math-types-Ba8qAf1p.d.cts → math-types-YSQUTviw.d.cts} +2 -0
  109. package/dist/{math-types-Ba8qAf1p.d.ts → math-types-YSQUTviw.d.ts} +2 -0
  110. package/dist/math-types.d.cts +1 -1
  111. package/dist/math-types.d.ts +1 -1
  112. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ //#region src/image/jpeg2000-errors.d.ts
2
+ declare class Jpeg2000ParseError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ declare class Jpeg2000UnsupportedError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ //#endregion
9
+ export { Jpeg2000ParseError, Jpeg2000UnsupportedError };
@@ -0,0 +1,9 @@
1
+ //#region src/image/jpeg2000-errors.d.ts
2
+ declare class Jpeg2000ParseError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ declare class Jpeg2000UnsupportedError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ //#endregion
9
+ export { Jpeg2000ParseError, Jpeg2000UnsupportedError };
@@ -0,0 +1,15 @@
1
+ //#region src/image/jpeg2000-errors.ts
2
+ var Jpeg2000ParseError = class extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = "Jpeg2000ParseError";
6
+ }
7
+ };
8
+ var Jpeg2000UnsupportedError = class extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.name = "Jpeg2000UnsupportedError";
12
+ }
13
+ };
14
+ //#endregion
15
+ export { Jpeg2000ParseError, Jpeg2000UnsupportedError };
@@ -0,0 +1,254 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_image_jbig2_arith = require("./jbig2-arith.cjs");
3
+ const require_image_jpeg2000_errors = require("./jpeg2000-errors.cjs");
4
+ //#region src/image/jpeg2000-t1.ts
5
+ const SIGN_CONTEXT_BASE = 9;
6
+ const MAGNITUDE_REFINEMENT_NO_NEIGHBOURS = 14;
7
+ const MAGNITUDE_REFINEMENT_WITH_NEIGHBOURS = 15;
8
+ const MAGNITUDE_REFINEMENT_SUBSEQUENT = 16;
9
+ const RUN_LENGTH_CONTEXT = 17;
10
+ const UNIFORM_CONTEXT = 18;
11
+ const CONTEXT_COUNT_BITS = 5;
12
+ const STYLE_SELECTIVE_BYPASS = 1;
13
+ const STYLE_RESET_CONTEXTS = 2;
14
+ const STYLE_TERMINATE_ALL = 4;
15
+ const STYLE_VERTICALLY_CAUSAL = 8;
16
+ const STYLE_SEGMENTATION_SYMBOLS = 32;
17
+ const SEGMENTATION_SYMBOL = 10;
18
+ const STRIPE_HEIGHT = 4;
19
+ const PASS_SIGNIFICANCE = 0;
20
+ const PASS_REFINEMENT = 1;
21
+ const PASS_CLEANUP = 2;
22
+ function throwForUnsupportedStyle(style) {
23
+ 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
+ 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
+ }
26
+ function zeroCodingContext(subband, horizontal, vertical, diagonal) {
27
+ if (subband === "HH") {
28
+ const straight = horizontal + vertical;
29
+ if (diagonal >= 3) return 8;
30
+ if (diagonal === 2) return straight >= 1 ? 7 : 6;
31
+ if (diagonal === 1) return straight >= 2 ? 5 : straight === 1 ? 4 : 3;
32
+ return straight >= 2 ? 2 : straight === 1 ? 1 : 0;
33
+ }
34
+ const primary = subband === "HL" ? vertical : horizontal;
35
+ const secondary = subband === "HL" ? horizontal : vertical;
36
+ if (primary === 2) return 8;
37
+ if (primary === 1) {
38
+ if (secondary >= 1) return 7;
39
+ return diagonal >= 1 ? 6 : 5;
40
+ }
41
+ if (secondary === 2) return 4;
42
+ if (secondary === 1) return 3;
43
+ return diagonal >= 2 ? 2 : diagonal === 1 ? 1 : 0;
44
+ }
45
+ const SIGN_CONTEXT_TABLE = (() => {
46
+ const rows = [
47
+ [
48
+ 1,
49
+ 1,
50
+ 4,
51
+ 0
52
+ ],
53
+ [
54
+ 1,
55
+ 0,
56
+ 3,
57
+ 0
58
+ ],
59
+ [
60
+ 1,
61
+ -1,
62
+ 2,
63
+ 0
64
+ ],
65
+ [
66
+ 0,
67
+ 1,
68
+ 1,
69
+ 0
70
+ ],
71
+ [
72
+ 0,
73
+ 0,
74
+ 0,
75
+ 0
76
+ ],
77
+ [
78
+ 0,
79
+ -1,
80
+ 1,
81
+ 1
82
+ ],
83
+ [
84
+ -1,
85
+ 1,
86
+ 2,
87
+ 1
88
+ ],
89
+ [
90
+ -1,
91
+ 0,
92
+ 3,
93
+ 1
94
+ ],
95
+ [
96
+ -1,
97
+ -1,
98
+ 4,
99
+ 1
100
+ ]
101
+ ];
102
+ const table = new Array(9).fill(0);
103
+ for (const [horizontal, vertical, offset, xorBit] of rows) table[(horizontal + 1) * 3 + (vertical + 1)] = offset | xorBit << 3;
104
+ return table;
105
+ })();
106
+ const SIGN_XOR_FLAG = 8;
107
+ function decodeJpeg2000CodeBlock(options) {
108
+ const { width, height, subband, zeroBitPlanes, maxBitPlanes, totalPasses, codeBlockStyle, data } = options;
109
+ throwForUnsupportedStyle(codeBlockStyle);
110
+ const values = new Int32Array(Math.max(width * height, 0));
111
+ const codedBitPlanes = maxBitPlanes - zeroBitPlanes;
112
+ if (width <= 0 || height <= 0 || codedBitPlanes <= 0 || totalPasses <= 0 || data.length === 0) return { values };
113
+ const stride = width + 2;
114
+ const cellCount = stride * (height + 2);
115
+ const significant = new Uint8Array(cellCount);
116
+ const negative = new Uint8Array(cellCount);
117
+ const codedThisPlane = new Uint8Array(cellCount);
118
+ const everRefined = new Uint8Array(cellCount);
119
+ const magnitude = new Int32Array(cellCount);
120
+ const lastCodedPlane = new Int32Array(cellCount);
121
+ const contexts = require_image_jbig2_arith.createArithContexts(CONTEXT_COUNT_BITS);
122
+ const resetContexts = () => {
123
+ contexts.fill(0);
124
+ contexts[0] = 8;
125
+ contexts[RUN_LENGTH_CONTEXT] = 6;
126
+ contexts[UNIFORM_CONTEXT] = 92;
127
+ };
128
+ resetContexts();
129
+ const mq = new require_image_jbig2_arith.MqDecoder(data, 0, data.length);
130
+ const verticallyCausal = (codeBlockStyle & STYLE_VERTICALLY_CAUSAL) !== 0;
131
+ const segmentationSymbols = (codeBlockStyle & STYLE_SEGMENTATION_SYMBOLS) !== 0;
132
+ const resetEachPass = (codeBlockStyle & STYLE_RESET_CONTEXTS) !== 0;
133
+ const at = (x, y) => (y + 1) * stride + (x + 1);
134
+ const belowVisible = (y, stripeEnd) => !verticallyCausal || y + 1 < stripeEnd;
135
+ const significanceContext = (x, y, stripeEnd) => {
136
+ const n = at(x, y);
137
+ const below = belowVisible(y, stripeEnd);
138
+ const horizontal = (significant[n - 1] ?? 0) + (significant[n + 1] ?? 0);
139
+ const vertical = (significant[n - stride] ?? 0) + (below ? significant[n + stride] ?? 0 : 0);
140
+ const diagonal = (significant[n - stride - 1] ?? 0) + (significant[n - stride + 1] ?? 0) + (below ? (significant[n + stride - 1] ?? 0) + (significant[n + stride + 1] ?? 0) : 0);
141
+ return zeroCodingContext(subband, horizontal, vertical, diagonal);
142
+ };
143
+ const neighbourhoodIsSignificant = (x, y, stripeEnd) => {
144
+ const n = at(x, y);
145
+ const below = belowVisible(y, stripeEnd);
146
+ return (significant[n - 1] ?? 0) + (significant[n + 1] ?? 0) + (significant[n - stride] ?? 0) + (below ? significant[n + stride] ?? 0 : 0) + ((significant[n - stride - 1] ?? 0) + (significant[n - stride + 1] ?? 0) + (below ? (significant[n + stride - 1] ?? 0) + (significant[n + stride + 1] ?? 0) : 0)) > 0;
147
+ };
148
+ const contribution = (cell) => (significant[cell] ?? 0) === 0 ? 0 : (negative[cell] ?? 0) === 1 ? -1 : 1;
149
+ const clampToUnit = (value) => value > 0 ? 1 : value < 0 ? -1 : 0;
150
+ const decodeSign = (x, y, stripeEnd) => {
151
+ const n = at(x, y);
152
+ const below = belowVisible(y, stripeEnd);
153
+ const horizontal = clampToUnit(contribution(n - 1) + contribution(n + 1));
154
+ const vertical = clampToUnit(contribution(n - stride) + (below ? contribution(n + stride) : 0));
155
+ const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * 3 + (vertical + 1)] ?? 0;
156
+ const decision = mq.decode(contexts, SIGN_CONTEXT_BASE + (packed & -9));
157
+ negative[n] = decision ^ ((packed & SIGN_XOR_FLAG) !== 0 ? 1 : 0);
158
+ };
159
+ const becomeSignificant = (x, y, plane, stripeEnd) => {
160
+ const n = at(x, y);
161
+ significant[n] = 1;
162
+ magnitude[n] = 1 << plane;
163
+ lastCodedPlane[n] = plane;
164
+ decodeSign(x, y, stripeEnd);
165
+ };
166
+ const significancePass = (plane) => {
167
+ for (let stripe = 0; stripe < height; stripe += STRIPE_HEIGHT) {
168
+ const stripeEnd = Math.min(stripe + STRIPE_HEIGHT, height);
169
+ for (let x = 0; x < width; x++) for (let y = stripe; y < stripeEnd; y++) {
170
+ const n = at(x, y);
171
+ if ((significant[n] ?? 0) === 1) continue;
172
+ const context = significanceContext(x, y, stripeEnd);
173
+ if (context === 0) continue;
174
+ if (mq.decode(contexts, context) === 1) becomeSignificant(x, y, plane, stripeEnd);
175
+ else lastCodedPlane[n] = plane;
176
+ codedThisPlane[n] = 1;
177
+ }
178
+ }
179
+ };
180
+ const refinementPass = (plane) => {
181
+ for (let stripe = 0; stripe < height; stripe += STRIPE_HEIGHT) {
182
+ const stripeEnd = Math.min(stripe + STRIPE_HEIGHT, height);
183
+ for (let x = 0; x < width; x++) for (let y = stripe; y < stripeEnd; y++) {
184
+ const n = at(x, y);
185
+ if ((significant[n] ?? 0) === 0 || (codedThisPlane[n] ?? 0) === 1) continue;
186
+ const context = (everRefined[n] ?? 0) === 1 ? MAGNITUDE_REFINEMENT_SUBSEQUENT : neighbourhoodIsSignificant(x, y, stripeEnd) ? MAGNITUDE_REFINEMENT_WITH_NEIGHBOURS : MAGNITUDE_REFINEMENT_NO_NEIGHBOURS;
187
+ if (mq.decode(contexts, context) === 1) magnitude[n] = (magnitude[n] ?? 0) | 1 << plane;
188
+ everRefined[n] = 1;
189
+ lastCodedPlane[n] = plane;
190
+ }
191
+ }
192
+ };
193
+ const cleanupPass = (plane) => {
194
+ for (let stripe = 0; stripe < height; stripe += STRIPE_HEIGHT) {
195
+ const stripeEnd = Math.min(stripe + STRIPE_HEIGHT, height);
196
+ const fullStripe = stripeEnd - stripe === STRIPE_HEIGHT;
197
+ for (let x = 0; x < width; x++) {
198
+ let y = stripe;
199
+ if (fullStripe && columnIsRunLengthEligible(x, stripe, stripeEnd)) {
200
+ if (mq.decode(contexts, RUN_LENGTH_CONTEXT) === 0) {
201
+ for (let row = stripe; row < stripeEnd; row++) lastCodedPlane[at(x, row)] = plane;
202
+ continue;
203
+ }
204
+ const firstSignificant = mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
205
+ for (let row = stripe; row < stripe + firstSignificant; row++) lastCodedPlane[at(x, row)] = plane;
206
+ y = stripe + firstSignificant;
207
+ becomeSignificant(x, y, plane, stripeEnd);
208
+ y++;
209
+ }
210
+ for (; y < stripeEnd; y++) {
211
+ const n = at(x, y);
212
+ if ((codedThisPlane[n] ?? 0) === 1 || (significant[n] ?? 0) === 1) continue;
213
+ if (mq.decode(contexts, significanceContext(x, y, stripeEnd)) === 1) becomeSignificant(x, y, plane, stripeEnd);
214
+ else lastCodedPlane[n] = plane;
215
+ }
216
+ }
217
+ }
218
+ if (segmentationSymbols) {
219
+ const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << 3 | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
220
+ if (symbol !== SEGMENTATION_SYMBOL) throw new require_image_jpeg2000_errors.Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(16)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
221
+ }
222
+ codedThisPlane.fill(0);
223
+ };
224
+ function columnIsRunLengthEligible(x, stripe, stripeEnd) {
225
+ for (let y = stripe; y < stripeEnd; y++) {
226
+ const n = at(x, y);
227
+ if ((significant[n] ?? 0) === 1 || (codedThisPlane[n] ?? 0) === 1) return false;
228
+ if (significanceContext(x, y, stripeEnd) !== 0) return false;
229
+ }
230
+ return true;
231
+ }
232
+ let plane = codedBitPlanes - 1;
233
+ let passType = PASS_CLEANUP;
234
+ for (let pass = 0; pass < totalPasses && plane >= 0; pass++) {
235
+ if (resetEachPass) resetContexts();
236
+ if (passType === PASS_SIGNIFICANCE) significancePass(plane);
237
+ else if (passType === PASS_REFINEMENT) refinementPass(plane);
238
+ else cleanupPass(plane);
239
+ passType++;
240
+ if (passType > PASS_CLEANUP) {
241
+ passType = PASS_SIGNIFICANCE;
242
+ plane--;
243
+ }
244
+ }
245
+ for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
246
+ const n = at(x, y);
247
+ if ((significant[n] ?? 0) === 0) continue;
248
+ const reconstructed = 2 * (magnitude[n] ?? 0) + (1 << (lastCodedPlane[n] ?? 0));
249
+ values[y * width + x] = (negative[n] ?? 0) === 1 ? -reconstructed : reconstructed;
250
+ }
251
+ return { values };
252
+ }
253
+ //#endregion
254
+ exports.decodeJpeg2000CodeBlock = decodeJpeg2000CodeBlock;
@@ -0,0 +1,18 @@
1
+ //#region src/image/jpeg2000-t1.d.ts
2
+ type Jpeg2000SubbandType = 'LL' | 'HL' | 'LH' | 'HH';
3
+ interface Jpeg2000CodeBlockDecodeOptions {
4
+ readonly width: number;
5
+ readonly height: number;
6
+ readonly subband: Jpeg2000SubbandType;
7
+ readonly zeroBitPlanes: number;
8
+ readonly maxBitPlanes: number;
9
+ readonly totalPasses: number;
10
+ readonly codeBlockStyle: number;
11
+ readonly data: Uint8Array<ArrayBuffer>;
12
+ }
13
+ interface Jpeg2000CodeBlockResult {
14
+ readonly values: Int32Array;
15
+ }
16
+ declare function decodeJpeg2000CodeBlock(options: Jpeg2000CodeBlockDecodeOptions): Jpeg2000CodeBlockResult;
17
+ //#endregion
18
+ export { Jpeg2000CodeBlockDecodeOptions, Jpeg2000CodeBlockResult, Jpeg2000SubbandType, decodeJpeg2000CodeBlock };
@@ -0,0 +1,18 @@
1
+ //#region src/image/jpeg2000-t1.d.ts
2
+ type Jpeg2000SubbandType = 'LL' | 'HL' | 'LH' | 'HH';
3
+ interface Jpeg2000CodeBlockDecodeOptions {
4
+ readonly width: number;
5
+ readonly height: number;
6
+ readonly subband: Jpeg2000SubbandType;
7
+ readonly zeroBitPlanes: number;
8
+ readonly maxBitPlanes: number;
9
+ readonly totalPasses: number;
10
+ readonly codeBlockStyle: number;
11
+ readonly data: Uint8Array<ArrayBuffer>;
12
+ }
13
+ interface Jpeg2000CodeBlockResult {
14
+ readonly values: Int32Array;
15
+ }
16
+ declare function decodeJpeg2000CodeBlock(options: Jpeg2000CodeBlockDecodeOptions): Jpeg2000CodeBlockResult;
17
+ //#endregion
18
+ export { Jpeg2000CodeBlockDecodeOptions, Jpeg2000CodeBlockResult, Jpeg2000SubbandType, decodeJpeg2000CodeBlock };
@@ -0,0 +1,253 @@
1
+ import { MqDecoder, createArithContexts } from "./jbig2-arith.js";
2
+ import { Jpeg2000ParseError, Jpeg2000UnsupportedError } from "./jpeg2000-errors.js";
3
+ //#region src/image/jpeg2000-t1.ts
4
+ const SIGN_CONTEXT_BASE = 9;
5
+ const MAGNITUDE_REFINEMENT_NO_NEIGHBOURS = 14;
6
+ const MAGNITUDE_REFINEMENT_WITH_NEIGHBOURS = 15;
7
+ const MAGNITUDE_REFINEMENT_SUBSEQUENT = 16;
8
+ const RUN_LENGTH_CONTEXT = 17;
9
+ const UNIFORM_CONTEXT = 18;
10
+ const CONTEXT_COUNT_BITS = 5;
11
+ const STYLE_SELECTIVE_BYPASS = 1;
12
+ const STYLE_RESET_CONTEXTS = 2;
13
+ const STYLE_TERMINATE_ALL = 4;
14
+ const STYLE_VERTICALLY_CAUSAL = 8;
15
+ const STYLE_SEGMENTATION_SYMBOLS = 32;
16
+ const SEGMENTATION_SYMBOL = 10;
17
+ const STRIPE_HEIGHT = 4;
18
+ const PASS_SIGNIFICANCE = 0;
19
+ const PASS_REFINEMENT = 1;
20
+ const PASS_CLEANUP = 2;
21
+ function throwForUnsupportedStyle(style) {
22
+ 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
+ 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
+ }
25
+ function zeroCodingContext(subband, horizontal, vertical, diagonal) {
26
+ if (subband === "HH") {
27
+ const straight = horizontal + vertical;
28
+ if (diagonal >= 3) return 8;
29
+ if (diagonal === 2) return straight >= 1 ? 7 : 6;
30
+ if (diagonal === 1) return straight >= 2 ? 5 : straight === 1 ? 4 : 3;
31
+ return straight >= 2 ? 2 : straight === 1 ? 1 : 0;
32
+ }
33
+ const primary = subband === "HL" ? vertical : horizontal;
34
+ const secondary = subband === "HL" ? horizontal : vertical;
35
+ if (primary === 2) return 8;
36
+ if (primary === 1) {
37
+ if (secondary >= 1) return 7;
38
+ return diagonal >= 1 ? 6 : 5;
39
+ }
40
+ if (secondary === 2) return 4;
41
+ if (secondary === 1) return 3;
42
+ return diagonal >= 2 ? 2 : diagonal === 1 ? 1 : 0;
43
+ }
44
+ const SIGN_CONTEXT_TABLE = (() => {
45
+ const rows = [
46
+ [
47
+ 1,
48
+ 1,
49
+ 4,
50
+ 0
51
+ ],
52
+ [
53
+ 1,
54
+ 0,
55
+ 3,
56
+ 0
57
+ ],
58
+ [
59
+ 1,
60
+ -1,
61
+ 2,
62
+ 0
63
+ ],
64
+ [
65
+ 0,
66
+ 1,
67
+ 1,
68
+ 0
69
+ ],
70
+ [
71
+ 0,
72
+ 0,
73
+ 0,
74
+ 0
75
+ ],
76
+ [
77
+ 0,
78
+ -1,
79
+ 1,
80
+ 1
81
+ ],
82
+ [
83
+ -1,
84
+ 1,
85
+ 2,
86
+ 1
87
+ ],
88
+ [
89
+ -1,
90
+ 0,
91
+ 3,
92
+ 1
93
+ ],
94
+ [
95
+ -1,
96
+ -1,
97
+ 4,
98
+ 1
99
+ ]
100
+ ];
101
+ const table = new Array(9).fill(0);
102
+ for (const [horizontal, vertical, offset, xorBit] of rows) table[(horizontal + 1) * 3 + (vertical + 1)] = offset | xorBit << 3;
103
+ return table;
104
+ })();
105
+ const SIGN_XOR_FLAG = 8;
106
+ function decodeJpeg2000CodeBlock(options) {
107
+ const { width, height, subband, zeroBitPlanes, maxBitPlanes, totalPasses, codeBlockStyle, data } = options;
108
+ throwForUnsupportedStyle(codeBlockStyle);
109
+ const values = new Int32Array(Math.max(width * height, 0));
110
+ const codedBitPlanes = maxBitPlanes - zeroBitPlanes;
111
+ if (width <= 0 || height <= 0 || codedBitPlanes <= 0 || totalPasses <= 0 || data.length === 0) return { values };
112
+ const stride = width + 2;
113
+ const cellCount = stride * (height + 2);
114
+ const significant = new Uint8Array(cellCount);
115
+ const negative = new Uint8Array(cellCount);
116
+ const codedThisPlane = new Uint8Array(cellCount);
117
+ const everRefined = new Uint8Array(cellCount);
118
+ const magnitude = new Int32Array(cellCount);
119
+ const lastCodedPlane = new Int32Array(cellCount);
120
+ const contexts = createArithContexts(CONTEXT_COUNT_BITS);
121
+ const resetContexts = () => {
122
+ contexts.fill(0);
123
+ contexts[0] = 8;
124
+ contexts[RUN_LENGTH_CONTEXT] = 6;
125
+ contexts[UNIFORM_CONTEXT] = 92;
126
+ };
127
+ resetContexts();
128
+ const mq = new MqDecoder(data, 0, data.length);
129
+ const verticallyCausal = (codeBlockStyle & STYLE_VERTICALLY_CAUSAL) !== 0;
130
+ const segmentationSymbols = (codeBlockStyle & STYLE_SEGMENTATION_SYMBOLS) !== 0;
131
+ const resetEachPass = (codeBlockStyle & STYLE_RESET_CONTEXTS) !== 0;
132
+ const at = (x, y) => (y + 1) * stride + (x + 1);
133
+ const belowVisible = (y, stripeEnd) => !verticallyCausal || y + 1 < stripeEnd;
134
+ const significanceContext = (x, y, stripeEnd) => {
135
+ const n = at(x, y);
136
+ const below = belowVisible(y, stripeEnd);
137
+ const horizontal = (significant[n - 1] ?? 0) + (significant[n + 1] ?? 0);
138
+ const vertical = (significant[n - stride] ?? 0) + (below ? significant[n + stride] ?? 0 : 0);
139
+ const diagonal = (significant[n - stride - 1] ?? 0) + (significant[n - stride + 1] ?? 0) + (below ? (significant[n + stride - 1] ?? 0) + (significant[n + stride + 1] ?? 0) : 0);
140
+ return zeroCodingContext(subband, horizontal, vertical, diagonal);
141
+ };
142
+ const neighbourhoodIsSignificant = (x, y, stripeEnd) => {
143
+ const n = at(x, y);
144
+ const below = belowVisible(y, stripeEnd);
145
+ return (significant[n - 1] ?? 0) + (significant[n + 1] ?? 0) + (significant[n - stride] ?? 0) + (below ? significant[n + stride] ?? 0 : 0) + ((significant[n - stride - 1] ?? 0) + (significant[n - stride + 1] ?? 0) + (below ? (significant[n + stride - 1] ?? 0) + (significant[n + stride + 1] ?? 0) : 0)) > 0;
146
+ };
147
+ const contribution = (cell) => (significant[cell] ?? 0) === 0 ? 0 : (negative[cell] ?? 0) === 1 ? -1 : 1;
148
+ const clampToUnit = (value) => value > 0 ? 1 : value < 0 ? -1 : 0;
149
+ const decodeSign = (x, y, stripeEnd) => {
150
+ const n = at(x, y);
151
+ const below = belowVisible(y, stripeEnd);
152
+ const horizontal = clampToUnit(contribution(n - 1) + contribution(n + 1));
153
+ const vertical = clampToUnit(contribution(n - stride) + (below ? contribution(n + stride) : 0));
154
+ const packed = SIGN_CONTEXT_TABLE[(horizontal + 1) * 3 + (vertical + 1)] ?? 0;
155
+ const decision = mq.decode(contexts, SIGN_CONTEXT_BASE + (packed & -9));
156
+ negative[n] = decision ^ ((packed & SIGN_XOR_FLAG) !== 0 ? 1 : 0);
157
+ };
158
+ const becomeSignificant = (x, y, plane, stripeEnd) => {
159
+ const n = at(x, y);
160
+ significant[n] = 1;
161
+ magnitude[n] = 1 << plane;
162
+ lastCodedPlane[n] = plane;
163
+ decodeSign(x, y, stripeEnd);
164
+ };
165
+ const significancePass = (plane) => {
166
+ for (let stripe = 0; stripe < height; stripe += STRIPE_HEIGHT) {
167
+ const stripeEnd = Math.min(stripe + STRIPE_HEIGHT, height);
168
+ for (let x = 0; x < width; x++) for (let y = stripe; y < stripeEnd; y++) {
169
+ const n = at(x, y);
170
+ if ((significant[n] ?? 0) === 1) continue;
171
+ const context = significanceContext(x, y, stripeEnd);
172
+ if (context === 0) continue;
173
+ if (mq.decode(contexts, context) === 1) becomeSignificant(x, y, plane, stripeEnd);
174
+ else lastCodedPlane[n] = plane;
175
+ codedThisPlane[n] = 1;
176
+ }
177
+ }
178
+ };
179
+ const refinementPass = (plane) => {
180
+ for (let stripe = 0; stripe < height; stripe += STRIPE_HEIGHT) {
181
+ const stripeEnd = Math.min(stripe + STRIPE_HEIGHT, height);
182
+ for (let x = 0; x < width; x++) for (let y = stripe; y < stripeEnd; y++) {
183
+ const n = at(x, y);
184
+ if ((significant[n] ?? 0) === 0 || (codedThisPlane[n] ?? 0) === 1) continue;
185
+ const context = (everRefined[n] ?? 0) === 1 ? MAGNITUDE_REFINEMENT_SUBSEQUENT : neighbourhoodIsSignificant(x, y, stripeEnd) ? MAGNITUDE_REFINEMENT_WITH_NEIGHBOURS : MAGNITUDE_REFINEMENT_NO_NEIGHBOURS;
186
+ if (mq.decode(contexts, context) === 1) magnitude[n] = (magnitude[n] ?? 0) | 1 << plane;
187
+ everRefined[n] = 1;
188
+ lastCodedPlane[n] = plane;
189
+ }
190
+ }
191
+ };
192
+ const cleanupPass = (plane) => {
193
+ for (let stripe = 0; stripe < height; stripe += STRIPE_HEIGHT) {
194
+ const stripeEnd = Math.min(stripe + STRIPE_HEIGHT, height);
195
+ const fullStripe = stripeEnd - stripe === STRIPE_HEIGHT;
196
+ for (let x = 0; x < width; x++) {
197
+ let y = stripe;
198
+ if (fullStripe && columnIsRunLengthEligible(x, stripe, stripeEnd)) {
199
+ if (mq.decode(contexts, RUN_LENGTH_CONTEXT) === 0) {
200
+ for (let row = stripe; row < stripeEnd; row++) lastCodedPlane[at(x, row)] = plane;
201
+ continue;
202
+ }
203
+ const firstSignificant = mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
204
+ for (let row = stripe; row < stripe + firstSignificant; row++) lastCodedPlane[at(x, row)] = plane;
205
+ y = stripe + firstSignificant;
206
+ becomeSignificant(x, y, plane, stripeEnd);
207
+ y++;
208
+ }
209
+ for (; y < stripeEnd; y++) {
210
+ const n = at(x, y);
211
+ if ((codedThisPlane[n] ?? 0) === 1 || (significant[n] ?? 0) === 1) continue;
212
+ if (mq.decode(contexts, significanceContext(x, y, stripeEnd)) === 1) becomeSignificant(x, y, plane, stripeEnd);
213
+ else lastCodedPlane[n] = plane;
214
+ }
215
+ }
216
+ }
217
+ if (segmentationSymbols) {
218
+ const symbol = mq.decode(contexts, UNIFORM_CONTEXT) << 3 | mq.decode(contexts, UNIFORM_CONTEXT) << 2 | mq.decode(contexts, UNIFORM_CONTEXT) << 1 | mq.decode(contexts, UNIFORM_CONTEXT);
219
+ if (symbol !== SEGMENTATION_SYMBOL) throw new Jpeg2000ParseError(`a cleanup pass ended with segmentation symbol 0x${symbol.toString(16)} rather than the 0xA ISO/IEC 15444-1 D.3.4 requires, so this code-block's coded data is corrupt`);
220
+ }
221
+ codedThisPlane.fill(0);
222
+ };
223
+ function columnIsRunLengthEligible(x, stripe, stripeEnd) {
224
+ for (let y = stripe; y < stripeEnd; y++) {
225
+ const n = at(x, y);
226
+ if ((significant[n] ?? 0) === 1 || (codedThisPlane[n] ?? 0) === 1) return false;
227
+ if (significanceContext(x, y, stripeEnd) !== 0) return false;
228
+ }
229
+ return true;
230
+ }
231
+ let plane = codedBitPlanes - 1;
232
+ let passType = PASS_CLEANUP;
233
+ for (let pass = 0; pass < totalPasses && plane >= 0; pass++) {
234
+ if (resetEachPass) resetContexts();
235
+ if (passType === PASS_SIGNIFICANCE) significancePass(plane);
236
+ else if (passType === PASS_REFINEMENT) refinementPass(plane);
237
+ else cleanupPass(plane);
238
+ passType++;
239
+ if (passType > PASS_CLEANUP) {
240
+ passType = PASS_SIGNIFICANCE;
241
+ plane--;
242
+ }
243
+ }
244
+ for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
245
+ const n = at(x, y);
246
+ if ((significant[n] ?? 0) === 0) continue;
247
+ const reconstructed = 2 * (magnitude[n] ?? 0) + (1 << (lastCodedPlane[n] ?? 0));
248
+ values[y * width + x] = (negative[n] ?? 0) === 1 ? -reconstructed : reconstructed;
249
+ }
250
+ return { values };
251
+ }
252
+ //#endregion
253
+ export { decodeJpeg2000CodeBlock };