@file-viewer/core 2.0.11 → 2.1.1
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.en.md +2 -2
- package/README.md +2 -2
- package/dist/config/options.d.ts +1 -1
- package/dist/config/options.js +1 -1
- package/dist/contracts/types.d.ts +76 -1
- package/dist/headless.d.ts +3 -3
- package/dist/headless.js +2 -2
- package/dist/index.d.ts +10 -7
- package/dist/index.js +106 -49
- package/dist/lifecycle/operations.d.ts +1 -0
- package/dist/lifecycle/operations.js +65 -6
- package/dist/platform/assets.d.ts +3 -1
- package/dist/platform/assets.js +43 -6
- package/dist/registry/capabilities.d.ts +2 -2
- package/dist/registry/capabilities.js +2 -1
- package/dist/registry/formats.d.ts +20 -7
- package/dist/registry/formats.js +14 -5
- package/dist/registry/registry.d.ts +8 -1
- package/dist/registry/registry.js +29 -0
- package/dist/renderers/image.js +1 -10
- package/dist/renderers/index.d.ts +320 -2
- package/dist/renderers/index.js +27 -157
- package/dist/viewer/createViewer.js +86 -3
- package/package.json +17 -44
- package/dist/renderers/archive.d.ts +0 -2
- package/dist/renderers/archive.js +0 -547
- package/dist/renderers/archiveCache.d.ts +0 -10
- package/dist/renderers/archiveCache.js +0 -96
- package/dist/renderers/archiveFallback.d.ts +0 -7
- package/dist/renderers/archiveFallback.js +0 -166
- package/dist/renderers/archiveShared.d.ts +0 -23
- package/dist/renderers/archiveShared.js +0 -71
- package/dist/renderers/audio.d.ts +0 -8
- package/dist/renderers/audio.js +0 -219
- package/dist/renderers/cad.d.ts +0 -2
- package/dist/renderers/cad.js +0 -446
- package/dist/renderers/code.d.ts +0 -11
- package/dist/renderers/code.js +0 -233
- package/dist/renderers/data.d.ts +0 -7
- package/dist/renderers/data.js +0 -370
- package/dist/renderers/drawing.d.ts +0 -10
- package/dist/renderers/drawing.js +0 -882
- package/dist/renderers/eda.d.ts +0 -2
- package/dist/renderers/eda.js +0 -434
- package/dist/renderers/edaParser.d.ts +0 -77
- package/dist/renderers/edaParser.js +0 -569
- package/dist/renderers/email.d.ts +0 -2
- package/dist/renderers/email.js +0 -463
- package/dist/renderers/epub.d.ts +0 -2
- package/dist/renderers/epub.js +0 -331
- package/dist/renderers/geo.d.ts +0 -2
- package/dist/renderers/geo.js +0 -284
- package/dist/renderers/markdown.d.ts +0 -2
- package/dist/renderers/markdown.js +0 -83
- package/dist/renderers/model.d.ts +0 -2
- package/dist/renderers/model.js +0 -567
- package/dist/renderers/ofd.d.ts +0 -2
- package/dist/renderers/ofd.js +0 -256
- package/dist/renderers/openDocument.d.ts +0 -2
- package/dist/renderers/openDocument.js +0 -122
- package/dist/renderers/pdf.d.ts +0 -3
- package/dist/renderers/pdf.js +0 -1001
- package/dist/renderers/pdfStyles.d.ts +0 -1
- package/dist/renderers/pdfStyles.js +0 -1
- package/dist/renderers/pptx.d.ts +0 -2
- package/dist/renderers/pptx.js +0 -217
- package/dist/renderers/spreadsheet/state.d.ts +0 -80
- package/dist/renderers/spreadsheet/state.js +0 -96
- package/dist/renderers/spreadsheet/view.d.ts +0 -25
- package/dist/renderers/spreadsheet/view.js +0 -833
- package/dist/renderers/spreadsheet/worker/index.d.ts +0 -2
- package/dist/renderers/spreadsheet/worker/index.js +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.d.ts +0 -73
- package/dist/renderers/spreadsheet/worker/sheetjs/SheetJsModel.js +0 -623
- package/dist/renderers/spreadsheet/worker/sheetjs/color.d.ts +0 -2
- package/dist/renderers/spreadsheet/worker/sheetjs/color.js +0 -73
- package/dist/renderers/spreadsheet/worker/sheetjs/index.d.ts +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/index.js +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/parser.d.ts +0 -18
- package/dist/renderers/spreadsheet/worker/sheetjs/parser.js +0 -106
- package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.d.ts +0 -1
- package/dist/renderers/spreadsheet/worker/sheetjs/sheet.worker.js +0 -11
- package/dist/renderers/spreadsheet/worker/type.d.ts +0 -57
- package/dist/renderers/spreadsheet/worker/type.js +0 -1
- package/dist/renderers/spreadsheet.d.ts +0 -3
- package/dist/renderers/spreadsheet.js +0 -929
- package/dist/renderers/typst.d.ts +0 -8
- package/dist/renderers/typst.js +0 -547
- package/dist/renderers/umd/parser.d.ts +0 -30
- package/dist/renderers/umd/parser.js +0 -408
- package/dist/renderers/umd.d.ts +0 -2
- package/dist/renderers/umd.js +0 -297
- package/dist/renderers/video.d.ts +0 -8
- package/dist/renderers/video.js +0 -108
- package/dist/renderers/wordDoc.d.ts +0 -5
- package/dist/renderers/wordDoc.js +0 -284
- package/dist/renderers/wordDocx.d.ts +0 -5
- package/dist/renderers/wordDocx.js +0 -985
- package/dist/renderers/wordDocx.worker.d.ts +0 -1
- package/dist/renderers/wordDocx.worker.js +0 -96
- package/vendor/ofd/dltech/jbig2/arithmetic_decoder.js +0 -183
- package/vendor/ofd/dltech/jbig2/ccitt.js +0 -1070
- package/vendor/ofd/dltech/jbig2/compatibility.js +0 -12
- package/vendor/ofd/dltech/jbig2/core_utils.js +0 -180
- package/vendor/ofd/dltech/jbig2/is_node.js +0 -27
- package/vendor/ofd/dltech/jbig2/jbig2.js +0 -2589
- package/vendor/ofd/dltech/jbig2/jbig2_stream.js +0 -81
- package/vendor/ofd/dltech/jbig2/primitives.js +0 -387
- package/vendor/ofd/dltech/jbig2/stream.js +0 -1348
- package/vendor/ofd/dltech/jbig2/util.js +0 -972
- package/vendor/ofd/dltech/ofd/ofd.d.ts +0 -11
- package/vendor/ofd/dltech/ofd/ofd.js +0 -100
- package/vendor/ofd/dltech/ofd/ofd_parser.js +0 -395
- package/vendor/ofd/dltech/ofd/ofd_render.js +0 -473
- package/vendor/ofd/dltech/ofd/ofd_util.js +0 -350
- package/vendor/ofd/dltech/ofd/pipeline.js +0 -26
|
@@ -1,2589 +0,0 @@
|
|
|
1
|
-
/* Copyright 2012 Mozilla Foundation
|
|
2
|
-
*
|
|
3
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
* you may not use this file except in compliance with the License.
|
|
5
|
-
* You may obtain a copy of the License at
|
|
6
|
-
*
|
|
7
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
*
|
|
9
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
* See the License for the specific language governing permissions and
|
|
13
|
-
* limitations under the License.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { BaseException, shadow } from "./util.js";
|
|
17
|
-
import { log2, readInt8, readUint16, readUint32 } from "./core_utils.js";
|
|
18
|
-
import { ArithmeticDecoder } from "./arithmetic_decoder.js";
|
|
19
|
-
import { CCITTFaxDecoder } from "./ccitt.js";
|
|
20
|
-
|
|
21
|
-
class Jbig2Error extends BaseException {
|
|
22
|
-
constructor(msg) {
|
|
23
|
-
super(`JBIG2 error: ${msg}`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
var Jbig2Image = (function Jbig2ImageClosure() {
|
|
28
|
-
// Utility data structures
|
|
29
|
-
function ContextCache() {}
|
|
30
|
-
|
|
31
|
-
ContextCache.prototype = {
|
|
32
|
-
getContexts(id) {
|
|
33
|
-
if (id in this) {
|
|
34
|
-
return this[id];
|
|
35
|
-
}
|
|
36
|
-
return (this[id] = new Int8Array(1 << 16));
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
function DecodingContext(data, start, end) {
|
|
41
|
-
this.data = data;
|
|
42
|
-
this.start = start;
|
|
43
|
-
this.end = end;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
DecodingContext.prototype = {
|
|
47
|
-
get decoder() {
|
|
48
|
-
var decoder = new ArithmeticDecoder(this.data, this.start, this.end);
|
|
49
|
-
return shadow(this, "decoder", decoder);
|
|
50
|
-
},
|
|
51
|
-
get contextCache() {
|
|
52
|
-
var cache = new ContextCache();
|
|
53
|
-
return shadow(this, "contextCache", cache);
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Annex A. Arithmetic Integer Decoding Procedure
|
|
58
|
-
// A.2 Procedure for decoding values
|
|
59
|
-
function decodeInteger(contextCache, procedure, decoder) {
|
|
60
|
-
var contexts = contextCache.getContexts(procedure);
|
|
61
|
-
var prev = 1;
|
|
62
|
-
|
|
63
|
-
function readBits(length) {
|
|
64
|
-
var v = 0;
|
|
65
|
-
for (var i = 0; i < length; i++) {
|
|
66
|
-
var bit = decoder.readBit(contexts, prev);
|
|
67
|
-
prev =
|
|
68
|
-
prev < 256 ? (prev << 1) | bit : (((prev << 1) | bit) & 511) | 256;
|
|
69
|
-
v = (v << 1) | bit;
|
|
70
|
-
}
|
|
71
|
-
return v >>> 0;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
var sign = readBits(1);
|
|
75
|
-
// prettier-ignore
|
|
76
|
-
/* eslint-disable no-nested-ternary */
|
|
77
|
-
var value = readBits(1) ?
|
|
78
|
-
(readBits(1) ?
|
|
79
|
-
(readBits(1) ?
|
|
80
|
-
(readBits(1) ?
|
|
81
|
-
(readBits(1) ?
|
|
82
|
-
(readBits(32) + 4436) :
|
|
83
|
-
readBits(12) + 340) :
|
|
84
|
-
readBits(8) + 84) :
|
|
85
|
-
readBits(6) + 20) :
|
|
86
|
-
readBits(4) + 4) :
|
|
87
|
-
readBits(2);
|
|
88
|
-
/* eslint-enable no-nested-ternary */
|
|
89
|
-
if (sign === 0) {
|
|
90
|
-
return value;
|
|
91
|
-
} else if (value > 0) {
|
|
92
|
-
return -value;
|
|
93
|
-
}
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// A.3 The IAID decoding procedure
|
|
98
|
-
function decodeIAID(contextCache, decoder, codeLength) {
|
|
99
|
-
var contexts = contextCache.getContexts("IAID");
|
|
100
|
-
|
|
101
|
-
var prev = 1;
|
|
102
|
-
for (var i = 0; i < codeLength; i++) {
|
|
103
|
-
var bit = decoder.readBit(contexts, prev);
|
|
104
|
-
prev = (prev << 1) | bit;
|
|
105
|
-
}
|
|
106
|
-
if (codeLength < 31) {
|
|
107
|
-
return prev & ((1 << codeLength) - 1);
|
|
108
|
-
}
|
|
109
|
-
return prev & 0x7fffffff;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// 7.3 Segment types
|
|
113
|
-
var SegmentTypes = [
|
|
114
|
-
"SymbolDictionary",
|
|
115
|
-
null,
|
|
116
|
-
null,
|
|
117
|
-
null,
|
|
118
|
-
"IntermediateTextRegion",
|
|
119
|
-
null,
|
|
120
|
-
"ImmediateTextRegion",
|
|
121
|
-
"ImmediateLosslessTextRegion",
|
|
122
|
-
null,
|
|
123
|
-
null,
|
|
124
|
-
null,
|
|
125
|
-
null,
|
|
126
|
-
null,
|
|
127
|
-
null,
|
|
128
|
-
null,
|
|
129
|
-
null,
|
|
130
|
-
"PatternDictionary",
|
|
131
|
-
null,
|
|
132
|
-
null,
|
|
133
|
-
null,
|
|
134
|
-
"IntermediateHalftoneRegion",
|
|
135
|
-
null,
|
|
136
|
-
"ImmediateHalftoneRegion",
|
|
137
|
-
"ImmediateLosslessHalftoneRegion",
|
|
138
|
-
null,
|
|
139
|
-
null,
|
|
140
|
-
null,
|
|
141
|
-
null,
|
|
142
|
-
null,
|
|
143
|
-
null,
|
|
144
|
-
null,
|
|
145
|
-
null,
|
|
146
|
-
null,
|
|
147
|
-
null,
|
|
148
|
-
null,
|
|
149
|
-
null,
|
|
150
|
-
"IntermediateGenericRegion",
|
|
151
|
-
null,
|
|
152
|
-
"ImmediateGenericRegion",
|
|
153
|
-
"ImmediateLosslessGenericRegion",
|
|
154
|
-
"IntermediateGenericRefinementRegion",
|
|
155
|
-
null,
|
|
156
|
-
"ImmediateGenericRefinementRegion",
|
|
157
|
-
"ImmediateLosslessGenericRefinementRegion",
|
|
158
|
-
null,
|
|
159
|
-
null,
|
|
160
|
-
null,
|
|
161
|
-
null,
|
|
162
|
-
"PageInformation",
|
|
163
|
-
"EndOfPage",
|
|
164
|
-
"EndOfStripe",
|
|
165
|
-
"EndOfFile",
|
|
166
|
-
"Profiles",
|
|
167
|
-
"Tables",
|
|
168
|
-
null,
|
|
169
|
-
null,
|
|
170
|
-
null,
|
|
171
|
-
null,
|
|
172
|
-
null,
|
|
173
|
-
null,
|
|
174
|
-
null,
|
|
175
|
-
null,
|
|
176
|
-
"Extension",
|
|
177
|
-
];
|
|
178
|
-
|
|
179
|
-
var CodingTemplates = [
|
|
180
|
-
[
|
|
181
|
-
{ x: -1, y: -2 },
|
|
182
|
-
{ x: 0, y: -2 },
|
|
183
|
-
{ x: 1, y: -2 },
|
|
184
|
-
{ x: -2, y: -1 },
|
|
185
|
-
{ x: -1, y: -1 },
|
|
186
|
-
{ x: 0, y: -1 },
|
|
187
|
-
{ x: 1, y: -1 },
|
|
188
|
-
{ x: 2, y: -1 },
|
|
189
|
-
{ x: -4, y: 0 },
|
|
190
|
-
{ x: -3, y: 0 },
|
|
191
|
-
{ x: -2, y: 0 },
|
|
192
|
-
{ x: -1, y: 0 },
|
|
193
|
-
],
|
|
194
|
-
[
|
|
195
|
-
{ x: -1, y: -2 },
|
|
196
|
-
{ x: 0, y: -2 },
|
|
197
|
-
{ x: 1, y: -2 },
|
|
198
|
-
{ x: 2, y: -2 },
|
|
199
|
-
{ x: -2, y: -1 },
|
|
200
|
-
{ x: -1, y: -1 },
|
|
201
|
-
{ x: 0, y: -1 },
|
|
202
|
-
{ x: 1, y: -1 },
|
|
203
|
-
{ x: 2, y: -1 },
|
|
204
|
-
{ x: -3, y: 0 },
|
|
205
|
-
{ x: -2, y: 0 },
|
|
206
|
-
{ x: -1, y: 0 },
|
|
207
|
-
],
|
|
208
|
-
[
|
|
209
|
-
{ x: -1, y: -2 },
|
|
210
|
-
{ x: 0, y: -2 },
|
|
211
|
-
{ x: 1, y: -2 },
|
|
212
|
-
{ x: -2, y: -1 },
|
|
213
|
-
{ x: -1, y: -1 },
|
|
214
|
-
{ x: 0, y: -1 },
|
|
215
|
-
{ x: 1, y: -1 },
|
|
216
|
-
{ x: -2, y: 0 },
|
|
217
|
-
{ x: -1, y: 0 },
|
|
218
|
-
],
|
|
219
|
-
[
|
|
220
|
-
{ x: -3, y: -1 },
|
|
221
|
-
{ x: -2, y: -1 },
|
|
222
|
-
{ x: -1, y: -1 },
|
|
223
|
-
{ x: 0, y: -1 },
|
|
224
|
-
{ x: 1, y: -1 },
|
|
225
|
-
{ x: -4, y: 0 },
|
|
226
|
-
{ x: -3, y: 0 },
|
|
227
|
-
{ x: -2, y: 0 },
|
|
228
|
-
{ x: -1, y: 0 },
|
|
229
|
-
],
|
|
230
|
-
];
|
|
231
|
-
|
|
232
|
-
var RefinementTemplates = [
|
|
233
|
-
{
|
|
234
|
-
coding: [
|
|
235
|
-
{ x: 0, y: -1 },
|
|
236
|
-
{ x: 1, y: -1 },
|
|
237
|
-
{ x: -1, y: 0 },
|
|
238
|
-
],
|
|
239
|
-
reference: [
|
|
240
|
-
{ x: 0, y: -1 },
|
|
241
|
-
{ x: 1, y: -1 },
|
|
242
|
-
{ x: -1, y: 0 },
|
|
243
|
-
{ x: 0, y: 0 },
|
|
244
|
-
{ x: 1, y: 0 },
|
|
245
|
-
{ x: -1, y: 1 },
|
|
246
|
-
{ x: 0, y: 1 },
|
|
247
|
-
{ x: 1, y: 1 },
|
|
248
|
-
],
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
coding: [
|
|
252
|
-
{ x: -1, y: -1 },
|
|
253
|
-
{ x: 0, y: -1 },
|
|
254
|
-
{ x: 1, y: -1 },
|
|
255
|
-
{ x: -1, y: 0 },
|
|
256
|
-
],
|
|
257
|
-
reference: [
|
|
258
|
-
{ x: 0, y: -1 },
|
|
259
|
-
{ x: -1, y: 0 },
|
|
260
|
-
{ x: 0, y: 0 },
|
|
261
|
-
{ x: 1, y: 0 },
|
|
262
|
-
{ x: 0, y: 1 },
|
|
263
|
-
{ x: 1, y: 1 },
|
|
264
|
-
],
|
|
265
|
-
},
|
|
266
|
-
];
|
|
267
|
-
|
|
268
|
-
// See 6.2.5.7 Decoding the bitmap.
|
|
269
|
-
var ReusedContexts = [
|
|
270
|
-
0x9b25, // 10011 0110010 0101
|
|
271
|
-
0x0795, // 0011 110010 101
|
|
272
|
-
0x00e5, // 001 11001 01
|
|
273
|
-
0x0195, // 011001 0101
|
|
274
|
-
];
|
|
275
|
-
|
|
276
|
-
var RefinementReusedContexts = [
|
|
277
|
-
0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference)
|
|
278
|
-
0x0008, // '0000' + '001000'
|
|
279
|
-
];
|
|
280
|
-
|
|
281
|
-
function decodeBitmapTemplate0(width, height, decodingContext) {
|
|
282
|
-
var decoder = decodingContext.decoder;
|
|
283
|
-
var contexts = decodingContext.contextCache.getContexts("GB");
|
|
284
|
-
var contextLabel,
|
|
285
|
-
i,
|
|
286
|
-
j,
|
|
287
|
-
pixel,
|
|
288
|
-
row,
|
|
289
|
-
row1,
|
|
290
|
-
row2,
|
|
291
|
-
bitmap = [];
|
|
292
|
-
|
|
293
|
-
// ...ooooo....
|
|
294
|
-
// ..ooooooo... Context template for current pixel (X)
|
|
295
|
-
// .ooooX...... (concatenate values of 'o'-pixels to get contextLabel)
|
|
296
|
-
var OLD_PIXEL_MASK = 0x7bf7; // 01111 0111111 0111
|
|
297
|
-
|
|
298
|
-
for (i = 0; i < height; i++) {
|
|
299
|
-
row = bitmap[i] = new Uint8Array(width);
|
|
300
|
-
row1 = i < 1 ? row : bitmap[i - 1];
|
|
301
|
-
row2 = i < 2 ? row : bitmap[i - 2];
|
|
302
|
-
|
|
303
|
-
// At the beginning of each row:
|
|
304
|
-
// Fill contextLabel with pixels that are above/right of (X)
|
|
305
|
-
contextLabel =
|
|
306
|
-
(row2[0] << 13) |
|
|
307
|
-
(row2[1] << 12) |
|
|
308
|
-
(row2[2] << 11) |
|
|
309
|
-
(row1[0] << 7) |
|
|
310
|
-
(row1[1] << 6) |
|
|
311
|
-
(row1[2] << 5) |
|
|
312
|
-
(row1[3] << 4);
|
|
313
|
-
|
|
314
|
-
for (j = 0; j < width; j++) {
|
|
315
|
-
row[j] = pixel = decoder.readBit(contexts, contextLabel);
|
|
316
|
-
|
|
317
|
-
// At each pixel: Clear contextLabel pixels that are shifted
|
|
318
|
-
// out of the context, then add new ones.
|
|
319
|
-
contextLabel =
|
|
320
|
-
((contextLabel & OLD_PIXEL_MASK) << 1) |
|
|
321
|
-
(j + 3 < width ? row2[j + 3] << 11 : 0) |
|
|
322
|
-
(j + 4 < width ? row1[j + 4] << 4 : 0) |
|
|
323
|
-
pixel;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return bitmap;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// 6.2 Generic Region Decoding Procedure
|
|
331
|
-
function decodeBitmap(
|
|
332
|
-
mmr,
|
|
333
|
-
width,
|
|
334
|
-
height,
|
|
335
|
-
templateIndex,
|
|
336
|
-
prediction,
|
|
337
|
-
skip,
|
|
338
|
-
at,
|
|
339
|
-
decodingContext
|
|
340
|
-
) {
|
|
341
|
-
if (mmr) {
|
|
342
|
-
const input = new Reader(
|
|
343
|
-
decodingContext.data,
|
|
344
|
-
decodingContext.start,
|
|
345
|
-
decodingContext.end
|
|
346
|
-
);
|
|
347
|
-
return decodeMMRBitmap(input, width, height, false);
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
// Use optimized version for the most common case
|
|
351
|
-
if (
|
|
352
|
-
templateIndex === 0 &&
|
|
353
|
-
!skip &&
|
|
354
|
-
!prediction &&
|
|
355
|
-
at.length === 4 &&
|
|
356
|
-
at[0].x === 3 &&
|
|
357
|
-
at[0].y === -1 &&
|
|
358
|
-
at[1].x === -3 &&
|
|
359
|
-
at[1].y === -1 &&
|
|
360
|
-
at[2].x === 2 &&
|
|
361
|
-
at[2].y === -2 &&
|
|
362
|
-
at[3].x === -2 &&
|
|
363
|
-
at[3].y === -2
|
|
364
|
-
) {
|
|
365
|
-
return decodeBitmapTemplate0(width, height, decodingContext);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
var useskip = !!skip;
|
|
369
|
-
var template = CodingTemplates[templateIndex].concat(at);
|
|
370
|
-
|
|
371
|
-
// Sorting is non-standard, and it is not required. But sorting increases
|
|
372
|
-
// the number of template bits that can be reused from the previous
|
|
373
|
-
// contextLabel in the main loop.
|
|
374
|
-
template.sort(function (a, b) {
|
|
375
|
-
return a.y - b.y || a.x - b.x;
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
var templateLength = template.length;
|
|
379
|
-
var templateX = new Int8Array(templateLength);
|
|
380
|
-
var templateY = new Int8Array(templateLength);
|
|
381
|
-
var changingTemplateEntries = [];
|
|
382
|
-
var reuseMask = 0,
|
|
383
|
-
minX = 0,
|
|
384
|
-
maxX = 0,
|
|
385
|
-
minY = 0;
|
|
386
|
-
var c, k;
|
|
387
|
-
|
|
388
|
-
for (k = 0; k < templateLength; k++) {
|
|
389
|
-
templateX[k] = template[k].x;
|
|
390
|
-
templateY[k] = template[k].y;
|
|
391
|
-
minX = Math.min(minX, template[k].x);
|
|
392
|
-
maxX = Math.max(maxX, template[k].x);
|
|
393
|
-
minY = Math.min(minY, template[k].y);
|
|
394
|
-
// Check if the template pixel appears in two consecutive context labels,
|
|
395
|
-
// so it can be reused. Otherwise, we add it to the list of changing
|
|
396
|
-
// template entries.
|
|
397
|
-
if (
|
|
398
|
-
k < templateLength - 1 &&
|
|
399
|
-
template[k].y === template[k + 1].y &&
|
|
400
|
-
template[k].x === template[k + 1].x - 1
|
|
401
|
-
) {
|
|
402
|
-
reuseMask |= 1 << (templateLength - 1 - k);
|
|
403
|
-
} else {
|
|
404
|
-
changingTemplateEntries.push(k);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
var changingEntriesLength = changingTemplateEntries.length;
|
|
408
|
-
|
|
409
|
-
var changingTemplateX = new Int8Array(changingEntriesLength);
|
|
410
|
-
var changingTemplateY = new Int8Array(changingEntriesLength);
|
|
411
|
-
var changingTemplateBit = new Uint16Array(changingEntriesLength);
|
|
412
|
-
for (c = 0; c < changingEntriesLength; c++) {
|
|
413
|
-
k = changingTemplateEntries[c];
|
|
414
|
-
changingTemplateX[c] = template[k].x;
|
|
415
|
-
changingTemplateY[c] = template[k].y;
|
|
416
|
-
changingTemplateBit[c] = 1 << (templateLength - 1 - k);
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Get the safe bounding box edges from the width, height, minX, maxX, minY
|
|
420
|
-
var sbb_left = -minX;
|
|
421
|
-
var sbb_top = -minY;
|
|
422
|
-
var sbb_right = width - maxX;
|
|
423
|
-
|
|
424
|
-
var pseudoPixelContext = ReusedContexts[templateIndex];
|
|
425
|
-
var row = new Uint8Array(width);
|
|
426
|
-
var bitmap = [];
|
|
427
|
-
|
|
428
|
-
var decoder = decodingContext.decoder;
|
|
429
|
-
var contexts = decodingContext.contextCache.getContexts("GB");
|
|
430
|
-
|
|
431
|
-
var ltp = 0,
|
|
432
|
-
j,
|
|
433
|
-
i0,
|
|
434
|
-
j0,
|
|
435
|
-
contextLabel = 0,
|
|
436
|
-
bit,
|
|
437
|
-
shift;
|
|
438
|
-
for (var i = 0; i < height; i++) {
|
|
439
|
-
if (prediction) {
|
|
440
|
-
var sltp = decoder.readBit(contexts, pseudoPixelContext);
|
|
441
|
-
ltp ^= sltp;
|
|
442
|
-
if (ltp) {
|
|
443
|
-
bitmap.push(row); // duplicate previous row
|
|
444
|
-
continue;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
row = new Uint8Array(row);
|
|
448
|
-
bitmap.push(row);
|
|
449
|
-
for (j = 0; j < width; j++) {
|
|
450
|
-
if (useskip && skip[i][j]) {
|
|
451
|
-
row[j] = 0;
|
|
452
|
-
continue;
|
|
453
|
-
}
|
|
454
|
-
// Are we in the middle of a scanline, so we can reuse contextLabel
|
|
455
|
-
// bits?
|
|
456
|
-
if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
|
|
457
|
-
// If yes, we can just shift the bits that are reusable and only
|
|
458
|
-
// fetch the remaining ones.
|
|
459
|
-
contextLabel = (contextLabel << 1) & reuseMask;
|
|
460
|
-
for (k = 0; k < changingEntriesLength; k++) {
|
|
461
|
-
i0 = i + changingTemplateY[k];
|
|
462
|
-
j0 = j + changingTemplateX[k];
|
|
463
|
-
bit = bitmap[i0][j0];
|
|
464
|
-
if (bit) {
|
|
465
|
-
bit = changingTemplateBit[k];
|
|
466
|
-
contextLabel |= bit;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
} else {
|
|
470
|
-
// compute the contextLabel from scratch
|
|
471
|
-
contextLabel = 0;
|
|
472
|
-
shift = templateLength - 1;
|
|
473
|
-
for (k = 0; k < templateLength; k++, shift--) {
|
|
474
|
-
j0 = j + templateX[k];
|
|
475
|
-
if (j0 >= 0 && j0 < width) {
|
|
476
|
-
i0 = i + templateY[k];
|
|
477
|
-
if (i0 >= 0) {
|
|
478
|
-
bit = bitmap[i0][j0];
|
|
479
|
-
if (bit) {
|
|
480
|
-
contextLabel |= bit << shift;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
var pixel = decoder.readBit(contexts, contextLabel);
|
|
487
|
-
row[j] = pixel;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
return bitmap;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
// 6.3.2 Generic Refinement Region Decoding Procedure
|
|
494
|
-
function decodeRefinement(
|
|
495
|
-
width,
|
|
496
|
-
height,
|
|
497
|
-
templateIndex,
|
|
498
|
-
referenceBitmap,
|
|
499
|
-
offsetX,
|
|
500
|
-
offsetY,
|
|
501
|
-
prediction,
|
|
502
|
-
at,
|
|
503
|
-
decodingContext
|
|
504
|
-
) {
|
|
505
|
-
var codingTemplate = RefinementTemplates[templateIndex].coding;
|
|
506
|
-
if (templateIndex === 0) {
|
|
507
|
-
codingTemplate = codingTemplate.concat([at[0]]);
|
|
508
|
-
}
|
|
509
|
-
var codingTemplateLength = codingTemplate.length;
|
|
510
|
-
var codingTemplateX = new Int32Array(codingTemplateLength);
|
|
511
|
-
var codingTemplateY = new Int32Array(codingTemplateLength);
|
|
512
|
-
var k;
|
|
513
|
-
for (k = 0; k < codingTemplateLength; k++) {
|
|
514
|
-
codingTemplateX[k] = codingTemplate[k].x;
|
|
515
|
-
codingTemplateY[k] = codingTemplate[k].y;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
var referenceTemplate = RefinementTemplates[templateIndex].reference;
|
|
519
|
-
if (templateIndex === 0) {
|
|
520
|
-
referenceTemplate = referenceTemplate.concat([at[1]]);
|
|
521
|
-
}
|
|
522
|
-
var referenceTemplateLength = referenceTemplate.length;
|
|
523
|
-
var referenceTemplateX = new Int32Array(referenceTemplateLength);
|
|
524
|
-
var referenceTemplateY = new Int32Array(referenceTemplateLength);
|
|
525
|
-
for (k = 0; k < referenceTemplateLength; k++) {
|
|
526
|
-
referenceTemplateX[k] = referenceTemplate[k].x;
|
|
527
|
-
referenceTemplateY[k] = referenceTemplate[k].y;
|
|
528
|
-
}
|
|
529
|
-
var referenceWidth = referenceBitmap[0].length;
|
|
530
|
-
var referenceHeight = referenceBitmap.length;
|
|
531
|
-
|
|
532
|
-
var pseudoPixelContext = RefinementReusedContexts[templateIndex];
|
|
533
|
-
var bitmap = [];
|
|
534
|
-
|
|
535
|
-
var decoder = decodingContext.decoder;
|
|
536
|
-
var contexts = decodingContext.contextCache.getContexts("GR");
|
|
537
|
-
|
|
538
|
-
var ltp = 0;
|
|
539
|
-
for (var i = 0; i < height; i++) {
|
|
540
|
-
if (prediction) {
|
|
541
|
-
var sltp = decoder.readBit(contexts, pseudoPixelContext);
|
|
542
|
-
ltp ^= sltp;
|
|
543
|
-
if (ltp) {
|
|
544
|
-
throw new Jbig2Error("prediction is not supported");
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
var row = new Uint8Array(width);
|
|
548
|
-
bitmap.push(row);
|
|
549
|
-
for (var j = 0; j < width; j++) {
|
|
550
|
-
var i0, j0;
|
|
551
|
-
var contextLabel = 0;
|
|
552
|
-
for (k = 0; k < codingTemplateLength; k++) {
|
|
553
|
-
i0 = i + codingTemplateY[k];
|
|
554
|
-
j0 = j + codingTemplateX[k];
|
|
555
|
-
if (i0 < 0 || j0 < 0 || j0 >= width) {
|
|
556
|
-
contextLabel <<= 1; // out of bound pixel
|
|
557
|
-
} else {
|
|
558
|
-
contextLabel = (contextLabel << 1) | bitmap[i0][j0];
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
for (k = 0; k < referenceTemplateLength; k++) {
|
|
562
|
-
i0 = i + referenceTemplateY[k] - offsetY;
|
|
563
|
-
j0 = j + referenceTemplateX[k] - offsetX;
|
|
564
|
-
if (
|
|
565
|
-
i0 < 0 ||
|
|
566
|
-
i0 >= referenceHeight ||
|
|
567
|
-
j0 < 0 ||
|
|
568
|
-
j0 >= referenceWidth
|
|
569
|
-
) {
|
|
570
|
-
contextLabel <<= 1; // out of bound pixel
|
|
571
|
-
} else {
|
|
572
|
-
contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
var pixel = decoder.readBit(contexts, contextLabel);
|
|
576
|
-
row[j] = pixel;
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
return bitmap;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
// 6.5.5 Decoding the symbol dictionary
|
|
584
|
-
function decodeSymbolDictionary(
|
|
585
|
-
huffman,
|
|
586
|
-
refinement,
|
|
587
|
-
symbols,
|
|
588
|
-
numberOfNewSymbols,
|
|
589
|
-
numberOfExportedSymbols,
|
|
590
|
-
huffmanTables,
|
|
591
|
-
templateIndex,
|
|
592
|
-
at,
|
|
593
|
-
refinementTemplateIndex,
|
|
594
|
-
refinementAt,
|
|
595
|
-
decodingContext,
|
|
596
|
-
huffmanInput
|
|
597
|
-
) {
|
|
598
|
-
if (huffman && refinement) {
|
|
599
|
-
throw new Jbig2Error("symbol refinement with Huffman is not supported");
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
var newSymbols = [];
|
|
603
|
-
var currentHeight = 0;
|
|
604
|
-
var symbolCodeLength = log2(symbols.length + numberOfNewSymbols);
|
|
605
|
-
|
|
606
|
-
var decoder = decodingContext.decoder;
|
|
607
|
-
var contextCache = decodingContext.contextCache;
|
|
608
|
-
let tableB1, symbolWidths;
|
|
609
|
-
if (huffman) {
|
|
610
|
-
tableB1 = getStandardTable(1); // standard table B.1
|
|
611
|
-
symbolWidths = [];
|
|
612
|
-
symbolCodeLength = Math.max(symbolCodeLength, 1); // 6.5.8.2.3
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
while (newSymbols.length < numberOfNewSymbols) {
|
|
616
|
-
var deltaHeight = huffman
|
|
617
|
-
? huffmanTables.tableDeltaHeight.decode(huffmanInput)
|
|
618
|
-
: decodeInteger(contextCache, "IADH", decoder); // 6.5.6
|
|
619
|
-
currentHeight += deltaHeight;
|
|
620
|
-
let currentWidth = 0,
|
|
621
|
-
totalWidth = 0;
|
|
622
|
-
const firstSymbol = huffman ? symbolWidths.length : 0;
|
|
623
|
-
while (true) {
|
|
624
|
-
var deltaWidth = huffman
|
|
625
|
-
? huffmanTables.tableDeltaWidth.decode(huffmanInput)
|
|
626
|
-
: decodeInteger(contextCache, "IADW", decoder); // 6.5.7
|
|
627
|
-
if (deltaWidth === null) {
|
|
628
|
-
break; // OOB
|
|
629
|
-
}
|
|
630
|
-
currentWidth += deltaWidth;
|
|
631
|
-
totalWidth += currentWidth;
|
|
632
|
-
var bitmap;
|
|
633
|
-
if (refinement) {
|
|
634
|
-
// 6.5.8.2 Refinement/aggregate-coded symbol bitmap
|
|
635
|
-
var numberOfInstances = decodeInteger(contextCache, "IAAI", decoder);
|
|
636
|
-
if (numberOfInstances > 1) {
|
|
637
|
-
bitmap = decodeTextRegion(
|
|
638
|
-
huffman,
|
|
639
|
-
refinement,
|
|
640
|
-
currentWidth,
|
|
641
|
-
currentHeight,
|
|
642
|
-
0,
|
|
643
|
-
numberOfInstances,
|
|
644
|
-
1, // strip size
|
|
645
|
-
symbols.concat(newSymbols),
|
|
646
|
-
symbolCodeLength,
|
|
647
|
-
0, // transposed
|
|
648
|
-
0, // ds offset
|
|
649
|
-
1, // top left 7.4.3.1.1
|
|
650
|
-
0, // OR operator
|
|
651
|
-
huffmanTables,
|
|
652
|
-
refinementTemplateIndex,
|
|
653
|
-
refinementAt,
|
|
654
|
-
decodingContext,
|
|
655
|
-
0,
|
|
656
|
-
huffmanInput
|
|
657
|
-
);
|
|
658
|
-
} else {
|
|
659
|
-
var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
|
|
660
|
-
var rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
|
|
661
|
-
var rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
|
|
662
|
-
var symbol =
|
|
663
|
-
symbolId < symbols.length
|
|
664
|
-
? symbols[symbolId]
|
|
665
|
-
: newSymbols[symbolId - symbols.length];
|
|
666
|
-
bitmap = decodeRefinement(
|
|
667
|
-
currentWidth,
|
|
668
|
-
currentHeight,
|
|
669
|
-
refinementTemplateIndex,
|
|
670
|
-
symbol,
|
|
671
|
-
rdx,
|
|
672
|
-
rdy,
|
|
673
|
-
false,
|
|
674
|
-
refinementAt,
|
|
675
|
-
decodingContext
|
|
676
|
-
);
|
|
677
|
-
}
|
|
678
|
-
newSymbols.push(bitmap);
|
|
679
|
-
} else if (huffman) {
|
|
680
|
-
// Store only symbol width and decode a collective bitmap when the
|
|
681
|
-
// height class is done.
|
|
682
|
-
symbolWidths.push(currentWidth);
|
|
683
|
-
} else {
|
|
684
|
-
// 6.5.8.1 Direct-coded symbol bitmap
|
|
685
|
-
bitmap = decodeBitmap(
|
|
686
|
-
false,
|
|
687
|
-
currentWidth,
|
|
688
|
-
currentHeight,
|
|
689
|
-
templateIndex,
|
|
690
|
-
false,
|
|
691
|
-
null,
|
|
692
|
-
at,
|
|
693
|
-
decodingContext
|
|
694
|
-
);
|
|
695
|
-
newSymbols.push(bitmap);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
if (huffman && !refinement) {
|
|
699
|
-
// 6.5.9 Height class collective bitmap
|
|
700
|
-
const bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);
|
|
701
|
-
huffmanInput.byteAlign();
|
|
702
|
-
let collectiveBitmap;
|
|
703
|
-
if (bitmapSize === 0) {
|
|
704
|
-
// Uncompressed collective bitmap
|
|
705
|
-
collectiveBitmap = readUncompressedBitmap(
|
|
706
|
-
huffmanInput,
|
|
707
|
-
totalWidth,
|
|
708
|
-
currentHeight
|
|
709
|
-
);
|
|
710
|
-
} else {
|
|
711
|
-
// MMR collective bitmap
|
|
712
|
-
const originalEnd = huffmanInput.end;
|
|
713
|
-
const bitmapEnd = huffmanInput.position + bitmapSize;
|
|
714
|
-
huffmanInput.end = bitmapEnd;
|
|
715
|
-
collectiveBitmap = decodeMMRBitmap(
|
|
716
|
-
huffmanInput,
|
|
717
|
-
totalWidth,
|
|
718
|
-
currentHeight,
|
|
719
|
-
false
|
|
720
|
-
);
|
|
721
|
-
huffmanInput.end = originalEnd;
|
|
722
|
-
huffmanInput.position = bitmapEnd;
|
|
723
|
-
}
|
|
724
|
-
const numberOfSymbolsDecoded = symbolWidths.length;
|
|
725
|
-
if (firstSymbol === numberOfSymbolsDecoded - 1) {
|
|
726
|
-
// collectiveBitmap is a single symbol.
|
|
727
|
-
newSymbols.push(collectiveBitmap);
|
|
728
|
-
} else {
|
|
729
|
-
// Divide collectiveBitmap into symbols.
|
|
730
|
-
let i,
|
|
731
|
-
y,
|
|
732
|
-
xMin = 0,
|
|
733
|
-
xMax,
|
|
734
|
-
bitmapWidth,
|
|
735
|
-
symbolBitmap;
|
|
736
|
-
for (i = firstSymbol; i < numberOfSymbolsDecoded; i++) {
|
|
737
|
-
bitmapWidth = symbolWidths[i];
|
|
738
|
-
xMax = xMin + bitmapWidth;
|
|
739
|
-
symbolBitmap = [];
|
|
740
|
-
for (y = 0; y < currentHeight; y++) {
|
|
741
|
-
symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
|
|
742
|
-
}
|
|
743
|
-
newSymbols.push(symbolBitmap);
|
|
744
|
-
xMin = xMax;
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
// 6.5.10 Exported symbols
|
|
751
|
-
var exportedSymbols = [];
|
|
752
|
-
var flags = [],
|
|
753
|
-
currentFlag = false;
|
|
754
|
-
var totalSymbolsLength = symbols.length + numberOfNewSymbols;
|
|
755
|
-
while (flags.length < totalSymbolsLength) {
|
|
756
|
-
var runLength = huffman
|
|
757
|
-
? tableB1.decode(huffmanInput)
|
|
758
|
-
: decodeInteger(contextCache, "IAEX", decoder);
|
|
759
|
-
while (runLength--) {
|
|
760
|
-
flags.push(currentFlag);
|
|
761
|
-
}
|
|
762
|
-
currentFlag = !currentFlag;
|
|
763
|
-
}
|
|
764
|
-
for (var i = 0, ii = symbols.length; i < ii; i++) {
|
|
765
|
-
if (flags[i]) {
|
|
766
|
-
exportedSymbols.push(symbols[i]);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
for (var j = 0; j < numberOfNewSymbols; i++, j++) {
|
|
770
|
-
if (flags[i]) {
|
|
771
|
-
exportedSymbols.push(newSymbols[j]);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
return exportedSymbols;
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
function decodeTextRegion(
|
|
778
|
-
huffman,
|
|
779
|
-
refinement,
|
|
780
|
-
width,
|
|
781
|
-
height,
|
|
782
|
-
defaultPixelValue,
|
|
783
|
-
numberOfSymbolInstances,
|
|
784
|
-
stripSize,
|
|
785
|
-
inputSymbols,
|
|
786
|
-
symbolCodeLength,
|
|
787
|
-
transposed,
|
|
788
|
-
dsOffset,
|
|
789
|
-
referenceCorner,
|
|
790
|
-
combinationOperator,
|
|
791
|
-
huffmanTables,
|
|
792
|
-
refinementTemplateIndex,
|
|
793
|
-
refinementAt,
|
|
794
|
-
decodingContext,
|
|
795
|
-
logStripSize,
|
|
796
|
-
huffmanInput
|
|
797
|
-
) {
|
|
798
|
-
if (huffman && refinement) {
|
|
799
|
-
throw new Jbig2Error("refinement with Huffman is not supported");
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
// Prepare bitmap
|
|
803
|
-
var bitmap = [];
|
|
804
|
-
var i, row;
|
|
805
|
-
for (i = 0; i < height; i++) {
|
|
806
|
-
row = new Uint8Array(width);
|
|
807
|
-
if (defaultPixelValue) {
|
|
808
|
-
for (var j = 0; j < width; j++) {
|
|
809
|
-
row[j] = defaultPixelValue;
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
bitmap.push(row);
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
var decoder = decodingContext.decoder;
|
|
816
|
-
var contextCache = decodingContext.contextCache;
|
|
817
|
-
|
|
818
|
-
var stripT = huffman
|
|
819
|
-
? -huffmanTables.tableDeltaT.decode(huffmanInput)
|
|
820
|
-
: -decodeInteger(contextCache, "IADT", decoder); // 6.4.6
|
|
821
|
-
var firstS = 0;
|
|
822
|
-
i = 0;
|
|
823
|
-
while (i < numberOfSymbolInstances) {
|
|
824
|
-
var deltaT = huffman
|
|
825
|
-
? huffmanTables.tableDeltaT.decode(huffmanInput)
|
|
826
|
-
: decodeInteger(contextCache, "IADT", decoder); // 6.4.6
|
|
827
|
-
stripT += deltaT;
|
|
828
|
-
|
|
829
|
-
var deltaFirstS = huffman
|
|
830
|
-
? huffmanTables.tableFirstS.decode(huffmanInput)
|
|
831
|
-
: decodeInteger(contextCache, "IAFS", decoder); // 6.4.7
|
|
832
|
-
firstS += deltaFirstS;
|
|
833
|
-
var currentS = firstS;
|
|
834
|
-
do {
|
|
835
|
-
let currentT = 0; // 6.4.9
|
|
836
|
-
if (stripSize > 1) {
|
|
837
|
-
currentT = huffman
|
|
838
|
-
? huffmanInput.readBits(logStripSize)
|
|
839
|
-
: decodeInteger(contextCache, "IAIT", decoder);
|
|
840
|
-
}
|
|
841
|
-
var t = stripSize * stripT + currentT;
|
|
842
|
-
var symbolId = huffman
|
|
843
|
-
? huffmanTables.symbolIDTable.decode(huffmanInput)
|
|
844
|
-
: decodeIAID(contextCache, decoder, symbolCodeLength);
|
|
845
|
-
var applyRefinement =
|
|
846
|
-
refinement &&
|
|
847
|
-
(huffman
|
|
848
|
-
? huffmanInput.readBit()
|
|
849
|
-
: decodeInteger(contextCache, "IARI", decoder));
|
|
850
|
-
var symbolBitmap = inputSymbols[symbolId];
|
|
851
|
-
var symbolWidth = symbolBitmap[0].length;
|
|
852
|
-
var symbolHeight = symbolBitmap.length;
|
|
853
|
-
if (applyRefinement) {
|
|
854
|
-
var rdw = decodeInteger(contextCache, "IARDW", decoder); // 6.4.11.1
|
|
855
|
-
var rdh = decodeInteger(contextCache, "IARDH", decoder); // 6.4.11.2
|
|
856
|
-
var rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
|
|
857
|
-
var rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
|
|
858
|
-
symbolWidth += rdw;
|
|
859
|
-
symbolHeight += rdh;
|
|
860
|
-
symbolBitmap = decodeRefinement(
|
|
861
|
-
symbolWidth,
|
|
862
|
-
symbolHeight,
|
|
863
|
-
refinementTemplateIndex,
|
|
864
|
-
symbolBitmap,
|
|
865
|
-
(rdw >> 1) + rdx,
|
|
866
|
-
(rdh >> 1) + rdy,
|
|
867
|
-
false,
|
|
868
|
-
refinementAt,
|
|
869
|
-
decodingContext
|
|
870
|
-
);
|
|
871
|
-
}
|
|
872
|
-
var offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);
|
|
873
|
-
var offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);
|
|
874
|
-
var s2, t2, symbolRow;
|
|
875
|
-
if (transposed) {
|
|
876
|
-
// Place Symbol Bitmap from T1,S1
|
|
877
|
-
for (s2 = 0; s2 < symbolHeight; s2++) {
|
|
878
|
-
row = bitmap[offsetS + s2];
|
|
879
|
-
if (!row) {
|
|
880
|
-
continue;
|
|
881
|
-
}
|
|
882
|
-
symbolRow = symbolBitmap[s2];
|
|
883
|
-
// To ignore Parts of Symbol bitmap which goes
|
|
884
|
-
// outside bitmap region
|
|
885
|
-
var maxWidth = Math.min(width - offsetT, symbolWidth);
|
|
886
|
-
switch (combinationOperator) {
|
|
887
|
-
case 0: // OR
|
|
888
|
-
for (t2 = 0; t2 < maxWidth; t2++) {
|
|
889
|
-
row[offsetT + t2] |= symbolRow[t2];
|
|
890
|
-
}
|
|
891
|
-
break;
|
|
892
|
-
case 2: // XOR
|
|
893
|
-
for (t2 = 0; t2 < maxWidth; t2++) {
|
|
894
|
-
row[offsetT + t2] ^= symbolRow[t2];
|
|
895
|
-
}
|
|
896
|
-
break;
|
|
897
|
-
default:
|
|
898
|
-
throw new Jbig2Error(
|
|
899
|
-
`operator ${combinationOperator} is not supported`
|
|
900
|
-
);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
currentS += symbolHeight - 1;
|
|
904
|
-
} else {
|
|
905
|
-
for (t2 = 0; t2 < symbolHeight; t2++) {
|
|
906
|
-
row = bitmap[offsetT + t2];
|
|
907
|
-
if (!row) {
|
|
908
|
-
continue;
|
|
909
|
-
}
|
|
910
|
-
symbolRow = symbolBitmap[t2];
|
|
911
|
-
switch (combinationOperator) {
|
|
912
|
-
case 0: // OR
|
|
913
|
-
for (s2 = 0; s2 < symbolWidth; s2++) {
|
|
914
|
-
row[offsetS + s2] |= symbolRow[s2];
|
|
915
|
-
}
|
|
916
|
-
break;
|
|
917
|
-
case 2: // XOR
|
|
918
|
-
for (s2 = 0; s2 < symbolWidth; s2++) {
|
|
919
|
-
row[offsetS + s2] ^= symbolRow[s2];
|
|
920
|
-
}
|
|
921
|
-
break;
|
|
922
|
-
default:
|
|
923
|
-
throw new Jbig2Error(
|
|
924
|
-
`operator ${combinationOperator} is not supported`
|
|
925
|
-
);
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
currentS += symbolWidth - 1;
|
|
929
|
-
}
|
|
930
|
-
i++;
|
|
931
|
-
var deltaS = huffman
|
|
932
|
-
? huffmanTables.tableDeltaS.decode(huffmanInput)
|
|
933
|
-
: decodeInteger(contextCache, "IADS", decoder); // 6.4.8
|
|
934
|
-
if (deltaS === null) {
|
|
935
|
-
break; // OOB
|
|
936
|
-
}
|
|
937
|
-
currentS += deltaS + dsOffset;
|
|
938
|
-
} while (true);
|
|
939
|
-
}
|
|
940
|
-
return bitmap;
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
function decodePatternDictionary(
|
|
944
|
-
mmr,
|
|
945
|
-
patternWidth,
|
|
946
|
-
patternHeight,
|
|
947
|
-
maxPatternIndex,
|
|
948
|
-
template,
|
|
949
|
-
decodingContext
|
|
950
|
-
) {
|
|
951
|
-
const at = [];
|
|
952
|
-
if (!mmr) {
|
|
953
|
-
at.push({
|
|
954
|
-
x: -patternWidth,
|
|
955
|
-
y: 0,
|
|
956
|
-
});
|
|
957
|
-
if (template === 0) {
|
|
958
|
-
at.push({
|
|
959
|
-
x: -3,
|
|
960
|
-
y: -1,
|
|
961
|
-
});
|
|
962
|
-
at.push({
|
|
963
|
-
x: 2,
|
|
964
|
-
y: -2,
|
|
965
|
-
});
|
|
966
|
-
at.push({
|
|
967
|
-
x: -2,
|
|
968
|
-
y: -2,
|
|
969
|
-
});
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
const collectiveWidth = (maxPatternIndex + 1) * patternWidth;
|
|
973
|
-
const collectiveBitmap = decodeBitmap(
|
|
974
|
-
mmr,
|
|
975
|
-
collectiveWidth,
|
|
976
|
-
patternHeight,
|
|
977
|
-
template,
|
|
978
|
-
false,
|
|
979
|
-
null,
|
|
980
|
-
at,
|
|
981
|
-
decodingContext
|
|
982
|
-
);
|
|
983
|
-
// Divide collective bitmap into patterns.
|
|
984
|
-
const patterns = [];
|
|
985
|
-
for (let i = 0; i <= maxPatternIndex; i++) {
|
|
986
|
-
const patternBitmap = [];
|
|
987
|
-
const xMin = patternWidth * i;
|
|
988
|
-
const xMax = xMin + patternWidth;
|
|
989
|
-
for (let y = 0; y < patternHeight; y++) {
|
|
990
|
-
patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
|
|
991
|
-
}
|
|
992
|
-
patterns.push(patternBitmap);
|
|
993
|
-
}
|
|
994
|
-
return patterns;
|
|
995
|
-
}
|
|
996
|
-
|
|
997
|
-
function decodeHalftoneRegion(
|
|
998
|
-
mmr,
|
|
999
|
-
patterns,
|
|
1000
|
-
template,
|
|
1001
|
-
regionWidth,
|
|
1002
|
-
regionHeight,
|
|
1003
|
-
defaultPixelValue,
|
|
1004
|
-
enableSkip,
|
|
1005
|
-
combinationOperator,
|
|
1006
|
-
gridWidth,
|
|
1007
|
-
gridHeight,
|
|
1008
|
-
gridOffsetX,
|
|
1009
|
-
gridOffsetY,
|
|
1010
|
-
gridVectorX,
|
|
1011
|
-
gridVectorY,
|
|
1012
|
-
decodingContext
|
|
1013
|
-
) {
|
|
1014
|
-
const skip = null;
|
|
1015
|
-
if (enableSkip) {
|
|
1016
|
-
throw new Jbig2Error("skip is not supported");
|
|
1017
|
-
}
|
|
1018
|
-
if (combinationOperator !== 0) {
|
|
1019
|
-
throw new Jbig2Error(
|
|
1020
|
-
"operator " +
|
|
1021
|
-
combinationOperator +
|
|
1022
|
-
" is not supported in halftone region"
|
|
1023
|
-
);
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
// Prepare bitmap.
|
|
1027
|
-
const regionBitmap = [];
|
|
1028
|
-
let i, j, row;
|
|
1029
|
-
for (i = 0; i < regionHeight; i++) {
|
|
1030
|
-
row = new Uint8Array(regionWidth);
|
|
1031
|
-
if (defaultPixelValue) {
|
|
1032
|
-
for (j = 0; j < regionWidth; j++) {
|
|
1033
|
-
row[j] = defaultPixelValue;
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
regionBitmap.push(row);
|
|
1037
|
-
}
|
|
1038
|
-
|
|
1039
|
-
const numberOfPatterns = patterns.length;
|
|
1040
|
-
const pattern0 = patterns[0];
|
|
1041
|
-
const patternWidth = pattern0[0].length,
|
|
1042
|
-
patternHeight = pattern0.length;
|
|
1043
|
-
const bitsPerValue = log2(numberOfPatterns);
|
|
1044
|
-
const at = [];
|
|
1045
|
-
if (!mmr) {
|
|
1046
|
-
at.push({
|
|
1047
|
-
x: template <= 1 ? 3 : 2,
|
|
1048
|
-
y: -1,
|
|
1049
|
-
});
|
|
1050
|
-
if (template === 0) {
|
|
1051
|
-
at.push({
|
|
1052
|
-
x: -3,
|
|
1053
|
-
y: -1,
|
|
1054
|
-
});
|
|
1055
|
-
at.push({
|
|
1056
|
-
x: 2,
|
|
1057
|
-
y: -2,
|
|
1058
|
-
});
|
|
1059
|
-
at.push({
|
|
1060
|
-
x: -2,
|
|
1061
|
-
y: -2,
|
|
1062
|
-
});
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
// Annex C. Gray-scale Image Decoding Procedure.
|
|
1066
|
-
const grayScaleBitPlanes = [];
|
|
1067
|
-
let mmrInput, bitmap;
|
|
1068
|
-
if (mmr) {
|
|
1069
|
-
// MMR bit planes are in one continuous stream. Only EOFB codes indicate
|
|
1070
|
-
// the end of each bitmap, so EOFBs must be decoded.
|
|
1071
|
-
mmrInput = new Reader(
|
|
1072
|
-
decodingContext.data,
|
|
1073
|
-
decodingContext.start,
|
|
1074
|
-
decodingContext.end
|
|
1075
|
-
);
|
|
1076
|
-
}
|
|
1077
|
-
for (i = bitsPerValue - 1; i >= 0; i--) {
|
|
1078
|
-
if (mmr) {
|
|
1079
|
-
bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);
|
|
1080
|
-
} else {
|
|
1081
|
-
bitmap = decodeBitmap(
|
|
1082
|
-
false,
|
|
1083
|
-
gridWidth,
|
|
1084
|
-
gridHeight,
|
|
1085
|
-
template,
|
|
1086
|
-
false,
|
|
1087
|
-
skip,
|
|
1088
|
-
at,
|
|
1089
|
-
decodingContext
|
|
1090
|
-
);
|
|
1091
|
-
}
|
|
1092
|
-
grayScaleBitPlanes[i] = bitmap;
|
|
1093
|
-
}
|
|
1094
|
-
// 6.6.5.2 Rendering the patterns.
|
|
1095
|
-
let mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow;
|
|
1096
|
-
for (mg = 0; mg < gridHeight; mg++) {
|
|
1097
|
-
for (ng = 0; ng < gridWidth; ng++) {
|
|
1098
|
-
bit = 0;
|
|
1099
|
-
patternIndex = 0;
|
|
1100
|
-
for (j = bitsPerValue - 1; j >= 0; j--) {
|
|
1101
|
-
bit = grayScaleBitPlanes[j][mg][ng] ^ bit; // Gray decoding
|
|
1102
|
-
patternIndex |= bit << j;
|
|
1103
|
-
}
|
|
1104
|
-
patternBitmap = patterns[patternIndex];
|
|
1105
|
-
x = (gridOffsetX + mg * gridVectorY + ng * gridVectorX) >> 8;
|
|
1106
|
-
y = (gridOffsetY + mg * gridVectorX - ng * gridVectorY) >> 8;
|
|
1107
|
-
// Draw patternBitmap at (x, y).
|
|
1108
|
-
if (
|
|
1109
|
-
x >= 0 &&
|
|
1110
|
-
x + patternWidth <= regionWidth &&
|
|
1111
|
-
y >= 0 &&
|
|
1112
|
-
y + patternHeight <= regionHeight
|
|
1113
|
-
) {
|
|
1114
|
-
for (i = 0; i < patternHeight; i++) {
|
|
1115
|
-
regionRow = regionBitmap[y + i];
|
|
1116
|
-
patternRow = patternBitmap[i];
|
|
1117
|
-
for (j = 0; j < patternWidth; j++) {
|
|
1118
|
-
regionRow[x + j] |= patternRow[j];
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
} else {
|
|
1122
|
-
let regionX, regionY;
|
|
1123
|
-
for (i = 0; i < patternHeight; i++) {
|
|
1124
|
-
regionY = y + i;
|
|
1125
|
-
if (regionY < 0 || regionY >= regionHeight) {
|
|
1126
|
-
continue;
|
|
1127
|
-
}
|
|
1128
|
-
regionRow = regionBitmap[regionY];
|
|
1129
|
-
patternRow = patternBitmap[i];
|
|
1130
|
-
for (j = 0; j < patternWidth; j++) {
|
|
1131
|
-
regionX = x + j;
|
|
1132
|
-
if (regionX >= 0 && regionX < regionWidth) {
|
|
1133
|
-
regionRow[regionX] |= patternRow[j];
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
return regionBitmap;
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
|
-
function readSegmentHeader(data, start) {
|
|
1144
|
-
var segmentHeader = {};
|
|
1145
|
-
segmentHeader.number = readUint32(data, start);
|
|
1146
|
-
var flags = data[start + 4];
|
|
1147
|
-
var segmentType = flags & 0x3f;
|
|
1148
|
-
if (!SegmentTypes[segmentType]) {
|
|
1149
|
-
throw new Jbig2Error("invalid segment type: " + segmentType);
|
|
1150
|
-
}
|
|
1151
|
-
segmentHeader.type = segmentType;
|
|
1152
|
-
segmentHeader.typeName = SegmentTypes[segmentType];
|
|
1153
|
-
segmentHeader.deferredNonRetain = !!(flags & 0x80);
|
|
1154
|
-
|
|
1155
|
-
var pageAssociationFieldSize = !!(flags & 0x40);
|
|
1156
|
-
var referredFlags = data[start + 5];
|
|
1157
|
-
var referredToCount = (referredFlags >> 5) & 7;
|
|
1158
|
-
var retainBits = [referredFlags & 31];
|
|
1159
|
-
var position = start + 6;
|
|
1160
|
-
if (referredFlags === 7) {
|
|
1161
|
-
referredToCount = readUint32(data, position - 1) & 0x1fffffff;
|
|
1162
|
-
position += 3;
|
|
1163
|
-
var bytes = (referredToCount + 7) >> 3;
|
|
1164
|
-
retainBits[0] = data[position++];
|
|
1165
|
-
while (--bytes > 0) {
|
|
1166
|
-
retainBits.push(data[position++]);
|
|
1167
|
-
}
|
|
1168
|
-
} else if (referredFlags === 5 || referredFlags === 6) {
|
|
1169
|
-
throw new Jbig2Error("invalid referred-to flags");
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
segmentHeader.retainBits = retainBits;
|
|
1173
|
-
|
|
1174
|
-
let referredToSegmentNumberSize = 4;
|
|
1175
|
-
if (segmentHeader.number <= 256) {
|
|
1176
|
-
referredToSegmentNumberSize = 1;
|
|
1177
|
-
} else if (segmentHeader.number <= 65536) {
|
|
1178
|
-
referredToSegmentNumberSize = 2;
|
|
1179
|
-
}
|
|
1180
|
-
var referredTo = [];
|
|
1181
|
-
var i, ii;
|
|
1182
|
-
for (i = 0; i < referredToCount; i++) {
|
|
1183
|
-
let number;
|
|
1184
|
-
if (referredToSegmentNumberSize === 1) {
|
|
1185
|
-
number = data[position];
|
|
1186
|
-
} else if (referredToSegmentNumberSize === 2) {
|
|
1187
|
-
number = readUint16(data, position);
|
|
1188
|
-
} else {
|
|
1189
|
-
number = readUint32(data, position);
|
|
1190
|
-
}
|
|
1191
|
-
referredTo.push(number);
|
|
1192
|
-
position += referredToSegmentNumberSize;
|
|
1193
|
-
}
|
|
1194
|
-
segmentHeader.referredTo = referredTo;
|
|
1195
|
-
if (!pageAssociationFieldSize) {
|
|
1196
|
-
segmentHeader.pageAssociation = data[position++];
|
|
1197
|
-
} else {
|
|
1198
|
-
segmentHeader.pageAssociation = readUint32(data, position);
|
|
1199
|
-
position += 4;
|
|
1200
|
-
}
|
|
1201
|
-
segmentHeader.length = readUint32(data, position);
|
|
1202
|
-
position += 4;
|
|
1203
|
-
|
|
1204
|
-
if (segmentHeader.length === 0xffffffff) {
|
|
1205
|
-
// 7.2.7 Segment data length, unknown segment length
|
|
1206
|
-
if (segmentType === 38) {
|
|
1207
|
-
// ImmediateGenericRegion
|
|
1208
|
-
var genericRegionInfo = readRegionSegmentInformation(data, position);
|
|
1209
|
-
var genericRegionSegmentFlags =
|
|
1210
|
-
data[position + RegionSegmentInformationFieldLength];
|
|
1211
|
-
var genericRegionMmr = !!(genericRegionSegmentFlags & 1);
|
|
1212
|
-
// searching for the segment end
|
|
1213
|
-
var searchPatternLength = 6;
|
|
1214
|
-
var searchPattern = new Uint8Array(searchPatternLength);
|
|
1215
|
-
if (!genericRegionMmr) {
|
|
1216
|
-
searchPattern[0] = 0xff;
|
|
1217
|
-
searchPattern[1] = 0xac;
|
|
1218
|
-
}
|
|
1219
|
-
searchPattern[2] = (genericRegionInfo.height >>> 24) & 0xff;
|
|
1220
|
-
searchPattern[3] = (genericRegionInfo.height >> 16) & 0xff;
|
|
1221
|
-
searchPattern[4] = (genericRegionInfo.height >> 8) & 0xff;
|
|
1222
|
-
searchPattern[5] = genericRegionInfo.height & 0xff;
|
|
1223
|
-
for (i = position, ii = data.length; i < ii; i++) {
|
|
1224
|
-
var j = 0;
|
|
1225
|
-
while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
|
|
1226
|
-
j++;
|
|
1227
|
-
}
|
|
1228
|
-
if (j === searchPatternLength) {
|
|
1229
|
-
segmentHeader.length = i + searchPatternLength;
|
|
1230
|
-
break;
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
if (segmentHeader.length === 0xffffffff) {
|
|
1234
|
-
throw new Jbig2Error("segment end was not found");
|
|
1235
|
-
}
|
|
1236
|
-
} else {
|
|
1237
|
-
throw new Jbig2Error("invalid unknown segment length");
|
|
1238
|
-
}
|
|
1239
|
-
}
|
|
1240
|
-
segmentHeader.headerEnd = position;
|
|
1241
|
-
return segmentHeader;
|
|
1242
|
-
}
|
|
1243
|
-
|
|
1244
|
-
function readSegments(header, data, start, end) {
|
|
1245
|
-
var segments = [];
|
|
1246
|
-
var position = start;
|
|
1247
|
-
while (position < end) {
|
|
1248
|
-
var segmentHeader = readSegmentHeader(data, position);
|
|
1249
|
-
position = segmentHeader.headerEnd;
|
|
1250
|
-
var segment = {
|
|
1251
|
-
header: segmentHeader,
|
|
1252
|
-
data,
|
|
1253
|
-
};
|
|
1254
|
-
if (!header.randomAccess) {
|
|
1255
|
-
segment.start = position;
|
|
1256
|
-
position += segmentHeader.length;
|
|
1257
|
-
segment.end = position;
|
|
1258
|
-
}
|
|
1259
|
-
segments.push(segment);
|
|
1260
|
-
if (segmentHeader.type === 51) {
|
|
1261
|
-
break; // end of file is found
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
if (header.randomAccess) {
|
|
1265
|
-
for (var i = 0, ii = segments.length; i < ii; i++) {
|
|
1266
|
-
segments[i].start = position;
|
|
1267
|
-
position += segments[i].header.length;
|
|
1268
|
-
segments[i].end = position;
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
return segments;
|
|
1272
|
-
}
|
|
1273
|
-
|
|
1274
|
-
// 7.4.1 Region segment information field
|
|
1275
|
-
function readRegionSegmentInformation(data, start) {
|
|
1276
|
-
return {
|
|
1277
|
-
width: readUint32(data, start),
|
|
1278
|
-
height: readUint32(data, start + 4),
|
|
1279
|
-
x: readUint32(data, start + 8),
|
|
1280
|
-
y: readUint32(data, start + 12),
|
|
1281
|
-
combinationOperator: data[start + 16] & 7,
|
|
1282
|
-
};
|
|
1283
|
-
}
|
|
1284
|
-
var RegionSegmentInformationFieldLength = 17;
|
|
1285
|
-
|
|
1286
|
-
function processSegment(segment, visitor) {
|
|
1287
|
-
var header = segment.header;
|
|
1288
|
-
|
|
1289
|
-
var data = segment.data,
|
|
1290
|
-
position = segment.start,
|
|
1291
|
-
end = segment.end;
|
|
1292
|
-
var args, at, i, atLength;
|
|
1293
|
-
switch (header.type) {
|
|
1294
|
-
case 0: // SymbolDictionary
|
|
1295
|
-
// 7.4.2 Symbol dictionary segment syntax
|
|
1296
|
-
var dictionary = {};
|
|
1297
|
-
var dictionaryFlags = readUint16(data, position); // 7.4.2.1.1
|
|
1298
|
-
dictionary.huffman = !!(dictionaryFlags & 1);
|
|
1299
|
-
dictionary.refinement = !!(dictionaryFlags & 2);
|
|
1300
|
-
dictionary.huffmanDHSelector = (dictionaryFlags >> 2) & 3;
|
|
1301
|
-
dictionary.huffmanDWSelector = (dictionaryFlags >> 4) & 3;
|
|
1302
|
-
dictionary.bitmapSizeSelector = (dictionaryFlags >> 6) & 1;
|
|
1303
|
-
dictionary.aggregationInstancesSelector = (dictionaryFlags >> 7) & 1;
|
|
1304
|
-
dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
|
|
1305
|
-
dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
|
|
1306
|
-
dictionary.template = (dictionaryFlags >> 10) & 3;
|
|
1307
|
-
dictionary.refinementTemplate = (dictionaryFlags >> 12) & 1;
|
|
1308
|
-
position += 2;
|
|
1309
|
-
if (!dictionary.huffman) {
|
|
1310
|
-
atLength = dictionary.template === 0 ? 4 : 1;
|
|
1311
|
-
at = [];
|
|
1312
|
-
for (i = 0; i < atLength; i++) {
|
|
1313
|
-
at.push({
|
|
1314
|
-
x: readInt8(data, position),
|
|
1315
|
-
y: readInt8(data, position + 1),
|
|
1316
|
-
});
|
|
1317
|
-
position += 2;
|
|
1318
|
-
}
|
|
1319
|
-
dictionary.at = at;
|
|
1320
|
-
}
|
|
1321
|
-
if (dictionary.refinement && !dictionary.refinementTemplate) {
|
|
1322
|
-
at = [];
|
|
1323
|
-
for (i = 0; i < 2; i++) {
|
|
1324
|
-
at.push({
|
|
1325
|
-
x: readInt8(data, position),
|
|
1326
|
-
y: readInt8(data, position + 1),
|
|
1327
|
-
});
|
|
1328
|
-
position += 2;
|
|
1329
|
-
}
|
|
1330
|
-
dictionary.refinementAt = at;
|
|
1331
|
-
}
|
|
1332
|
-
dictionary.numberOfExportedSymbols = readUint32(data, position);
|
|
1333
|
-
position += 4;
|
|
1334
|
-
dictionary.numberOfNewSymbols = readUint32(data, position);
|
|
1335
|
-
position += 4;
|
|
1336
|
-
args = [
|
|
1337
|
-
dictionary,
|
|
1338
|
-
header.number,
|
|
1339
|
-
header.referredTo,
|
|
1340
|
-
data,
|
|
1341
|
-
position,
|
|
1342
|
-
end,
|
|
1343
|
-
];
|
|
1344
|
-
break;
|
|
1345
|
-
case 6: // ImmediateTextRegion
|
|
1346
|
-
case 7: // ImmediateLosslessTextRegion
|
|
1347
|
-
var textRegion = {};
|
|
1348
|
-
textRegion.info = readRegionSegmentInformation(data, position);
|
|
1349
|
-
position += RegionSegmentInformationFieldLength;
|
|
1350
|
-
var textRegionSegmentFlags = readUint16(data, position);
|
|
1351
|
-
position += 2;
|
|
1352
|
-
textRegion.huffman = !!(textRegionSegmentFlags & 1);
|
|
1353
|
-
textRegion.refinement = !!(textRegionSegmentFlags & 2);
|
|
1354
|
-
textRegion.logStripSize = (textRegionSegmentFlags >> 2) & 3;
|
|
1355
|
-
textRegion.stripSize = 1 << textRegion.logStripSize;
|
|
1356
|
-
textRegion.referenceCorner = (textRegionSegmentFlags >> 4) & 3;
|
|
1357
|
-
textRegion.transposed = !!(textRegionSegmentFlags & 64);
|
|
1358
|
-
textRegion.combinationOperator = (textRegionSegmentFlags >> 7) & 3;
|
|
1359
|
-
textRegion.defaultPixelValue = (textRegionSegmentFlags >> 9) & 1;
|
|
1360
|
-
textRegion.dsOffset = (textRegionSegmentFlags << 17) >> 27;
|
|
1361
|
-
textRegion.refinementTemplate = (textRegionSegmentFlags >> 15) & 1;
|
|
1362
|
-
if (textRegion.huffman) {
|
|
1363
|
-
var textRegionHuffmanFlags = readUint16(data, position);
|
|
1364
|
-
position += 2;
|
|
1365
|
-
textRegion.huffmanFS = textRegionHuffmanFlags & 3;
|
|
1366
|
-
textRegion.huffmanDS = (textRegionHuffmanFlags >> 2) & 3;
|
|
1367
|
-
textRegion.huffmanDT = (textRegionHuffmanFlags >> 4) & 3;
|
|
1368
|
-
textRegion.huffmanRefinementDW = (textRegionHuffmanFlags >> 6) & 3;
|
|
1369
|
-
textRegion.huffmanRefinementDH = (textRegionHuffmanFlags >> 8) & 3;
|
|
1370
|
-
textRegion.huffmanRefinementDX = (textRegionHuffmanFlags >> 10) & 3;
|
|
1371
|
-
textRegion.huffmanRefinementDY = (textRegionHuffmanFlags >> 12) & 3;
|
|
1372
|
-
textRegion.huffmanRefinementSizeSelector = !!(
|
|
1373
|
-
textRegionHuffmanFlags & 0x4000
|
|
1374
|
-
);
|
|
1375
|
-
}
|
|
1376
|
-
if (textRegion.refinement && !textRegion.refinementTemplate) {
|
|
1377
|
-
at = [];
|
|
1378
|
-
for (i = 0; i < 2; i++) {
|
|
1379
|
-
at.push({
|
|
1380
|
-
x: readInt8(data, position),
|
|
1381
|
-
y: readInt8(data, position + 1),
|
|
1382
|
-
});
|
|
1383
|
-
position += 2;
|
|
1384
|
-
}
|
|
1385
|
-
textRegion.refinementAt = at;
|
|
1386
|
-
}
|
|
1387
|
-
textRegion.numberOfSymbolInstances = readUint32(data, position);
|
|
1388
|
-
position += 4;
|
|
1389
|
-
args = [textRegion, header.referredTo, data, position, end];
|
|
1390
|
-
break;
|
|
1391
|
-
case 16: // PatternDictionary
|
|
1392
|
-
// 7.4.4. Pattern dictionary segment syntax
|
|
1393
|
-
const patternDictionary = {};
|
|
1394
|
-
const patternDictionaryFlags = data[position++];
|
|
1395
|
-
patternDictionary.mmr = !!(patternDictionaryFlags & 1);
|
|
1396
|
-
patternDictionary.template = (patternDictionaryFlags >> 1) & 3;
|
|
1397
|
-
patternDictionary.patternWidth = data[position++];
|
|
1398
|
-
patternDictionary.patternHeight = data[position++];
|
|
1399
|
-
patternDictionary.maxPatternIndex = readUint32(data, position);
|
|
1400
|
-
position += 4;
|
|
1401
|
-
args = [patternDictionary, header.number, data, position, end];
|
|
1402
|
-
break;
|
|
1403
|
-
case 22: // ImmediateHalftoneRegion
|
|
1404
|
-
case 23: // ImmediateLosslessHalftoneRegion
|
|
1405
|
-
// 7.4.5 Halftone region segment syntax
|
|
1406
|
-
const halftoneRegion = {};
|
|
1407
|
-
halftoneRegion.info = readRegionSegmentInformation(data, position);
|
|
1408
|
-
position += RegionSegmentInformationFieldLength;
|
|
1409
|
-
const halftoneRegionFlags = data[position++];
|
|
1410
|
-
halftoneRegion.mmr = !!(halftoneRegionFlags & 1);
|
|
1411
|
-
halftoneRegion.template = (halftoneRegionFlags >> 1) & 3;
|
|
1412
|
-
halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8);
|
|
1413
|
-
halftoneRegion.combinationOperator = (halftoneRegionFlags >> 4) & 7;
|
|
1414
|
-
halftoneRegion.defaultPixelValue = (halftoneRegionFlags >> 7) & 1;
|
|
1415
|
-
halftoneRegion.gridWidth = readUint32(data, position);
|
|
1416
|
-
position += 4;
|
|
1417
|
-
halftoneRegion.gridHeight = readUint32(data, position);
|
|
1418
|
-
position += 4;
|
|
1419
|
-
halftoneRegion.gridOffsetX = readUint32(data, position) & 0xffffffff;
|
|
1420
|
-
position += 4;
|
|
1421
|
-
halftoneRegion.gridOffsetY = readUint32(data, position) & 0xffffffff;
|
|
1422
|
-
position += 4;
|
|
1423
|
-
halftoneRegion.gridVectorX = readUint16(data, position);
|
|
1424
|
-
position += 2;
|
|
1425
|
-
halftoneRegion.gridVectorY = readUint16(data, position);
|
|
1426
|
-
position += 2;
|
|
1427
|
-
args = [halftoneRegion, header.referredTo, data, position, end];
|
|
1428
|
-
break;
|
|
1429
|
-
case 38: // ImmediateGenericRegion
|
|
1430
|
-
case 39: // ImmediateLosslessGenericRegion
|
|
1431
|
-
var genericRegion = {};
|
|
1432
|
-
genericRegion.info = readRegionSegmentInformation(data, position);
|
|
1433
|
-
position += RegionSegmentInformationFieldLength;
|
|
1434
|
-
var genericRegionSegmentFlags = data[position++];
|
|
1435
|
-
genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
|
|
1436
|
-
genericRegion.template = (genericRegionSegmentFlags >> 1) & 3;
|
|
1437
|
-
genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
|
|
1438
|
-
if (!genericRegion.mmr) {
|
|
1439
|
-
atLength = genericRegion.template === 0 ? 4 : 1;
|
|
1440
|
-
at = [];
|
|
1441
|
-
for (i = 0; i < atLength; i++) {
|
|
1442
|
-
at.push({
|
|
1443
|
-
x: readInt8(data, position),
|
|
1444
|
-
y: readInt8(data, position + 1),
|
|
1445
|
-
});
|
|
1446
|
-
position += 2;
|
|
1447
|
-
}
|
|
1448
|
-
genericRegion.at = at;
|
|
1449
|
-
}
|
|
1450
|
-
args = [genericRegion, data, position, end];
|
|
1451
|
-
break;
|
|
1452
|
-
case 48: // PageInformation
|
|
1453
|
-
var pageInfo = {
|
|
1454
|
-
width: readUint32(data, position),
|
|
1455
|
-
height: readUint32(data, position + 4),
|
|
1456
|
-
resolutionX: readUint32(data, position + 8),
|
|
1457
|
-
resolutionY: readUint32(data, position + 12),
|
|
1458
|
-
};
|
|
1459
|
-
if (pageInfo.height === 0xffffffff) {
|
|
1460
|
-
delete pageInfo.height;
|
|
1461
|
-
}
|
|
1462
|
-
var pageSegmentFlags = data[position + 16];
|
|
1463
|
-
readUint16(data, position + 17); // pageStripingInformation
|
|
1464
|
-
pageInfo.lossless = !!(pageSegmentFlags & 1);
|
|
1465
|
-
pageInfo.refinement = !!(pageSegmentFlags & 2);
|
|
1466
|
-
pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1;
|
|
1467
|
-
pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3;
|
|
1468
|
-
pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
|
|
1469
|
-
pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
|
|
1470
|
-
args = [pageInfo];
|
|
1471
|
-
break;
|
|
1472
|
-
case 49: // EndOfPage
|
|
1473
|
-
break;
|
|
1474
|
-
case 50: // EndOfStripe
|
|
1475
|
-
break;
|
|
1476
|
-
case 51: // EndOfFile
|
|
1477
|
-
break;
|
|
1478
|
-
case 53: // Tables
|
|
1479
|
-
args = [header.number, data, position, end];
|
|
1480
|
-
break;
|
|
1481
|
-
case 62: // 7.4.15 defines 2 extension types which
|
|
1482
|
-
// are comments and can be ignored.
|
|
1483
|
-
break;
|
|
1484
|
-
default:
|
|
1485
|
-
throw new Jbig2Error(
|
|
1486
|
-
`segment type ${header.typeName}(${header.type})` +
|
|
1487
|
-
" is not implemented"
|
|
1488
|
-
);
|
|
1489
|
-
}
|
|
1490
|
-
var callbackName = "on" + header.typeName;
|
|
1491
|
-
if (callbackName in visitor) {
|
|
1492
|
-
visitor[callbackName].apply(visitor, args);
|
|
1493
|
-
}
|
|
1494
|
-
}
|
|
1495
|
-
|
|
1496
|
-
function processSegments(segments, visitor) {
|
|
1497
|
-
for (var i = 0, ii = segments.length; i < ii; i++) {
|
|
1498
|
-
processSegment(segments[i], visitor);
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
function parseJbig2Chunks(chunks) {
|
|
1503
|
-
var visitor = new SimpleSegmentVisitor();
|
|
1504
|
-
for (var i = 0, ii = chunks.length; i < ii; i++) {
|
|
1505
|
-
var chunk = chunks[i];
|
|
1506
|
-
var segments = readSegments({}, chunk.data, chunk.start, chunk.end);
|
|
1507
|
-
processSegments(segments, visitor);
|
|
1508
|
-
}
|
|
1509
|
-
return visitor.buffer;
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
function parseJbig2(data) {
|
|
1513
|
-
const end = data.length;
|
|
1514
|
-
let position = 0;
|
|
1515
|
-
|
|
1516
|
-
if (
|
|
1517
|
-
data[position] !== 0x97 ||
|
|
1518
|
-
data[position + 1] !== 0x4a ||
|
|
1519
|
-
data[position + 2] !== 0x42 ||
|
|
1520
|
-
data[position + 3] !== 0x32 ||
|
|
1521
|
-
data[position + 4] !== 0x0d ||
|
|
1522
|
-
data[position + 5] !== 0x0a ||
|
|
1523
|
-
data[position + 6] !== 0x1a ||
|
|
1524
|
-
data[position + 7] !== 0x0a
|
|
1525
|
-
) {
|
|
1526
|
-
throw new Jbig2Error("parseJbig2 - invalid header.");
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
const header = Object.create(null);
|
|
1530
|
-
position += 8;
|
|
1531
|
-
const flags = data[position++];
|
|
1532
|
-
header.randomAccess = !(flags & 1);
|
|
1533
|
-
if (!(flags & 2)) {
|
|
1534
|
-
header.numberOfPages = readUint32(data, position);
|
|
1535
|
-
position += 4;
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1538
|
-
const segments = readSegments(header, data, position, end);
|
|
1539
|
-
const visitor = new SimpleSegmentVisitor();
|
|
1540
|
-
processSegments(segments, visitor);
|
|
1541
|
-
|
|
1542
|
-
const { width, height } = visitor.currentPageInfo;
|
|
1543
|
-
const bitPacked = visitor.buffer;
|
|
1544
|
-
const imgData = new Uint8ClampedArray(width * height);
|
|
1545
|
-
let q = 0,
|
|
1546
|
-
k = 0;
|
|
1547
|
-
for (let i = 0; i < height; i++) {
|
|
1548
|
-
let mask = 0,
|
|
1549
|
-
buffer;
|
|
1550
|
-
for (let j = 0; j < width; j++) {
|
|
1551
|
-
if (!mask) {
|
|
1552
|
-
mask = 128;
|
|
1553
|
-
buffer = bitPacked[k++];
|
|
1554
|
-
}
|
|
1555
|
-
imgData[q++] = buffer & mask ? 0 : 255;
|
|
1556
|
-
mask >>= 1;
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
return { imgData, width, height };
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
function SimpleSegmentVisitor() {}
|
|
1564
|
-
|
|
1565
|
-
SimpleSegmentVisitor.prototype = {
|
|
1566
|
-
onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
|
|
1567
|
-
this.currentPageInfo = info;
|
|
1568
|
-
var rowSize = (info.width + 7) >> 3;
|
|
1569
|
-
var buffer = new Uint8ClampedArray(rowSize * info.height);
|
|
1570
|
-
// The contents of ArrayBuffers are initialized to 0.
|
|
1571
|
-
// Fill the buffer with 0xFF only if info.defaultPixelValue is set
|
|
1572
|
-
if (info.defaultPixelValue) {
|
|
1573
|
-
for (var i = 0, ii = buffer.length; i < ii; i++) {
|
|
1574
|
-
buffer[i] = 0xff;
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
this.buffer = buffer;
|
|
1578
|
-
},
|
|
1579
|
-
drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
|
|
1580
|
-
var pageInfo = this.currentPageInfo;
|
|
1581
|
-
var width = regionInfo.width,
|
|
1582
|
-
height = regionInfo.height;
|
|
1583
|
-
var rowSize = (pageInfo.width + 7) >> 3;
|
|
1584
|
-
var combinationOperator = pageInfo.combinationOperatorOverride
|
|
1585
|
-
? regionInfo.combinationOperator
|
|
1586
|
-
: pageInfo.combinationOperator;
|
|
1587
|
-
var buffer = this.buffer;
|
|
1588
|
-
var mask0 = 128 >> (regionInfo.x & 7);
|
|
1589
|
-
var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
|
|
1590
|
-
var i, j, mask, offset;
|
|
1591
|
-
switch (combinationOperator) {
|
|
1592
|
-
case 0: // OR
|
|
1593
|
-
for (i = 0; i < height; i++) {
|
|
1594
|
-
mask = mask0;
|
|
1595
|
-
offset = offset0;
|
|
1596
|
-
for (j = 0; j < width; j++) {
|
|
1597
|
-
if (bitmap[i][j]) {
|
|
1598
|
-
buffer[offset] |= mask;
|
|
1599
|
-
}
|
|
1600
|
-
mask >>= 1;
|
|
1601
|
-
if (!mask) {
|
|
1602
|
-
mask = 128;
|
|
1603
|
-
offset++;
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
offset0 += rowSize;
|
|
1607
|
-
}
|
|
1608
|
-
break;
|
|
1609
|
-
case 2: // XOR
|
|
1610
|
-
for (i = 0; i < height; i++) {
|
|
1611
|
-
mask = mask0;
|
|
1612
|
-
offset = offset0;
|
|
1613
|
-
for (j = 0; j < width; j++) {
|
|
1614
|
-
if (bitmap[i][j]) {
|
|
1615
|
-
buffer[offset] ^= mask;
|
|
1616
|
-
}
|
|
1617
|
-
mask >>= 1;
|
|
1618
|
-
if (!mask) {
|
|
1619
|
-
mask = 128;
|
|
1620
|
-
offset++;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
offset0 += rowSize;
|
|
1624
|
-
}
|
|
1625
|
-
break;
|
|
1626
|
-
default:
|
|
1627
|
-
throw new Jbig2Error(
|
|
1628
|
-
`operator ${combinationOperator} is not supported`
|
|
1629
|
-
);
|
|
1630
|
-
}
|
|
1631
|
-
},
|
|
1632
|
-
onImmediateGenericRegion: function SimpleSegmentVisitor_onImmediateGenericRegion(
|
|
1633
|
-
region,
|
|
1634
|
-
data,
|
|
1635
|
-
start,
|
|
1636
|
-
end
|
|
1637
|
-
) {
|
|
1638
|
-
var regionInfo = region.info;
|
|
1639
|
-
var decodingContext = new DecodingContext(data, start, end);
|
|
1640
|
-
var bitmap = decodeBitmap(
|
|
1641
|
-
region.mmr,
|
|
1642
|
-
regionInfo.width,
|
|
1643
|
-
regionInfo.height,
|
|
1644
|
-
region.template,
|
|
1645
|
-
region.prediction,
|
|
1646
|
-
null,
|
|
1647
|
-
region.at,
|
|
1648
|
-
decodingContext
|
|
1649
|
-
);
|
|
1650
|
-
this.drawBitmap(regionInfo, bitmap);
|
|
1651
|
-
},
|
|
1652
|
-
onImmediateLosslessGenericRegion: function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
|
|
1653
|
-
this.onImmediateGenericRegion.apply(this, arguments);
|
|
1654
|
-
},
|
|
1655
|
-
onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(
|
|
1656
|
-
dictionary,
|
|
1657
|
-
currentSegment,
|
|
1658
|
-
referredSegments,
|
|
1659
|
-
data,
|
|
1660
|
-
start,
|
|
1661
|
-
end
|
|
1662
|
-
) {
|
|
1663
|
-
let huffmanTables, huffmanInput;
|
|
1664
|
-
if (dictionary.huffman) {
|
|
1665
|
-
huffmanTables = getSymbolDictionaryHuffmanTables(
|
|
1666
|
-
dictionary,
|
|
1667
|
-
referredSegments,
|
|
1668
|
-
this.customTables
|
|
1669
|
-
);
|
|
1670
|
-
huffmanInput = new Reader(data, start, end);
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
// Combines exported symbols from all referred segments
|
|
1674
|
-
var symbols = this.symbols;
|
|
1675
|
-
if (!symbols) {
|
|
1676
|
-
this.symbols = symbols = {};
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
var inputSymbols = [];
|
|
1680
|
-
for (var i = 0, ii = referredSegments.length; i < ii; i++) {
|
|
1681
|
-
const referredSymbols = symbols[referredSegments[i]];
|
|
1682
|
-
// referredSymbols is undefined when we have a reference to a Tables
|
|
1683
|
-
// segment instead of a SymbolDictionary.
|
|
1684
|
-
if (referredSymbols) {
|
|
1685
|
-
inputSymbols = inputSymbols.concat(referredSymbols);
|
|
1686
|
-
}
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
|
-
var decodingContext = new DecodingContext(data, start, end);
|
|
1690
|
-
symbols[currentSegment] = decodeSymbolDictionary(
|
|
1691
|
-
dictionary.huffman,
|
|
1692
|
-
dictionary.refinement,
|
|
1693
|
-
inputSymbols,
|
|
1694
|
-
dictionary.numberOfNewSymbols,
|
|
1695
|
-
dictionary.numberOfExportedSymbols,
|
|
1696
|
-
huffmanTables,
|
|
1697
|
-
dictionary.template,
|
|
1698
|
-
dictionary.at,
|
|
1699
|
-
dictionary.refinementTemplate,
|
|
1700
|
-
dictionary.refinementAt,
|
|
1701
|
-
decodingContext,
|
|
1702
|
-
huffmanInput
|
|
1703
|
-
);
|
|
1704
|
-
},
|
|
1705
|
-
onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(
|
|
1706
|
-
region,
|
|
1707
|
-
referredSegments,
|
|
1708
|
-
data,
|
|
1709
|
-
start,
|
|
1710
|
-
end
|
|
1711
|
-
) {
|
|
1712
|
-
var regionInfo = region.info;
|
|
1713
|
-
let huffmanTables, huffmanInput;
|
|
1714
|
-
|
|
1715
|
-
// Combines exported symbols from all referred segments
|
|
1716
|
-
var symbols = this.symbols;
|
|
1717
|
-
var inputSymbols = [];
|
|
1718
|
-
for (var i = 0, ii = referredSegments.length; i < ii; i++) {
|
|
1719
|
-
const referredSymbols = symbols[referredSegments[i]];
|
|
1720
|
-
// referredSymbols is undefined when we have a reference to a Tables
|
|
1721
|
-
// segment instead of a SymbolDictionary.
|
|
1722
|
-
if (referredSymbols) {
|
|
1723
|
-
inputSymbols = inputSymbols.concat(referredSymbols);
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1726
|
-
var symbolCodeLength = log2(inputSymbols.length);
|
|
1727
|
-
if (region.huffman) {
|
|
1728
|
-
huffmanInput = new Reader(data, start, end);
|
|
1729
|
-
huffmanTables = getTextRegionHuffmanTables(
|
|
1730
|
-
region,
|
|
1731
|
-
referredSegments,
|
|
1732
|
-
this.customTables,
|
|
1733
|
-
inputSymbols.length,
|
|
1734
|
-
huffmanInput
|
|
1735
|
-
);
|
|
1736
|
-
}
|
|
1737
|
-
|
|
1738
|
-
var decodingContext = new DecodingContext(data, start, end);
|
|
1739
|
-
var bitmap = decodeTextRegion(
|
|
1740
|
-
region.huffman,
|
|
1741
|
-
region.refinement,
|
|
1742
|
-
regionInfo.width,
|
|
1743
|
-
regionInfo.height,
|
|
1744
|
-
region.defaultPixelValue,
|
|
1745
|
-
region.numberOfSymbolInstances,
|
|
1746
|
-
region.stripSize,
|
|
1747
|
-
inputSymbols,
|
|
1748
|
-
symbolCodeLength,
|
|
1749
|
-
region.transposed,
|
|
1750
|
-
region.dsOffset,
|
|
1751
|
-
region.referenceCorner,
|
|
1752
|
-
region.combinationOperator,
|
|
1753
|
-
huffmanTables,
|
|
1754
|
-
region.refinementTemplate,
|
|
1755
|
-
region.refinementAt,
|
|
1756
|
-
decodingContext,
|
|
1757
|
-
region.logStripSize,
|
|
1758
|
-
huffmanInput
|
|
1759
|
-
);
|
|
1760
|
-
this.drawBitmap(regionInfo, bitmap);
|
|
1761
|
-
},
|
|
1762
|
-
onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
|
|
1763
|
-
this.onImmediateTextRegion.apply(this, arguments);
|
|
1764
|
-
},
|
|
1765
|
-
onPatternDictionary(dictionary, currentSegment, data, start, end) {
|
|
1766
|
-
let patterns = this.patterns;
|
|
1767
|
-
if (!patterns) {
|
|
1768
|
-
this.patterns = patterns = {};
|
|
1769
|
-
}
|
|
1770
|
-
const decodingContext = new DecodingContext(data, start, end);
|
|
1771
|
-
patterns[currentSegment] = decodePatternDictionary(
|
|
1772
|
-
dictionary.mmr,
|
|
1773
|
-
dictionary.patternWidth,
|
|
1774
|
-
dictionary.patternHeight,
|
|
1775
|
-
dictionary.maxPatternIndex,
|
|
1776
|
-
dictionary.template,
|
|
1777
|
-
decodingContext
|
|
1778
|
-
);
|
|
1779
|
-
},
|
|
1780
|
-
onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
|
|
1781
|
-
// HalftoneRegion refers to exactly one PatternDictionary.
|
|
1782
|
-
const patterns = this.patterns[referredSegments[0]];
|
|
1783
|
-
const regionInfo = region.info;
|
|
1784
|
-
const decodingContext = new DecodingContext(data, start, end);
|
|
1785
|
-
const bitmap = decodeHalftoneRegion(
|
|
1786
|
-
region.mmr,
|
|
1787
|
-
patterns,
|
|
1788
|
-
region.template,
|
|
1789
|
-
regionInfo.width,
|
|
1790
|
-
regionInfo.height,
|
|
1791
|
-
region.defaultPixelValue,
|
|
1792
|
-
region.enableSkip,
|
|
1793
|
-
region.combinationOperator,
|
|
1794
|
-
region.gridWidth,
|
|
1795
|
-
region.gridHeight,
|
|
1796
|
-
region.gridOffsetX,
|
|
1797
|
-
region.gridOffsetY,
|
|
1798
|
-
region.gridVectorX,
|
|
1799
|
-
region.gridVectorY,
|
|
1800
|
-
decodingContext
|
|
1801
|
-
);
|
|
1802
|
-
this.drawBitmap(regionInfo, bitmap);
|
|
1803
|
-
},
|
|
1804
|
-
onImmediateLosslessHalftoneRegion() {
|
|
1805
|
-
this.onImmediateHalftoneRegion.apply(this, arguments);
|
|
1806
|
-
},
|
|
1807
|
-
onTables(currentSegment, data, start, end) {
|
|
1808
|
-
let customTables = this.customTables;
|
|
1809
|
-
if (!customTables) {
|
|
1810
|
-
this.customTables = customTables = {};
|
|
1811
|
-
}
|
|
1812
|
-
customTables[currentSegment] = decodeTablesSegment(data, start, end);
|
|
1813
|
-
},
|
|
1814
|
-
};
|
|
1815
|
-
|
|
1816
|
-
function HuffmanLine(lineData) {
|
|
1817
|
-
if (lineData.length === 2) {
|
|
1818
|
-
// OOB line.
|
|
1819
|
-
this.isOOB = true;
|
|
1820
|
-
this.rangeLow = 0;
|
|
1821
|
-
this.prefixLength = lineData[0];
|
|
1822
|
-
this.rangeLength = 0;
|
|
1823
|
-
this.prefixCode = lineData[1];
|
|
1824
|
-
this.isLowerRange = false;
|
|
1825
|
-
} else {
|
|
1826
|
-
// Normal, upper range or lower range line.
|
|
1827
|
-
// Upper range lines are processed like normal lines.
|
|
1828
|
-
this.isOOB = false;
|
|
1829
|
-
this.rangeLow = lineData[0];
|
|
1830
|
-
this.prefixLength = lineData[1];
|
|
1831
|
-
this.rangeLength = lineData[2];
|
|
1832
|
-
this.prefixCode = lineData[3];
|
|
1833
|
-
this.isLowerRange = lineData[4] === "lower";
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
|
|
1837
|
-
function HuffmanTreeNode(line) {
|
|
1838
|
-
this.children = [];
|
|
1839
|
-
if (line) {
|
|
1840
|
-
// Leaf node
|
|
1841
|
-
this.isLeaf = true;
|
|
1842
|
-
this.rangeLength = line.rangeLength;
|
|
1843
|
-
this.rangeLow = line.rangeLow;
|
|
1844
|
-
this.isLowerRange = line.isLowerRange;
|
|
1845
|
-
this.isOOB = line.isOOB;
|
|
1846
|
-
} else {
|
|
1847
|
-
// Intermediate or root node
|
|
1848
|
-
this.isLeaf = false;
|
|
1849
|
-
}
|
|
1850
|
-
}
|
|
1851
|
-
|
|
1852
|
-
HuffmanTreeNode.prototype = {
|
|
1853
|
-
buildTree(line, shift) {
|
|
1854
|
-
const bit = (line.prefixCode >> shift) & 1;
|
|
1855
|
-
if (shift <= 0) {
|
|
1856
|
-
// Create a leaf node.
|
|
1857
|
-
this.children[bit] = new HuffmanTreeNode(line);
|
|
1858
|
-
} else {
|
|
1859
|
-
// Create an intermediate node and continue recursively.
|
|
1860
|
-
let node = this.children[bit];
|
|
1861
|
-
if (!node) {
|
|
1862
|
-
this.children[bit] = node = new HuffmanTreeNode(null);
|
|
1863
|
-
}
|
|
1864
|
-
node.buildTree(line, shift - 1);
|
|
1865
|
-
}
|
|
1866
|
-
},
|
|
1867
|
-
decodeNode(reader) {
|
|
1868
|
-
if (this.isLeaf) {
|
|
1869
|
-
if (this.isOOB) {
|
|
1870
|
-
return null;
|
|
1871
|
-
}
|
|
1872
|
-
const htOffset = reader.readBits(this.rangeLength);
|
|
1873
|
-
return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);
|
|
1874
|
-
}
|
|
1875
|
-
const node = this.children[reader.readBit()];
|
|
1876
|
-
if (!node) {
|
|
1877
|
-
throw new Jbig2Error("invalid Huffman data");
|
|
1878
|
-
}
|
|
1879
|
-
return node.decodeNode(reader);
|
|
1880
|
-
},
|
|
1881
|
-
};
|
|
1882
|
-
|
|
1883
|
-
function HuffmanTable(lines, prefixCodesDone) {
|
|
1884
|
-
if (!prefixCodesDone) {
|
|
1885
|
-
this.assignPrefixCodes(lines);
|
|
1886
|
-
}
|
|
1887
|
-
// Create Huffman tree.
|
|
1888
|
-
this.rootNode = new HuffmanTreeNode(null);
|
|
1889
|
-
for (let i = 0, ii = lines.length; i < ii; i++) {
|
|
1890
|
-
const line = lines[i];
|
|
1891
|
-
if (line.prefixLength > 0) {
|
|
1892
|
-
this.rootNode.buildTree(line, line.prefixLength - 1);
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
|
|
1897
|
-
HuffmanTable.prototype = {
|
|
1898
|
-
decode(reader) {
|
|
1899
|
-
return this.rootNode.decodeNode(reader);
|
|
1900
|
-
},
|
|
1901
|
-
assignPrefixCodes(lines) {
|
|
1902
|
-
// Annex B.3 Assigning the prefix codes.
|
|
1903
|
-
const linesLength = lines.length;
|
|
1904
|
-
let prefixLengthMax = 0;
|
|
1905
|
-
for (let i = 0; i < linesLength; i++) {
|
|
1906
|
-
prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
const histogram = new Uint32Array(prefixLengthMax + 1);
|
|
1910
|
-
for (let i = 0; i < linesLength; i++) {
|
|
1911
|
-
histogram[lines[i].prefixLength]++;
|
|
1912
|
-
}
|
|
1913
|
-
let currentLength = 1,
|
|
1914
|
-
firstCode = 0,
|
|
1915
|
-
currentCode,
|
|
1916
|
-
currentTemp,
|
|
1917
|
-
line;
|
|
1918
|
-
histogram[0] = 0;
|
|
1919
|
-
|
|
1920
|
-
while (currentLength <= prefixLengthMax) {
|
|
1921
|
-
firstCode = (firstCode + histogram[currentLength - 1]) << 1;
|
|
1922
|
-
currentCode = firstCode;
|
|
1923
|
-
currentTemp = 0;
|
|
1924
|
-
while (currentTemp < linesLength) {
|
|
1925
|
-
line = lines[currentTemp];
|
|
1926
|
-
if (line.prefixLength === currentLength) {
|
|
1927
|
-
line.prefixCode = currentCode;
|
|
1928
|
-
currentCode++;
|
|
1929
|
-
}
|
|
1930
|
-
currentTemp++;
|
|
1931
|
-
}
|
|
1932
|
-
currentLength++;
|
|
1933
|
-
}
|
|
1934
|
-
},
|
|
1935
|
-
};
|
|
1936
|
-
|
|
1937
|
-
function decodeTablesSegment(data, start, end) {
|
|
1938
|
-
// Decodes a Tables segment, i.e., a custom Huffman table.
|
|
1939
|
-
// Annex B.2 Code table structure.
|
|
1940
|
-
const flags = data[start];
|
|
1941
|
-
const lowestValue = readUint32(data, start + 1) & 0xffffffff;
|
|
1942
|
-
const highestValue = readUint32(data, start + 5) & 0xffffffff;
|
|
1943
|
-
const reader = new Reader(data, start + 9, end);
|
|
1944
|
-
|
|
1945
|
-
const prefixSizeBits = ((flags >> 1) & 7) + 1;
|
|
1946
|
-
const rangeSizeBits = ((flags >> 4) & 7) + 1;
|
|
1947
|
-
const lines = [];
|
|
1948
|
-
let prefixLength,
|
|
1949
|
-
rangeLength,
|
|
1950
|
-
currentRangeLow = lowestValue;
|
|
1951
|
-
|
|
1952
|
-
// Normal table lines
|
|
1953
|
-
do {
|
|
1954
|
-
prefixLength = reader.readBits(prefixSizeBits);
|
|
1955
|
-
rangeLength = reader.readBits(rangeSizeBits);
|
|
1956
|
-
lines.push(
|
|
1957
|
-
new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0])
|
|
1958
|
-
);
|
|
1959
|
-
currentRangeLow += 1 << rangeLength;
|
|
1960
|
-
} while (currentRangeLow < highestValue);
|
|
1961
|
-
|
|
1962
|
-
// Lower range table line
|
|
1963
|
-
prefixLength = reader.readBits(prefixSizeBits);
|
|
1964
|
-
lines.push(
|
|
1965
|
-
new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"])
|
|
1966
|
-
);
|
|
1967
|
-
|
|
1968
|
-
// Upper range table line
|
|
1969
|
-
prefixLength = reader.readBits(prefixSizeBits);
|
|
1970
|
-
lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));
|
|
1971
|
-
|
|
1972
|
-
if (flags & 1) {
|
|
1973
|
-
// Out-of-band table line
|
|
1974
|
-
prefixLength = reader.readBits(prefixSizeBits);
|
|
1975
|
-
lines.push(new HuffmanLine([prefixLength, 0]));
|
|
1976
|
-
}
|
|
1977
|
-
|
|
1978
|
-
return new HuffmanTable(lines, false);
|
|
1979
|
-
}
|
|
1980
|
-
|
|
1981
|
-
const standardTablesCache = {};
|
|
1982
|
-
|
|
1983
|
-
function getStandardTable(number) {
|
|
1984
|
-
// Annex B.5 Standard Huffman tables.
|
|
1985
|
-
let table = standardTablesCache[number];
|
|
1986
|
-
if (table) {
|
|
1987
|
-
return table;
|
|
1988
|
-
}
|
|
1989
|
-
let lines;
|
|
1990
|
-
switch (number) {
|
|
1991
|
-
case 1:
|
|
1992
|
-
lines = [
|
|
1993
|
-
[0, 1, 4, 0x0],
|
|
1994
|
-
[16, 2, 8, 0x2],
|
|
1995
|
-
[272, 3, 16, 0x6],
|
|
1996
|
-
[65808, 3, 32, 0x7], // upper
|
|
1997
|
-
];
|
|
1998
|
-
break;
|
|
1999
|
-
case 2:
|
|
2000
|
-
lines = [
|
|
2001
|
-
[0, 1, 0, 0x0],
|
|
2002
|
-
[1, 2, 0, 0x2],
|
|
2003
|
-
[2, 3, 0, 0x6],
|
|
2004
|
-
[3, 4, 3, 0xe],
|
|
2005
|
-
[11, 5, 6, 0x1e],
|
|
2006
|
-
[75, 6, 32, 0x3e], // upper
|
|
2007
|
-
[6, 0x3f], // OOB
|
|
2008
|
-
];
|
|
2009
|
-
break;
|
|
2010
|
-
case 3:
|
|
2011
|
-
lines = [
|
|
2012
|
-
[-256, 8, 8, 0xfe],
|
|
2013
|
-
[0, 1, 0, 0x0],
|
|
2014
|
-
[1, 2, 0, 0x2],
|
|
2015
|
-
[2, 3, 0, 0x6],
|
|
2016
|
-
[3, 4, 3, 0xe],
|
|
2017
|
-
[11, 5, 6, 0x1e],
|
|
2018
|
-
[-257, 8, 32, 0xff, "lower"],
|
|
2019
|
-
[75, 7, 32, 0x7e], // upper
|
|
2020
|
-
[6, 0x3e], // OOB
|
|
2021
|
-
];
|
|
2022
|
-
break;
|
|
2023
|
-
case 4:
|
|
2024
|
-
lines = [
|
|
2025
|
-
[1, 1, 0, 0x0],
|
|
2026
|
-
[2, 2, 0, 0x2],
|
|
2027
|
-
[3, 3, 0, 0x6],
|
|
2028
|
-
[4, 4, 3, 0xe],
|
|
2029
|
-
[12, 5, 6, 0x1e],
|
|
2030
|
-
[76, 5, 32, 0x1f], // upper
|
|
2031
|
-
];
|
|
2032
|
-
break;
|
|
2033
|
-
case 5:
|
|
2034
|
-
lines = [
|
|
2035
|
-
[-255, 7, 8, 0x7e],
|
|
2036
|
-
[1, 1, 0, 0x0],
|
|
2037
|
-
[2, 2, 0, 0x2],
|
|
2038
|
-
[3, 3, 0, 0x6],
|
|
2039
|
-
[4, 4, 3, 0xe],
|
|
2040
|
-
[12, 5, 6, 0x1e],
|
|
2041
|
-
[-256, 7, 32, 0x7f, "lower"],
|
|
2042
|
-
[76, 6, 32, 0x3e], // upper
|
|
2043
|
-
];
|
|
2044
|
-
break;
|
|
2045
|
-
case 6:
|
|
2046
|
-
lines = [
|
|
2047
|
-
[-2048, 5, 10, 0x1c],
|
|
2048
|
-
[-1024, 4, 9, 0x8],
|
|
2049
|
-
[-512, 4, 8, 0x9],
|
|
2050
|
-
[-256, 4, 7, 0xa],
|
|
2051
|
-
[-128, 5, 6, 0x1d],
|
|
2052
|
-
[-64, 5, 5, 0x1e],
|
|
2053
|
-
[-32, 4, 5, 0xb],
|
|
2054
|
-
[0, 2, 7, 0x0],
|
|
2055
|
-
[128, 3, 7, 0x2],
|
|
2056
|
-
[256, 3, 8, 0x3],
|
|
2057
|
-
[512, 4, 9, 0xc],
|
|
2058
|
-
[1024, 4, 10, 0xd],
|
|
2059
|
-
[-2049, 6, 32, 0x3e, "lower"],
|
|
2060
|
-
[2048, 6, 32, 0x3f], // upper
|
|
2061
|
-
];
|
|
2062
|
-
break;
|
|
2063
|
-
case 7:
|
|
2064
|
-
lines = [
|
|
2065
|
-
[-1024, 4, 9, 0x8],
|
|
2066
|
-
[-512, 3, 8, 0x0],
|
|
2067
|
-
[-256, 4, 7, 0x9],
|
|
2068
|
-
[-128, 5, 6, 0x1a],
|
|
2069
|
-
[-64, 5, 5, 0x1b],
|
|
2070
|
-
[-32, 4, 5, 0xa],
|
|
2071
|
-
[0, 4, 5, 0xb],
|
|
2072
|
-
[32, 5, 5, 0x1c],
|
|
2073
|
-
[64, 5, 6, 0x1d],
|
|
2074
|
-
[128, 4, 7, 0xc],
|
|
2075
|
-
[256, 3, 8, 0x1],
|
|
2076
|
-
[512, 3, 9, 0x2],
|
|
2077
|
-
[1024, 3, 10, 0x3],
|
|
2078
|
-
[-1025, 5, 32, 0x1e, "lower"],
|
|
2079
|
-
[2048, 5, 32, 0x1f], // upper
|
|
2080
|
-
];
|
|
2081
|
-
break;
|
|
2082
|
-
case 8:
|
|
2083
|
-
lines = [
|
|
2084
|
-
[-15, 8, 3, 0xfc],
|
|
2085
|
-
[-7, 9, 1, 0x1fc],
|
|
2086
|
-
[-5, 8, 1, 0xfd],
|
|
2087
|
-
[-3, 9, 0, 0x1fd],
|
|
2088
|
-
[-2, 7, 0, 0x7c],
|
|
2089
|
-
[-1, 4, 0, 0xa],
|
|
2090
|
-
[0, 2, 1, 0x0],
|
|
2091
|
-
[2, 5, 0, 0x1a],
|
|
2092
|
-
[3, 6, 0, 0x3a],
|
|
2093
|
-
[4, 3, 4, 0x4],
|
|
2094
|
-
[20, 6, 1, 0x3b],
|
|
2095
|
-
[22, 4, 4, 0xb],
|
|
2096
|
-
[38, 4, 5, 0xc],
|
|
2097
|
-
[70, 5, 6, 0x1b],
|
|
2098
|
-
[134, 5, 7, 0x1c],
|
|
2099
|
-
[262, 6, 7, 0x3c],
|
|
2100
|
-
[390, 7, 8, 0x7d],
|
|
2101
|
-
[646, 6, 10, 0x3d],
|
|
2102
|
-
[-16, 9, 32, 0x1fe, "lower"],
|
|
2103
|
-
[1670, 9, 32, 0x1ff], // upper
|
|
2104
|
-
[2, 0x1], // OOB
|
|
2105
|
-
];
|
|
2106
|
-
break;
|
|
2107
|
-
case 9:
|
|
2108
|
-
lines = [
|
|
2109
|
-
[-31, 8, 4, 0xfc],
|
|
2110
|
-
[-15, 9, 2, 0x1fc],
|
|
2111
|
-
[-11, 8, 2, 0xfd],
|
|
2112
|
-
[-7, 9, 1, 0x1fd],
|
|
2113
|
-
[-5, 7, 1, 0x7c],
|
|
2114
|
-
[-3, 4, 1, 0xa],
|
|
2115
|
-
[-1, 3, 1, 0x2],
|
|
2116
|
-
[1, 3, 1, 0x3],
|
|
2117
|
-
[3, 5, 1, 0x1a],
|
|
2118
|
-
[5, 6, 1, 0x3a],
|
|
2119
|
-
[7, 3, 5, 0x4],
|
|
2120
|
-
[39, 6, 2, 0x3b],
|
|
2121
|
-
[43, 4, 5, 0xb],
|
|
2122
|
-
[75, 4, 6, 0xc],
|
|
2123
|
-
[139, 5, 7, 0x1b],
|
|
2124
|
-
[267, 5, 8, 0x1c],
|
|
2125
|
-
[523, 6, 8, 0x3c],
|
|
2126
|
-
[779, 7, 9, 0x7d],
|
|
2127
|
-
[1291, 6, 11, 0x3d],
|
|
2128
|
-
[-32, 9, 32, 0x1fe, "lower"],
|
|
2129
|
-
[3339, 9, 32, 0x1ff], // upper
|
|
2130
|
-
[2, 0x0], // OOB
|
|
2131
|
-
];
|
|
2132
|
-
break;
|
|
2133
|
-
case 10:
|
|
2134
|
-
lines = [
|
|
2135
|
-
[-21, 7, 4, 0x7a],
|
|
2136
|
-
[-5, 8, 0, 0xfc],
|
|
2137
|
-
[-4, 7, 0, 0x7b],
|
|
2138
|
-
[-3, 5, 0, 0x18],
|
|
2139
|
-
[-2, 2, 2, 0x0],
|
|
2140
|
-
[2, 5, 0, 0x19],
|
|
2141
|
-
[3, 6, 0, 0x36],
|
|
2142
|
-
[4, 7, 0, 0x7c],
|
|
2143
|
-
[5, 8, 0, 0xfd],
|
|
2144
|
-
[6, 2, 6, 0x1],
|
|
2145
|
-
[70, 5, 5, 0x1a],
|
|
2146
|
-
[102, 6, 5, 0x37],
|
|
2147
|
-
[134, 6, 6, 0x38],
|
|
2148
|
-
[198, 6, 7, 0x39],
|
|
2149
|
-
[326, 6, 8, 0x3a],
|
|
2150
|
-
[582, 6, 9, 0x3b],
|
|
2151
|
-
[1094, 6, 10, 0x3c],
|
|
2152
|
-
[2118, 7, 11, 0x7d],
|
|
2153
|
-
[-22, 8, 32, 0xfe, "lower"],
|
|
2154
|
-
[4166, 8, 32, 0xff], // upper
|
|
2155
|
-
[2, 0x2], // OOB
|
|
2156
|
-
];
|
|
2157
|
-
break;
|
|
2158
|
-
case 11:
|
|
2159
|
-
lines = [
|
|
2160
|
-
[1, 1, 0, 0x0],
|
|
2161
|
-
[2, 2, 1, 0x2],
|
|
2162
|
-
[4, 4, 0, 0xc],
|
|
2163
|
-
[5, 4, 1, 0xd],
|
|
2164
|
-
[7, 5, 1, 0x1c],
|
|
2165
|
-
[9, 5, 2, 0x1d],
|
|
2166
|
-
[13, 6, 2, 0x3c],
|
|
2167
|
-
[17, 7, 2, 0x7a],
|
|
2168
|
-
[21, 7, 3, 0x7b],
|
|
2169
|
-
[29, 7, 4, 0x7c],
|
|
2170
|
-
[45, 7, 5, 0x7d],
|
|
2171
|
-
[77, 7, 6, 0x7e],
|
|
2172
|
-
[141, 7, 32, 0x7f], // upper
|
|
2173
|
-
];
|
|
2174
|
-
break;
|
|
2175
|
-
case 12:
|
|
2176
|
-
lines = [
|
|
2177
|
-
[1, 1, 0, 0x0],
|
|
2178
|
-
[2, 2, 0, 0x2],
|
|
2179
|
-
[3, 3, 1, 0x6],
|
|
2180
|
-
[5, 5, 0, 0x1c],
|
|
2181
|
-
[6, 5, 1, 0x1d],
|
|
2182
|
-
[8, 6, 1, 0x3c],
|
|
2183
|
-
[10, 7, 0, 0x7a],
|
|
2184
|
-
[11, 7, 1, 0x7b],
|
|
2185
|
-
[13, 7, 2, 0x7c],
|
|
2186
|
-
[17, 7, 3, 0x7d],
|
|
2187
|
-
[25, 7, 4, 0x7e],
|
|
2188
|
-
[41, 8, 5, 0xfe],
|
|
2189
|
-
[73, 8, 32, 0xff], // upper
|
|
2190
|
-
];
|
|
2191
|
-
break;
|
|
2192
|
-
case 13:
|
|
2193
|
-
lines = [
|
|
2194
|
-
[1, 1, 0, 0x0],
|
|
2195
|
-
[2, 3, 0, 0x4],
|
|
2196
|
-
[3, 4, 0, 0xc],
|
|
2197
|
-
[4, 5, 0, 0x1c],
|
|
2198
|
-
[5, 4, 1, 0xd],
|
|
2199
|
-
[7, 3, 3, 0x5],
|
|
2200
|
-
[15, 6, 1, 0x3a],
|
|
2201
|
-
[17, 6, 2, 0x3b],
|
|
2202
|
-
[21, 6, 3, 0x3c],
|
|
2203
|
-
[29, 6, 4, 0x3d],
|
|
2204
|
-
[45, 6, 5, 0x3e],
|
|
2205
|
-
[77, 7, 6, 0x7e],
|
|
2206
|
-
[141, 7, 32, 0x7f], // upper
|
|
2207
|
-
];
|
|
2208
|
-
break;
|
|
2209
|
-
case 14:
|
|
2210
|
-
lines = [
|
|
2211
|
-
[-2, 3, 0, 0x4],
|
|
2212
|
-
[-1, 3, 0, 0x5],
|
|
2213
|
-
[0, 1, 0, 0x0],
|
|
2214
|
-
[1, 3, 0, 0x6],
|
|
2215
|
-
[2, 3, 0, 0x7],
|
|
2216
|
-
];
|
|
2217
|
-
break;
|
|
2218
|
-
case 15:
|
|
2219
|
-
lines = [
|
|
2220
|
-
[-24, 7, 4, 0x7c],
|
|
2221
|
-
[-8, 6, 2, 0x3c],
|
|
2222
|
-
[-4, 5, 1, 0x1c],
|
|
2223
|
-
[-2, 4, 0, 0xc],
|
|
2224
|
-
[-1, 3, 0, 0x4],
|
|
2225
|
-
[0, 1, 0, 0x0],
|
|
2226
|
-
[1, 3, 0, 0x5],
|
|
2227
|
-
[2, 4, 0, 0xd],
|
|
2228
|
-
[3, 5, 1, 0x1d],
|
|
2229
|
-
[5, 6, 2, 0x3d],
|
|
2230
|
-
[9, 7, 4, 0x7d],
|
|
2231
|
-
[-25, 7, 32, 0x7e, "lower"],
|
|
2232
|
-
[25, 7, 32, 0x7f], // upper
|
|
2233
|
-
];
|
|
2234
|
-
break;
|
|
2235
|
-
default:
|
|
2236
|
-
throw new Jbig2Error(`standard table B.${number} does not exist`);
|
|
2237
|
-
}
|
|
2238
|
-
|
|
2239
|
-
for (let i = 0, ii = lines.length; i < ii; i++) {
|
|
2240
|
-
lines[i] = new HuffmanLine(lines[i]);
|
|
2241
|
-
}
|
|
2242
|
-
table = new HuffmanTable(lines, true);
|
|
2243
|
-
standardTablesCache[number] = table;
|
|
2244
|
-
return table;
|
|
2245
|
-
}
|
|
2246
|
-
|
|
2247
|
-
function Reader(data, start, end) {
|
|
2248
|
-
this.data = data;
|
|
2249
|
-
this.start = start;
|
|
2250
|
-
this.end = end;
|
|
2251
|
-
this.position = start;
|
|
2252
|
-
this.shift = -1;
|
|
2253
|
-
this.currentByte = 0;
|
|
2254
|
-
}
|
|
2255
|
-
|
|
2256
|
-
Reader.prototype = {
|
|
2257
|
-
readBit() {
|
|
2258
|
-
if (this.shift < 0) {
|
|
2259
|
-
if (this.position >= this.end) {
|
|
2260
|
-
throw new Jbig2Error("end of data while reading bit");
|
|
2261
|
-
}
|
|
2262
|
-
this.currentByte = this.data[this.position++];
|
|
2263
|
-
this.shift = 7;
|
|
2264
|
-
}
|
|
2265
|
-
const bit = (this.currentByte >> this.shift) & 1;
|
|
2266
|
-
this.shift--;
|
|
2267
|
-
return bit;
|
|
2268
|
-
},
|
|
2269
|
-
|
|
2270
|
-
readBits(numBits) {
|
|
2271
|
-
let result = 0,
|
|
2272
|
-
i;
|
|
2273
|
-
for (i = numBits - 1; i >= 0; i--) {
|
|
2274
|
-
result |= this.readBit() << i;
|
|
2275
|
-
}
|
|
2276
|
-
return result;
|
|
2277
|
-
},
|
|
2278
|
-
|
|
2279
|
-
byteAlign() {
|
|
2280
|
-
this.shift = -1;
|
|
2281
|
-
},
|
|
2282
|
-
|
|
2283
|
-
next() {
|
|
2284
|
-
if (this.position >= this.end) {
|
|
2285
|
-
return -1;
|
|
2286
|
-
}
|
|
2287
|
-
return this.data[this.position++];
|
|
2288
|
-
},
|
|
2289
|
-
};
|
|
2290
|
-
|
|
2291
|
-
function getCustomHuffmanTable(index, referredTo, customTables) {
|
|
2292
|
-
// Returns a Tables segment that has been earlier decoded.
|
|
2293
|
-
// See 7.4.2.1.6 (symbol dictionary) or 7.4.3.1.6 (text region).
|
|
2294
|
-
let currentIndex = 0;
|
|
2295
|
-
for (let i = 0, ii = referredTo.length; i < ii; i++) {
|
|
2296
|
-
const table = customTables[referredTo[i]];
|
|
2297
|
-
if (table) {
|
|
2298
|
-
if (index === currentIndex) {
|
|
2299
|
-
return table;
|
|
2300
|
-
}
|
|
2301
|
-
currentIndex++;
|
|
2302
|
-
}
|
|
2303
|
-
}
|
|
2304
|
-
throw new Jbig2Error("can't find custom Huffman table");
|
|
2305
|
-
}
|
|
2306
|
-
|
|
2307
|
-
function getTextRegionHuffmanTables(
|
|
2308
|
-
textRegion,
|
|
2309
|
-
referredTo,
|
|
2310
|
-
customTables,
|
|
2311
|
-
numberOfSymbols,
|
|
2312
|
-
reader
|
|
2313
|
-
) {
|
|
2314
|
-
// 7.4.3.1.7 Symbol ID Huffman table decoding
|
|
2315
|
-
|
|
2316
|
-
// Read code lengths for RUNCODEs 0...34.
|
|
2317
|
-
const codes = [];
|
|
2318
|
-
for (let i = 0; i <= 34; i++) {
|
|
2319
|
-
const codeLength = reader.readBits(4);
|
|
2320
|
-
codes.push(new HuffmanLine([i, codeLength, 0, 0]));
|
|
2321
|
-
}
|
|
2322
|
-
// Assign Huffman codes for RUNCODEs.
|
|
2323
|
-
const runCodesTable = new HuffmanTable(codes, false);
|
|
2324
|
-
|
|
2325
|
-
// Read a Huffman code using the assignment above.
|
|
2326
|
-
// Interpret the RUNCODE codes and the additional bits (if any).
|
|
2327
|
-
codes.length = 0;
|
|
2328
|
-
for (let i = 0; i < numberOfSymbols; ) {
|
|
2329
|
-
const codeLength = runCodesTable.decode(reader);
|
|
2330
|
-
if (codeLength >= 32) {
|
|
2331
|
-
let repeatedLength, numberOfRepeats, j;
|
|
2332
|
-
switch (codeLength) {
|
|
2333
|
-
case 32:
|
|
2334
|
-
if (i === 0) {
|
|
2335
|
-
throw new Jbig2Error("no previous value in symbol ID table");
|
|
2336
|
-
}
|
|
2337
|
-
numberOfRepeats = reader.readBits(2) + 3;
|
|
2338
|
-
repeatedLength = codes[i - 1].prefixLength;
|
|
2339
|
-
break;
|
|
2340
|
-
case 33:
|
|
2341
|
-
numberOfRepeats = reader.readBits(3) + 3;
|
|
2342
|
-
repeatedLength = 0;
|
|
2343
|
-
break;
|
|
2344
|
-
case 34:
|
|
2345
|
-
numberOfRepeats = reader.readBits(7) + 11;
|
|
2346
|
-
repeatedLength = 0;
|
|
2347
|
-
break;
|
|
2348
|
-
default:
|
|
2349
|
-
throw new Jbig2Error("invalid code length in symbol ID table");
|
|
2350
|
-
}
|
|
2351
|
-
for (j = 0; j < numberOfRepeats; j++) {
|
|
2352
|
-
codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));
|
|
2353
|
-
i++;
|
|
2354
|
-
}
|
|
2355
|
-
} else {
|
|
2356
|
-
codes.push(new HuffmanLine([i, codeLength, 0, 0]));
|
|
2357
|
-
i++;
|
|
2358
|
-
}
|
|
2359
|
-
}
|
|
2360
|
-
reader.byteAlign();
|
|
2361
|
-
const symbolIDTable = new HuffmanTable(codes, false);
|
|
2362
|
-
|
|
2363
|
-
// 7.4.3.1.6 Text region segment Huffman table selection
|
|
2364
|
-
|
|
2365
|
-
let customIndex = 0,
|
|
2366
|
-
tableFirstS,
|
|
2367
|
-
tableDeltaS,
|
|
2368
|
-
tableDeltaT;
|
|
2369
|
-
|
|
2370
|
-
switch (textRegion.huffmanFS) {
|
|
2371
|
-
case 0:
|
|
2372
|
-
case 1:
|
|
2373
|
-
tableFirstS = getStandardTable(textRegion.huffmanFS + 6);
|
|
2374
|
-
break;
|
|
2375
|
-
case 3:
|
|
2376
|
-
tableFirstS = getCustomHuffmanTable(
|
|
2377
|
-
customIndex,
|
|
2378
|
-
referredTo,
|
|
2379
|
-
customTables
|
|
2380
|
-
);
|
|
2381
|
-
customIndex++;
|
|
2382
|
-
break;
|
|
2383
|
-
default:
|
|
2384
|
-
throw new Jbig2Error("invalid Huffman FS selector");
|
|
2385
|
-
}
|
|
2386
|
-
|
|
2387
|
-
switch (textRegion.huffmanDS) {
|
|
2388
|
-
case 0:
|
|
2389
|
-
case 1:
|
|
2390
|
-
case 2:
|
|
2391
|
-
tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);
|
|
2392
|
-
break;
|
|
2393
|
-
case 3:
|
|
2394
|
-
tableDeltaS = getCustomHuffmanTable(
|
|
2395
|
-
customIndex,
|
|
2396
|
-
referredTo,
|
|
2397
|
-
customTables
|
|
2398
|
-
);
|
|
2399
|
-
customIndex++;
|
|
2400
|
-
break;
|
|
2401
|
-
default:
|
|
2402
|
-
throw new Jbig2Error("invalid Huffman DS selector");
|
|
2403
|
-
}
|
|
2404
|
-
|
|
2405
|
-
switch (textRegion.huffmanDT) {
|
|
2406
|
-
case 0:
|
|
2407
|
-
case 1:
|
|
2408
|
-
case 2:
|
|
2409
|
-
tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);
|
|
2410
|
-
break;
|
|
2411
|
-
case 3:
|
|
2412
|
-
tableDeltaT = getCustomHuffmanTable(
|
|
2413
|
-
customIndex,
|
|
2414
|
-
referredTo,
|
|
2415
|
-
customTables
|
|
2416
|
-
);
|
|
2417
|
-
customIndex++;
|
|
2418
|
-
break;
|
|
2419
|
-
default:
|
|
2420
|
-
throw new Jbig2Error("invalid Huffman DT selector");
|
|
2421
|
-
}
|
|
2422
|
-
|
|
2423
|
-
if (textRegion.refinement) {
|
|
2424
|
-
// Load tables RDW, RDH, RDX and RDY.
|
|
2425
|
-
throw new Jbig2Error("refinement with Huffman is not supported");
|
|
2426
|
-
}
|
|
2427
|
-
|
|
2428
|
-
return {
|
|
2429
|
-
symbolIDTable,
|
|
2430
|
-
tableFirstS,
|
|
2431
|
-
tableDeltaS,
|
|
2432
|
-
tableDeltaT,
|
|
2433
|
-
};
|
|
2434
|
-
}
|
|
2435
|
-
|
|
2436
|
-
function getSymbolDictionaryHuffmanTables(
|
|
2437
|
-
dictionary,
|
|
2438
|
-
referredTo,
|
|
2439
|
-
customTables
|
|
2440
|
-
) {
|
|
2441
|
-
// 7.4.2.1.6 Symbol dictionary segment Huffman table selection
|
|
2442
|
-
|
|
2443
|
-
let customIndex = 0,
|
|
2444
|
-
tableDeltaHeight,
|
|
2445
|
-
tableDeltaWidth;
|
|
2446
|
-
switch (dictionary.huffmanDHSelector) {
|
|
2447
|
-
case 0:
|
|
2448
|
-
case 1:
|
|
2449
|
-
tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);
|
|
2450
|
-
break;
|
|
2451
|
-
case 3:
|
|
2452
|
-
tableDeltaHeight = getCustomHuffmanTable(
|
|
2453
|
-
customIndex,
|
|
2454
|
-
referredTo,
|
|
2455
|
-
customTables
|
|
2456
|
-
);
|
|
2457
|
-
customIndex++;
|
|
2458
|
-
break;
|
|
2459
|
-
default:
|
|
2460
|
-
throw new Jbig2Error("invalid Huffman DH selector");
|
|
2461
|
-
}
|
|
2462
|
-
|
|
2463
|
-
switch (dictionary.huffmanDWSelector) {
|
|
2464
|
-
case 0:
|
|
2465
|
-
case 1:
|
|
2466
|
-
tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);
|
|
2467
|
-
break;
|
|
2468
|
-
case 3:
|
|
2469
|
-
tableDeltaWidth = getCustomHuffmanTable(
|
|
2470
|
-
customIndex,
|
|
2471
|
-
referredTo,
|
|
2472
|
-
customTables
|
|
2473
|
-
);
|
|
2474
|
-
customIndex++;
|
|
2475
|
-
break;
|
|
2476
|
-
default:
|
|
2477
|
-
throw new Jbig2Error("invalid Huffman DW selector");
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
|
-
let tableBitmapSize, tableAggregateInstances;
|
|
2481
|
-
if (dictionary.bitmapSizeSelector) {
|
|
2482
|
-
tableBitmapSize = getCustomHuffmanTable(
|
|
2483
|
-
customIndex,
|
|
2484
|
-
referredTo,
|
|
2485
|
-
customTables
|
|
2486
|
-
);
|
|
2487
|
-
customIndex++;
|
|
2488
|
-
} else {
|
|
2489
|
-
tableBitmapSize = getStandardTable(1);
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
if (dictionary.aggregationInstancesSelector) {
|
|
2493
|
-
tableAggregateInstances = getCustomHuffmanTable(
|
|
2494
|
-
customIndex,
|
|
2495
|
-
referredTo,
|
|
2496
|
-
customTables
|
|
2497
|
-
);
|
|
2498
|
-
} else {
|
|
2499
|
-
tableAggregateInstances = getStandardTable(1);
|
|
2500
|
-
}
|
|
2501
|
-
|
|
2502
|
-
return {
|
|
2503
|
-
tableDeltaHeight,
|
|
2504
|
-
tableDeltaWidth,
|
|
2505
|
-
tableBitmapSize,
|
|
2506
|
-
tableAggregateInstances,
|
|
2507
|
-
};
|
|
2508
|
-
}
|
|
2509
|
-
|
|
2510
|
-
function readUncompressedBitmap(reader, width, height) {
|
|
2511
|
-
const bitmap = [];
|
|
2512
|
-
for (let y = 0; y < height; y++) {
|
|
2513
|
-
const row = new Uint8Array(width);
|
|
2514
|
-
bitmap.push(row);
|
|
2515
|
-
for (let x = 0; x < width; x++) {
|
|
2516
|
-
row[x] = reader.readBit();
|
|
2517
|
-
}
|
|
2518
|
-
reader.byteAlign();
|
|
2519
|
-
}
|
|
2520
|
-
return bitmap;
|
|
2521
|
-
}
|
|
2522
|
-
|
|
2523
|
-
function decodeMMRBitmap(input, width, height, endOfBlock) {
|
|
2524
|
-
// MMR is the same compression algorithm as the PDF filter
|
|
2525
|
-
// CCITTFaxDecode with /K -1.
|
|
2526
|
-
const params = {
|
|
2527
|
-
K: -1,
|
|
2528
|
-
Columns: width,
|
|
2529
|
-
Rows: height,
|
|
2530
|
-
BlackIs1: true,
|
|
2531
|
-
EndOfBlock: endOfBlock,
|
|
2532
|
-
};
|
|
2533
|
-
const decoder = new CCITTFaxDecoder(input, params);
|
|
2534
|
-
const bitmap = [];
|
|
2535
|
-
let currentByte,
|
|
2536
|
-
eof = false;
|
|
2537
|
-
|
|
2538
|
-
for (let y = 0; y < height; y++) {
|
|
2539
|
-
const row = new Uint8Array(width);
|
|
2540
|
-
bitmap.push(row);
|
|
2541
|
-
let shift = -1;
|
|
2542
|
-
for (let x = 0; x < width; x++) {
|
|
2543
|
-
if (shift < 0) {
|
|
2544
|
-
currentByte = decoder.readNextChar();
|
|
2545
|
-
if (currentByte === -1) {
|
|
2546
|
-
// Set the rest of the bits to zero.
|
|
2547
|
-
currentByte = 0;
|
|
2548
|
-
eof = true;
|
|
2549
|
-
}
|
|
2550
|
-
shift = 7;
|
|
2551
|
-
}
|
|
2552
|
-
row[x] = (currentByte >> shift) & 1;
|
|
2553
|
-
shift--;
|
|
2554
|
-
}
|
|
2555
|
-
}
|
|
2556
|
-
|
|
2557
|
-
if (endOfBlock && !eof) {
|
|
2558
|
-
// Read until EOFB has been consumed.
|
|
2559
|
-
const lookForEOFLimit = 5;
|
|
2560
|
-
for (let i = 0; i < lookForEOFLimit; i++) {
|
|
2561
|
-
if (decoder.readNextChar() === -1) {
|
|
2562
|
-
break;
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2567
|
-
return bitmap;
|
|
2568
|
-
}
|
|
2569
|
-
|
|
2570
|
-
// eslint-disable-next-line no-shadow
|
|
2571
|
-
function Jbig2Image() {}
|
|
2572
|
-
|
|
2573
|
-
Jbig2Image.prototype = {
|
|
2574
|
-
parseChunks(chunks) {
|
|
2575
|
-
return parseJbig2Chunks(chunks);
|
|
2576
|
-
},
|
|
2577
|
-
|
|
2578
|
-
parse(data) {
|
|
2579
|
-
const { imgData, width, height } = parseJbig2(data);
|
|
2580
|
-
this.width = width;
|
|
2581
|
-
this.height = height;
|
|
2582
|
-
return imgData;
|
|
2583
|
-
},
|
|
2584
|
-
};
|
|
2585
|
-
|
|
2586
|
-
return Jbig2Image;
|
|
2587
|
-
})();
|
|
2588
|
-
|
|
2589
|
-
export { Jbig2Image };
|