pdf-codec 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -12
- package/dist/content-write.cjs +2 -3
- package/dist/content-write.js +1 -2
- package/dist/crypto/aes.cjs +166 -0
- package/dist/crypto/aes.d.cts +6 -0
- package/dist/crypto/aes.d.ts +6 -0
- package/dist/crypto/aes.js +163 -0
- package/dist/crypto/md5.cjs +215 -0
- package/dist/crypto/md5.d.cts +4 -0
- package/dist/crypto/md5.d.ts +4 -0
- package/dist/crypto/md5.js +214 -0
- package/dist/crypto/rc4.cjs +29 -0
- package/dist/crypto/rc4.d.cts +4 -0
- package/dist/crypto/rc4.d.ts +4 -0
- package/dist/crypto/rc4.js +28 -0
- package/dist/crypto/sha2.cjs +261 -0
- package/dist/crypto/sha2.d.cts +6 -0
- package/dist/crypto/sha2.d.ts +6 -0
- package/dist/crypto/sha2.js +258 -0
- package/dist/diagnostics.cjs +7 -0
- package/dist/diagnostics.d.cts +4 -1
- package/dist/diagnostics.d.ts +4 -1
- package/dist/diagnostics.js +7 -1
- package/dist/document.cjs +38 -2
- package/dist/document.js +38 -2
- package/dist/encrypt.cjs +264 -0
- package/dist/encrypt.d.cts +11 -0
- package/dist/encrypt.d.ts +11 -0
- package/dist/encrypt.js +263 -0
- package/dist/filters.cjs +19 -1
- package/dist/filters.js +19 -1
- package/dist/image/ccitt.cjs +488 -0
- package/dist/image/ccitt.d.cts +17 -0
- package/dist/image/ccitt.d.ts +17 -0
- package/dist/image/ccitt.js +487 -0
- package/dist/images-read.cjs +1 -4
- package/dist/images-read.js +2 -5
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/interpret.cjs +173 -38
- package/dist/interpret.d.cts +27 -10
- package/dist/interpret.d.ts +27 -10
- package/dist/interpret.js +174 -39
- package/dist/math-font-write.cjs +1 -1
- package/dist/math-font-write.js +1 -1
- package/dist/{matrix-B3c2_a2f.d.cts → matrix-BHzJESll.d.cts} +2 -1
- package/dist/{matrix-B3c2_a2f.d.ts → matrix-BHzJESll.d.ts} +2 -1
- package/dist/matrix.cjs +2 -0
- package/dist/matrix.d.cts +2 -2
- package/dist/matrix.d.ts +2 -2
- package/dist/matrix.js +2 -1
- package/dist/objects.cjs +4 -0
- package/dist/objects.d.cts +2 -1
- package/dist/objects.d.ts +2 -1
- package/dist/objects.js +4 -1
- package/dist/read.cjs +43 -4
- package/dist/read.d.cts +1 -1
- package/dist/read.d.ts +1 -1
- package/dist/read.js +43 -4
- package/dist/write.cjs +1 -1
- package/dist/write.js +1 -1
- package/package.json +1 -1
package/dist/filters.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isAsciiWhitespace } from "./bytes/reader.js";
|
|
2
|
+
import { asArray, asBool, asDict, asName, asNumber, dictGet } from "./objects.js";
|
|
2
3
|
import { inflateTolerant } from "./bytes/flate.js";
|
|
3
|
-
import {
|
|
4
|
+
import { decodeCcittFax } from "./image/ccitt.js";
|
|
4
5
|
import { applyPredictor, readPredictorParams } from "./predictors.js";
|
|
5
6
|
//#region src/filters.ts
|
|
6
7
|
function decodeStream(raw, dict, sink) {
|
|
@@ -17,6 +18,7 @@ function decodeStream(raw, dict, sink) {
|
|
|
17
18
|
} else if (filter === "ASCII85Decode" || filter === "A85") bytes = ascii85Decode(bytes);
|
|
18
19
|
else if (filter === "ASCIIHexDecode" || filter === "AHx") bytes = asciiHexDecode(bytes);
|
|
19
20
|
else if (filter === "RunLengthDecode" || filter === "RL") bytes = runLengthDecode(bytes);
|
|
21
|
+
else if (filter === "CCITTFaxDecode" || filter === "CCF") bytes = ccittFaxDecode(bytes, parm, dict, sink);
|
|
20
22
|
else if (filter === "DCTDecode" || filter === "DCT") return {
|
|
21
23
|
bytes,
|
|
22
24
|
remainingFilter: "DCTDecode"
|
|
@@ -38,6 +40,22 @@ function decodeStream(raw, dict, sink) {
|
|
|
38
40
|
function applyPredictorIfPresent(data, parm, sink) {
|
|
39
41
|
return applyPredictor(data, readPredictorParams(parm), sink);
|
|
40
42
|
}
|
|
43
|
+
function ccittFaxDecode(data, parm, dict, sink) {
|
|
44
|
+
const parmGet = (key) => parm !== void 0 ? dictGet(parm, key) : void 0;
|
|
45
|
+
const rows = asNumber(parmGet("Rows")) ?? asNumber(dictGet(dict, "Height") ?? dictGet(dict, "H"));
|
|
46
|
+
return decodeCcittFax(data, {
|
|
47
|
+
k: asNumber(parmGet("K")),
|
|
48
|
+
columns: asNumber(parmGet("Columns")),
|
|
49
|
+
rows,
|
|
50
|
+
blackIs1: asBool(parmGet("BlackIs1")),
|
|
51
|
+
encodedByteAlign: asBool(parmGet("EncodedByteAlign")),
|
|
52
|
+
onWarning: (message) => sink({
|
|
53
|
+
code: "pdf/ccitt-fax-degraded",
|
|
54
|
+
severity: "warning",
|
|
55
|
+
message
|
|
56
|
+
})
|
|
57
|
+
}).bytes;
|
|
58
|
+
}
|
|
41
59
|
function filterNames(dict) {
|
|
42
60
|
const filterObj = dictGet(dict, "Filter") ?? dictGet(dict, "F");
|
|
43
61
|
if (filterObj === void 0) return [];
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_bytes_writer = require("../bytes/writer.cjs");
|
|
3
|
+
//#region src/image/ccitt.ts
|
|
4
|
+
const WHITE_TERMINATING_AND_MAKEUP = [
|
|
5
|
+
["00110101", 0],
|
|
6
|
+
["000111", 1],
|
|
7
|
+
["0111", 2],
|
|
8
|
+
["1000", 3],
|
|
9
|
+
["1011", 4],
|
|
10
|
+
["1100", 5],
|
|
11
|
+
["1110", 6],
|
|
12
|
+
["1111", 7],
|
|
13
|
+
["10011", 8],
|
|
14
|
+
["10100", 9],
|
|
15
|
+
["00111", 10],
|
|
16
|
+
["01000", 11],
|
|
17
|
+
["001000", 12],
|
|
18
|
+
["000011", 13],
|
|
19
|
+
["110100", 14],
|
|
20
|
+
["110101", 15],
|
|
21
|
+
["101010", 16],
|
|
22
|
+
["101011", 17],
|
|
23
|
+
["0100111", 18],
|
|
24
|
+
["0001100", 19],
|
|
25
|
+
["0001000", 20],
|
|
26
|
+
["0010111", 21],
|
|
27
|
+
["0000011", 22],
|
|
28
|
+
["0000100", 23],
|
|
29
|
+
["0101000", 24],
|
|
30
|
+
["0101011", 25],
|
|
31
|
+
["0010011", 26],
|
|
32
|
+
["0100100", 27],
|
|
33
|
+
["0011000", 28],
|
|
34
|
+
["00000010", 29],
|
|
35
|
+
["00000011", 30],
|
|
36
|
+
["00011010", 31],
|
|
37
|
+
["00011011", 32],
|
|
38
|
+
["00010010", 33],
|
|
39
|
+
["00010011", 34],
|
|
40
|
+
["00010100", 35],
|
|
41
|
+
["00010101", 36],
|
|
42
|
+
["00010110", 37],
|
|
43
|
+
["00010111", 38],
|
|
44
|
+
["00101000", 39],
|
|
45
|
+
["00101001", 40],
|
|
46
|
+
["00101010", 41],
|
|
47
|
+
["00101011", 42],
|
|
48
|
+
["00101100", 43],
|
|
49
|
+
["00101101", 44],
|
|
50
|
+
["00000100", 45],
|
|
51
|
+
["00000101", 46],
|
|
52
|
+
["00001010", 47],
|
|
53
|
+
["00001011", 48],
|
|
54
|
+
["01010010", 49],
|
|
55
|
+
["01010011", 50],
|
|
56
|
+
["01010100", 51],
|
|
57
|
+
["01010101", 52],
|
|
58
|
+
["00100100", 53],
|
|
59
|
+
["00100101", 54],
|
|
60
|
+
["01011000", 55],
|
|
61
|
+
["01011001", 56],
|
|
62
|
+
["01011010", 57],
|
|
63
|
+
["01011011", 58],
|
|
64
|
+
["01001010", 59],
|
|
65
|
+
["01001011", 60],
|
|
66
|
+
["00110010", 61],
|
|
67
|
+
["00110011", 62],
|
|
68
|
+
["00110100", 63],
|
|
69
|
+
["11011", 64],
|
|
70
|
+
["10010", 128],
|
|
71
|
+
["010111", 192],
|
|
72
|
+
["0110111", 256],
|
|
73
|
+
["00110110", 320],
|
|
74
|
+
["00110111", 384],
|
|
75
|
+
["01100100", 448],
|
|
76
|
+
["01100101", 512],
|
|
77
|
+
["01101000", 576],
|
|
78
|
+
["01100111", 640],
|
|
79
|
+
["011001100", 704],
|
|
80
|
+
["011001101", 768],
|
|
81
|
+
["011010010", 832],
|
|
82
|
+
["011010011", 896],
|
|
83
|
+
["011010100", 960],
|
|
84
|
+
["011010101", 1024],
|
|
85
|
+
["011010110", 1088],
|
|
86
|
+
["011010111", 1152],
|
|
87
|
+
["011011000", 1216],
|
|
88
|
+
["011011001", 1280],
|
|
89
|
+
["011011010", 1344],
|
|
90
|
+
["011011011", 1408],
|
|
91
|
+
["010011000", 1472],
|
|
92
|
+
["010011001", 1536],
|
|
93
|
+
["010011010", 1600],
|
|
94
|
+
["011000", 1664],
|
|
95
|
+
["010011011", 1728]
|
|
96
|
+
];
|
|
97
|
+
const BLACK_TERMINATING_AND_MAKEUP = [
|
|
98
|
+
["0000110111", 0],
|
|
99
|
+
["010", 1],
|
|
100
|
+
["11", 2],
|
|
101
|
+
["10", 3],
|
|
102
|
+
["011", 4],
|
|
103
|
+
["0011", 5],
|
|
104
|
+
["0010", 6],
|
|
105
|
+
["00011", 7],
|
|
106
|
+
["000101", 8],
|
|
107
|
+
["000100", 9],
|
|
108
|
+
["0000100", 10],
|
|
109
|
+
["0000101", 11],
|
|
110
|
+
["0000111", 12],
|
|
111
|
+
["00000100", 13],
|
|
112
|
+
["00000111", 14],
|
|
113
|
+
["000011000", 15],
|
|
114
|
+
["0000010111", 16],
|
|
115
|
+
["0000011000", 17],
|
|
116
|
+
["0000001000", 18],
|
|
117
|
+
["00001100111", 19],
|
|
118
|
+
["00001101000", 20],
|
|
119
|
+
["00001101100", 21],
|
|
120
|
+
["00000110111", 22],
|
|
121
|
+
["00000101000", 23],
|
|
122
|
+
["00000010111", 24],
|
|
123
|
+
["00000011000", 25],
|
|
124
|
+
["000011001010", 26],
|
|
125
|
+
["000011001011", 27],
|
|
126
|
+
["000011001100", 28],
|
|
127
|
+
["000011001101", 29],
|
|
128
|
+
["000001101000", 30],
|
|
129
|
+
["000001101001", 31],
|
|
130
|
+
["000001101010", 32],
|
|
131
|
+
["000001101011", 33],
|
|
132
|
+
["000011010010", 34],
|
|
133
|
+
["000011010011", 35],
|
|
134
|
+
["000011010100", 36],
|
|
135
|
+
["000011010101", 37],
|
|
136
|
+
["000011010110", 38],
|
|
137
|
+
["000011010111", 39],
|
|
138
|
+
["000001101100", 40],
|
|
139
|
+
["000001101101", 41],
|
|
140
|
+
["000011011010", 42],
|
|
141
|
+
["000011011011", 43],
|
|
142
|
+
["000001010100", 44],
|
|
143
|
+
["000001010101", 45],
|
|
144
|
+
["000001010110", 46],
|
|
145
|
+
["000001010111", 47],
|
|
146
|
+
["000001100100", 48],
|
|
147
|
+
["000001100101", 49],
|
|
148
|
+
["000001010010", 50],
|
|
149
|
+
["000001010011", 51],
|
|
150
|
+
["000000100100", 52],
|
|
151
|
+
["000000110111", 53],
|
|
152
|
+
["000000111000", 54],
|
|
153
|
+
["000000100111", 55],
|
|
154
|
+
["000000101000", 56],
|
|
155
|
+
["000001011000", 57],
|
|
156
|
+
["000001011001", 58],
|
|
157
|
+
["000000101011", 59],
|
|
158
|
+
["000000101100", 60],
|
|
159
|
+
["000001011010", 61],
|
|
160
|
+
["000001100110", 62],
|
|
161
|
+
["000001100111", 63],
|
|
162
|
+
["0000001111", 64],
|
|
163
|
+
["000011001000", 128],
|
|
164
|
+
["000011001001", 192],
|
|
165
|
+
["000001011011", 256],
|
|
166
|
+
["000000110011", 320],
|
|
167
|
+
["000000110100", 384],
|
|
168
|
+
["000000110101", 448],
|
|
169
|
+
["0000001101100", 512],
|
|
170
|
+
["0000001101101", 576],
|
|
171
|
+
["0000001001010", 640],
|
|
172
|
+
["0000001001011", 704],
|
|
173
|
+
["0000001001100", 768],
|
|
174
|
+
["0000001001101", 832],
|
|
175
|
+
["0000001110010", 896],
|
|
176
|
+
["0000001110011", 960],
|
|
177
|
+
["0000001110100", 1024],
|
|
178
|
+
["0000001110101", 1088],
|
|
179
|
+
["0000001110110", 1152],
|
|
180
|
+
["0000001110111", 1216],
|
|
181
|
+
["0000001010010", 1280],
|
|
182
|
+
["0000001010011", 1344],
|
|
183
|
+
["0000001010100", 1408],
|
|
184
|
+
["0000001010101", 1472],
|
|
185
|
+
["0000001011010", 1536],
|
|
186
|
+
["0000001011011", 1600],
|
|
187
|
+
["0000001100100", 1664],
|
|
188
|
+
["0000001100101", 1728]
|
|
189
|
+
];
|
|
190
|
+
const EXTENDED_MAKEUP = [
|
|
191
|
+
["00000001000", 1792],
|
|
192
|
+
["00000001100", 1856],
|
|
193
|
+
["00000001101", 1920],
|
|
194
|
+
["000000010010", 1984],
|
|
195
|
+
["000000010011", 2048],
|
|
196
|
+
["000000010100", 2112],
|
|
197
|
+
["000000010101", 2176],
|
|
198
|
+
["000000010110", 2240],
|
|
199
|
+
["000000010111", 2304],
|
|
200
|
+
["000000011100", 2368],
|
|
201
|
+
["000000011101", 2432],
|
|
202
|
+
["000000011110", 2496],
|
|
203
|
+
["000000011111", 2560]
|
|
204
|
+
];
|
|
205
|
+
const TERMINATING_RUN_LIMIT = 64;
|
|
206
|
+
const MAX_RUN_CODE_BITS = 14;
|
|
207
|
+
const MODE_CODES = [
|
|
208
|
+
["1", {
|
|
209
|
+
kind: "vertical",
|
|
210
|
+
delta: 0
|
|
211
|
+
}],
|
|
212
|
+
["011", {
|
|
213
|
+
kind: "vertical",
|
|
214
|
+
delta: 1
|
|
215
|
+
}],
|
|
216
|
+
["010", {
|
|
217
|
+
kind: "vertical",
|
|
218
|
+
delta: -1
|
|
219
|
+
}],
|
|
220
|
+
["001", {
|
|
221
|
+
kind: "horizontal",
|
|
222
|
+
delta: 0
|
|
223
|
+
}],
|
|
224
|
+
["0001", {
|
|
225
|
+
kind: "pass",
|
|
226
|
+
delta: 0
|
|
227
|
+
}],
|
|
228
|
+
["000011", {
|
|
229
|
+
kind: "vertical",
|
|
230
|
+
delta: 2
|
|
231
|
+
}],
|
|
232
|
+
["000010", {
|
|
233
|
+
kind: "vertical",
|
|
234
|
+
delta: -2
|
|
235
|
+
}],
|
|
236
|
+
["0000011", {
|
|
237
|
+
kind: "vertical",
|
|
238
|
+
delta: 3
|
|
239
|
+
}],
|
|
240
|
+
["0000010", {
|
|
241
|
+
kind: "vertical",
|
|
242
|
+
delta: -3
|
|
243
|
+
}],
|
|
244
|
+
["0000001", {
|
|
245
|
+
kind: "extension",
|
|
246
|
+
delta: 0
|
|
247
|
+
}]
|
|
248
|
+
];
|
|
249
|
+
const MAX_MODE_CODE_BITS = 7;
|
|
250
|
+
const EOL_MIN_ZEROS = 11;
|
|
251
|
+
const MAX_FILL_ZERO_BITS = 512;
|
|
252
|
+
function codeKey(bitLength, code) {
|
|
253
|
+
return bitLength * 2 ** 16 + code;
|
|
254
|
+
}
|
|
255
|
+
function buildCodeTable(...groups) {
|
|
256
|
+
const table = /* @__PURE__ */ new Map();
|
|
257
|
+
for (const group of groups) for (const [bits, run] of group) table.set(codeKey(bits.length, Number.parseInt(bits, 2)), run);
|
|
258
|
+
return table;
|
|
259
|
+
}
|
|
260
|
+
const WHITE_CODE_TABLE = buildCodeTable(WHITE_TERMINATING_AND_MAKEUP, EXTENDED_MAKEUP);
|
|
261
|
+
const BLACK_CODE_TABLE = buildCodeTable(BLACK_TERMINATING_AND_MAKEUP, EXTENDED_MAKEUP);
|
|
262
|
+
const MODE_CODE_TABLE = new Map(MODE_CODES.map(([bits, mode]) => [codeKey(bits.length, Number.parseInt(bits, 2)), mode]));
|
|
263
|
+
const BITS_PER_BYTE = 8;
|
|
264
|
+
var CcittBitReader = class {
|
|
265
|
+
data;
|
|
266
|
+
position = 0;
|
|
267
|
+
constructor(data) {
|
|
268
|
+
this.data = data;
|
|
269
|
+
}
|
|
270
|
+
get bitPosition() {
|
|
271
|
+
return this.position;
|
|
272
|
+
}
|
|
273
|
+
set bitPosition(value) {
|
|
274
|
+
this.position = value;
|
|
275
|
+
}
|
|
276
|
+
get exhausted() {
|
|
277
|
+
return this.position >= this.data.length * BITS_PER_BYTE;
|
|
278
|
+
}
|
|
279
|
+
readBit() {
|
|
280
|
+
if (this.exhausted) return -1;
|
|
281
|
+
const bit = (this.data[this.position >> 3] ?? 0) >> 7 - (this.position & 7) & 1;
|
|
282
|
+
this.position++;
|
|
283
|
+
return bit;
|
|
284
|
+
}
|
|
285
|
+
alignToByte() {
|
|
286
|
+
this.position = Math.ceil(this.position / BITS_PER_BYTE) * BITS_PER_BYTE;
|
|
287
|
+
}
|
|
288
|
+
get atZeroPadding() {
|
|
289
|
+
const remaining = this.data.length * BITS_PER_BYTE - this.position;
|
|
290
|
+
if (remaining <= 0) return true;
|
|
291
|
+
if (remaining >= BITS_PER_BYTE) return false;
|
|
292
|
+
return ((this.data[this.data.length - 1] ?? 0) & (1 << remaining) - 1) === 0;
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
function readSingleRunCode(reader, table) {
|
|
296
|
+
let code = 0;
|
|
297
|
+
for (let bitLength = 1; bitLength <= MAX_RUN_CODE_BITS; bitLength++) {
|
|
298
|
+
const bit = reader.readBit();
|
|
299
|
+
if (bit < 0) return;
|
|
300
|
+
code = code << 1 | bit;
|
|
301
|
+
const run = table.get(codeKey(bitLength, code));
|
|
302
|
+
if (run !== void 0) return run;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function readRunLength(reader, black) {
|
|
306
|
+
const table = black ? BLACK_CODE_TABLE : WHITE_CODE_TABLE;
|
|
307
|
+
let total = 0;
|
|
308
|
+
for (;;) {
|
|
309
|
+
const run = readSingleRunCode(reader, table);
|
|
310
|
+
if (run === void 0) return;
|
|
311
|
+
total += run;
|
|
312
|
+
if (run < TERMINATING_RUN_LIMIT) return total;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function readModeCode(reader) {
|
|
316
|
+
let code = 0;
|
|
317
|
+
for (let bitLength = 1; bitLength <= MAX_MODE_CODE_BITS; bitLength++) {
|
|
318
|
+
const bit = reader.readBit();
|
|
319
|
+
if (bit < 0) return {
|
|
320
|
+
kind: "invalid",
|
|
321
|
+
delta: 0
|
|
322
|
+
};
|
|
323
|
+
code = code << 1 | bit;
|
|
324
|
+
const mode = MODE_CODE_TABLE.get(codeKey(bitLength, code));
|
|
325
|
+
if (mode !== void 0) return mode;
|
|
326
|
+
}
|
|
327
|
+
return code === 0 ? {
|
|
328
|
+
kind: "eol-prefix",
|
|
329
|
+
delta: 0
|
|
330
|
+
} : {
|
|
331
|
+
kind: "invalid",
|
|
332
|
+
delta: 0
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function tryReadEol(reader) {
|
|
336
|
+
const start = reader.bitPosition;
|
|
337
|
+
let zeros = 0;
|
|
338
|
+
for (;;) {
|
|
339
|
+
const bit = reader.readBit();
|
|
340
|
+
if (bit < 0) {
|
|
341
|
+
reader.bitPosition = start;
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
if (bit === 0) {
|
|
345
|
+
zeros++;
|
|
346
|
+
if (zeros > MAX_FILL_ZERO_BITS) {
|
|
347
|
+
reader.bitPosition = start;
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
if (zeros >= EOL_MIN_ZEROS) return true;
|
|
353
|
+
reader.bitPosition = start;
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
function findB1Index(reference, a0, color) {
|
|
358
|
+
let index = 0;
|
|
359
|
+
while (index < reference.length && reference[index] <= a0) index++;
|
|
360
|
+
if (index < reference.length && (index & 1) !== color) index++;
|
|
361
|
+
return index;
|
|
362
|
+
}
|
|
363
|
+
function elementAt(reference, index, columns) {
|
|
364
|
+
return index < reference.length ? reference[index] : columns;
|
|
365
|
+
}
|
|
366
|
+
function decode1dRow(reader, columns) {
|
|
367
|
+
const transitions = [];
|
|
368
|
+
let position = 0;
|
|
369
|
+
let black = false;
|
|
370
|
+
while (position < columns) {
|
|
371
|
+
const run = readRunLength(reader, black);
|
|
372
|
+
if (run === void 0) return;
|
|
373
|
+
position = Math.min(columns, position + run);
|
|
374
|
+
transitions.push(position);
|
|
375
|
+
black = !black;
|
|
376
|
+
}
|
|
377
|
+
return transitions;
|
|
378
|
+
}
|
|
379
|
+
function decode2dRow(reader, reference, columns) {
|
|
380
|
+
const transitions = [];
|
|
381
|
+
let a0 = -1;
|
|
382
|
+
let color = 0;
|
|
383
|
+
const maxTransitions = columns + 2;
|
|
384
|
+
while (a0 < columns) {
|
|
385
|
+
if (transitions.length > maxTransitions) return;
|
|
386
|
+
const mode = readModeCode(reader);
|
|
387
|
+
if (mode.kind === "invalid" || mode.kind === "extension") return;
|
|
388
|
+
if (mode.kind === "eol-prefix") return;
|
|
389
|
+
const b1Index = findB1Index(reference, a0, color);
|
|
390
|
+
const b1 = elementAt(reference, b1Index, columns);
|
|
391
|
+
const b2 = elementAt(reference, b1Index + 1, columns);
|
|
392
|
+
if (mode.kind === "pass") {
|
|
393
|
+
a0 = b2;
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (mode.kind === "horizontal") {
|
|
397
|
+
const start = a0 < 0 ? 0 : a0;
|
|
398
|
+
const firstRun = readRunLength(reader, color === 1);
|
|
399
|
+
if (firstRun === void 0) return;
|
|
400
|
+
const secondRun = readRunLength(reader, color !== 1);
|
|
401
|
+
if (secondRun === void 0) return;
|
|
402
|
+
const a1 = Math.min(columns, start + firstRun);
|
|
403
|
+
const a2 = Math.min(columns, a1 + secondRun);
|
|
404
|
+
transitions.push(a1, a2);
|
|
405
|
+
a0 = a2;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
const a1 = Math.min(columns, Math.max(0, b1 + mode.delta));
|
|
409
|
+
transitions.push(a1);
|
|
410
|
+
a0 = a1;
|
|
411
|
+
color ^= 1;
|
|
412
|
+
}
|
|
413
|
+
return transitions;
|
|
414
|
+
}
|
|
415
|
+
function setBitRun(row, from, to, bit) {
|
|
416
|
+
for (let x = from; x < to; x++) {
|
|
417
|
+
const index = x >> 3;
|
|
418
|
+
const mask = 128 >> (x & 7);
|
|
419
|
+
if (bit === 1) row[index] = (row[index] ?? 0) | mask;
|
|
420
|
+
else row[index] = (row[index] ?? 0) & ~mask;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
function renderRow(transitions, columns, blackBit) {
|
|
424
|
+
const row = new Uint8Array(Math.ceil(columns / 8));
|
|
425
|
+
if (blackBit === 0) row.fill(255);
|
|
426
|
+
let position = 0;
|
|
427
|
+
let black = false;
|
|
428
|
+
for (const transition of transitions) {
|
|
429
|
+
const end = Math.min(transition, columns);
|
|
430
|
+
if (black && end > position) setBitRun(row, position, end, blackBit);
|
|
431
|
+
position = Math.max(position, end);
|
|
432
|
+
black = !black;
|
|
433
|
+
}
|
|
434
|
+
return row;
|
|
435
|
+
}
|
|
436
|
+
const DEFAULT_COLUMNS = 1728;
|
|
437
|
+
function decodeCcittFax(data, options = {}) {
|
|
438
|
+
const columns = options.columns ?? DEFAULT_COLUMNS;
|
|
439
|
+
const requestedRows = options.rows ?? 0;
|
|
440
|
+
const k = options.k ?? 0;
|
|
441
|
+
const blackBit = options.blackIs1 === true ? 1 : 0;
|
|
442
|
+
const encodedByteAlign = options.encodedByteAlign === true;
|
|
443
|
+
const warn = options.onWarning;
|
|
444
|
+
if (columns <= 0) return {
|
|
445
|
+
bytes: /* @__PURE__ */ new Uint8Array(0),
|
|
446
|
+
columns: 0,
|
|
447
|
+
rows: 0
|
|
448
|
+
};
|
|
449
|
+
const reader = new CcittBitReader(data);
|
|
450
|
+
const rows = [];
|
|
451
|
+
let reference = [];
|
|
452
|
+
let nextRowIs1d = k >= 0;
|
|
453
|
+
while (requestedRows === 0 || rows.length < requestedRows) {
|
|
454
|
+
if (encodedByteAlign) reader.alignToByte();
|
|
455
|
+
if (tryReadEol(reader)) {
|
|
456
|
+
if (k > 0) {
|
|
457
|
+
const tag = reader.readBit();
|
|
458
|
+
if (tag < 0) break;
|
|
459
|
+
nextRowIs1d = tag === 1;
|
|
460
|
+
}
|
|
461
|
+
if (tryReadEol(reader)) break;
|
|
462
|
+
}
|
|
463
|
+
if (reader.atZeroPadding) break;
|
|
464
|
+
const transitions = nextRowIs1d ? decode1dRow(reader, columns) : decode2dRow(reader, reference, columns);
|
|
465
|
+
if (transitions === void 0) {
|
|
466
|
+
if (warn !== void 0) warn(`CCITT fax data became undecodable at row ${String(rows.length)}; keeping the ${String(rows.length)} row(s) recovered so far`);
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
rows.push(renderRow(transitions, columns, blackBit));
|
|
470
|
+
reference = transitions;
|
|
471
|
+
}
|
|
472
|
+
if (requestedRows > 0 && rows.length < requestedRows) {
|
|
473
|
+
if (warn !== void 0 && rows.length > 0) warn(`CCITT fax data ended after ${String(rows.length)} of ${String(requestedRows)} declared rows; padding the remainder white`);
|
|
474
|
+
const bytesPerRow = Math.ceil(columns / 8);
|
|
475
|
+
while (rows.length < requestedRows) {
|
|
476
|
+
const blank = new Uint8Array(bytesPerRow);
|
|
477
|
+
if (blackBit === 0) blank.fill(255);
|
|
478
|
+
rows.push(blank);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return {
|
|
482
|
+
bytes: require_bytes_writer.concatBytes(rows),
|
|
483
|
+
columns,
|
|
484
|
+
rows: rows.length
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
//#endregion
|
|
488
|
+
exports.decodeCcittFax = decodeCcittFax;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/image/ccitt.d.ts
|
|
2
|
+
interface CcittFaxOptions {
|
|
3
|
+
readonly k?: number;
|
|
4
|
+
readonly columns?: number;
|
|
5
|
+
readonly rows?: number;
|
|
6
|
+
readonly blackIs1?: boolean;
|
|
7
|
+
readonly encodedByteAlign?: boolean;
|
|
8
|
+
readonly onWarning?: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
interface CcittFaxImage {
|
|
11
|
+
readonly bytes: Uint8Array<ArrayBuffer>;
|
|
12
|
+
readonly columns: number;
|
|
13
|
+
readonly rows: number;
|
|
14
|
+
}
|
|
15
|
+
declare function decodeCcittFax(data: Uint8Array<ArrayBuffer>, options?: CcittFaxOptions): CcittFaxImage;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CcittFaxImage, CcittFaxOptions, decodeCcittFax };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/image/ccitt.d.ts
|
|
2
|
+
interface CcittFaxOptions {
|
|
3
|
+
readonly k?: number;
|
|
4
|
+
readonly columns?: number;
|
|
5
|
+
readonly rows?: number;
|
|
6
|
+
readonly blackIs1?: boolean;
|
|
7
|
+
readonly encodedByteAlign?: boolean;
|
|
8
|
+
readonly onWarning?: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
interface CcittFaxImage {
|
|
11
|
+
readonly bytes: Uint8Array<ArrayBuffer>;
|
|
12
|
+
readonly columns: number;
|
|
13
|
+
readonly rows: number;
|
|
14
|
+
}
|
|
15
|
+
declare function decodeCcittFax(data: Uint8Array<ArrayBuffer>, options?: CcittFaxOptions): CcittFaxImage;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { CcittFaxImage, CcittFaxOptions, decodeCcittFax };
|