@vaadin-component-factory/vcf-pdf-viewer 0.9.0 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +1 -1
  2. package/package.json +33 -18
  3. package/{src/display → pdfjs/dist}/display_utils.js +344 -139
  4. package/{src/display → pdfjs/dist}/fetch_stream.js +115 -97
  5. package/pdfjs/dist/get.js +1857 -0
  6. package/pdfjs/dist/index.js +767 -0
  7. package/pdfjs/dist/l10n_utils.js +140 -0
  8. package/{src/shared → pdfjs/dist}/message_handler.js +243 -259
  9. package/{src/display → pdfjs/dist}/network.js +149 -87
  10. package/{src/display/content_disposition.js → pdfjs/dist/network_utils.js} +167 -55
  11. package/{src/display → pdfjs/dist}/node_stream.js +133 -98
  12. package/pdfjs/dist/pdf.js +12778 -0
  13. package/pdfjs/dist/pdf_link_service.js +638 -0
  14. package/pdfjs/dist/pdf_rendering_queue.js +199 -0
  15. package/pdfjs/dist/pdf_thumbnail_viewer.js +819 -0
  16. package/pdfjs/dist/pdf_viewer.js +3598 -0
  17. package/pdfjs/dist/typeof.js +100 -0
  18. package/pdfjs/dist/ui_utils.js +1033 -0
  19. package/{src/shared → pdfjs/dist}/util.js +301 -287
  20. package/pdfjs/dist/worker.js +62813 -0
  21. package/src/vcf-pdf-viewer.js +77 -27
  22. package/theme/lumo/vcf-pdf-viewer-styles.js +1 -1
  23. package/theme/material/vcf-pdf-viewer.js +2 -2
  24. package/src/core/.eslintrc +0 -13
  25. package/src/core/annotation.js +0 -2948
  26. package/src/core/arithmetic_decoder.js +0 -182
  27. package/src/core/ascii_85_stream.js +0 -98
  28. package/src/core/ascii_hex_stream.js +0 -79
  29. package/src/core/base_stream.js +0 -110
  30. package/src/core/bidi.js +0 -438
  31. package/src/core/calibri_factors.js +0 -308
  32. package/src/core/catalog.js +0 -1459
  33. package/src/core/ccitt.js +0 -1062
  34. package/src/core/ccitt_stream.js +0 -60
  35. package/src/core/cff_font.js +0 -116
  36. package/src/core/cff_parser.js +0 -1949
  37. package/src/core/charsets.js +0 -119
  38. package/src/core/chunked_stream.js +0 -557
  39. package/src/core/cmap.js +0 -1039
  40. package/src/core/colorspace.js +0 -1533
  41. package/src/core/core_utils.js +0 -464
  42. package/src/core/crypto.js +0 -1900
  43. package/src/core/decode_stream.js +0 -170
  44. package/src/core/decrypt_stream.js +0 -59
  45. package/src/core/default_appearance.js +0 -99
  46. package/src/core/document.js +0 -1456
  47. package/src/core/encodings.js +0 -301
  48. package/src/core/evaluator.js +0 -4601
  49. package/src/core/file_spec.js +0 -108
  50. package/src/core/flate_stream.js +0 -402
  51. package/src/core/font_renderer.js +0 -882
  52. package/src/core/fonts.js +0 -3260
  53. package/src/core/fonts_utils.js +0 -221
  54. package/src/core/function.js +0 -1257
  55. package/src/core/glyf.js +0 -706
  56. package/src/core/glyphlist.js +0 -4558
  57. package/src/core/helvetica_factors.js +0 -353
  58. package/src/core/image.js +0 -802
  59. package/src/core/image_utils.js +0 -291
  60. package/src/core/jbig2.js +0 -2572
  61. package/src/core/jbig2_stream.js +0 -73
  62. package/src/core/jpeg_stream.js +0 -105
  63. package/src/core/jpg.js +0 -1416
  64. package/src/core/jpx.js +0 -2343
  65. package/src/core/jpx_stream.js +0 -87
  66. package/src/core/liberationsans_widths.js +0 -221
  67. package/src/core/lzw_stream.js +0 -150
  68. package/src/core/metadata_parser.js +0 -146
  69. package/src/core/metrics.js +0 -2970
  70. package/src/core/murmurhash3.js +0 -139
  71. package/src/core/myriadpro_factors.js +0 -290
  72. package/src/core/name_number_tree.js +0 -153
  73. package/src/core/object_loader.js +0 -149
  74. package/src/core/opentype_file_builder.js +0 -154
  75. package/src/core/operator_list.js +0 -734
  76. package/src/core/parser.js +0 -1416
  77. package/src/core/pattern.js +0 -985
  78. package/src/core/pdf_manager.js +0 -217
  79. package/src/core/predictor_stream.js +0 -238
  80. package/src/core/primitives.js +0 -402
  81. package/src/core/ps_parser.js +0 -272
  82. package/src/core/run_length_stream.js +0 -61
  83. package/src/core/segoeui_factors.js +0 -308
  84. package/src/core/standard_fonts.js +0 -817
  85. package/src/core/stream.js +0 -103
  86. package/src/core/struct_tree.js +0 -335
  87. package/src/core/to_unicode_map.js +0 -103
  88. package/src/core/type1_font.js +0 -421
  89. package/src/core/type1_parser.js +0 -776
  90. package/src/core/unicode.js +0 -1649
  91. package/src/core/worker.js +0 -848
  92. package/src/core/worker_stream.js +0 -135
  93. package/src/core/writer.js +0 -278
  94. package/src/core/xfa/bind.js +0 -652
  95. package/src/core/xfa/builder.js +0 -207
  96. package/src/core/xfa/config.js +0 -1926
  97. package/src/core/xfa/connection_set.js +0 -202
  98. package/src/core/xfa/data.js +0 -82
  99. package/src/core/xfa/datasets.js +0 -76
  100. package/src/core/xfa/factory.js +0 -111
  101. package/src/core/xfa/fonts.js +0 -181
  102. package/src/core/xfa/formcalc_lexer.js +0 -385
  103. package/src/core/xfa/formcalc_parser.js +0 -1340
  104. package/src/core/xfa/html_utils.js +0 -639
  105. package/src/core/xfa/layout.js +0 -383
  106. package/src/core/xfa/locale_set.js +0 -345
  107. package/src/core/xfa/namespaces.js +0 -81
  108. package/src/core/xfa/parser.js +0 -184
  109. package/src/core/xfa/setup.js +0 -38
  110. package/src/core/xfa/signature.js +0 -40
  111. package/src/core/xfa/som.js +0 -338
  112. package/src/core/xfa/stylesheet.js +0 -40
  113. package/src/core/xfa/template.js +0 -6260
  114. package/src/core/xfa/text.js +0 -290
  115. package/src/core/xfa/unknown.js +0 -29
  116. package/src/core/xfa/utils.js +0 -217
  117. package/src/core/xfa/xdp.js +0 -59
  118. package/src/core/xfa/xfa_object.js +0 -1130
  119. package/src/core/xfa/xhtml.js +0 -543
  120. package/src/core/xfa_fonts.js +0 -208
  121. package/src/core/xml_parser.js +0 -507
  122. package/src/core/xref.js +0 -899
  123. package/src/display/annotation_layer.js +0 -2107
  124. package/src/display/annotation_storage.js +0 -113
  125. package/src/display/api.js +0 -3292
  126. package/src/display/base_factory.js +0 -180
  127. package/src/display/canvas.js +0 -2828
  128. package/src/display/font_loader.js +0 -484
  129. package/src/display/metadata.js +0 -41
  130. package/src/display/network_utils.js +0 -100
  131. package/src/display/node_utils.js +0 -83
  132. package/src/display/optional_content_config.js +0 -189
  133. package/src/display/pattern_helper.js +0 -659
  134. package/src/display/svg.js +0 -1709
  135. package/src/display/text_layer.js +0 -847
  136. package/src/display/transport_stream.js +0 -303
  137. package/src/display/worker_options.js +0 -40
  138. package/src/display/xfa_layer.js +0 -204
  139. package/src/doc_helper.js +0 -25
  140. package/src/images/logo.svg +0 -41
  141. package/src/interfaces.js +0 -169
  142. package/src/license_header.js +0 -14
  143. package/src/license_header_libre.js +0 -21
  144. package/src/pdf.image_decoders.js +0 -46
  145. package/src/pdf.js +0 -146
  146. package/src/pdf.sandbox.external.js +0 -181
  147. package/src/pdf.sandbox.js +0 -151
  148. package/src/pdf.scripting.js +0 -25
  149. package/src/pdf.worker.entry.js +0 -19
  150. package/src/pdf.worker.js +0 -23
  151. package/src/scripting_api/aform.js +0 -608
  152. package/src/scripting_api/app.js +0 -621
  153. package/src/scripting_api/color.js +0 -129
  154. package/src/scripting_api/common.js +0 -58
  155. package/src/scripting_api/console.js +0 -38
  156. package/src/scripting_api/constants.js +0 -208
  157. package/src/scripting_api/doc.js +0 -1195
  158. package/src/scripting_api/error.js +0 -23
  159. package/src/scripting_api/event.js +0 -232
  160. package/src/scripting_api/field.js +0 -620
  161. package/src/scripting_api/fullscreen.js +0 -145
  162. package/src/scripting_api/initialization.js +0 -223
  163. package/src/scripting_api/pdf_object.js +0 -24
  164. package/src/scripting_api/print_params.js +0 -146
  165. package/src/scripting_api/proxy.js +0 -139
  166. package/src/scripting_api/thermometer.js +0 -69
  167. package/src/scripting_api/util.js +0 -581
  168. package/src/shared/.eslintrc +0 -13
  169. package/src/shared/cffStandardStrings.js +0 -311
  170. package/src/shared/compatibility.js +0 -114
  171. package/src/shared/fonts_utils.js +0 -429
  172. package/src/shared/is_node.js +0 -27
  173. package/src/shared/scripting_utils.js +0 -85
  174. package/src/worker_loader.js +0 -32
package/src/core/jpx.js DELETED
@@ -1,2343 +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, info, unreachable, warn } from "../shared/util.js";
17
- import { log2, readUint16, readUint32 } from "./core_utils.js";
18
- import { ArithmeticDecoder } from "./arithmetic_decoder.js";
19
-
20
- class JpxError extends BaseException {
21
- constructor(msg) {
22
- super(`JPX error: ${msg}`);
23
- }
24
- }
25
-
26
- // Table E.1
27
- const SubbandsGainLog2 = {
28
- LL: 0,
29
- LH: 1,
30
- HL: 1,
31
- HH: 2,
32
- };
33
-
34
- class JpxImage {
35
- constructor() {
36
- this.failOnCorruptedImage = false;
37
- }
38
-
39
- parse(data) {
40
- const head = readUint16(data, 0);
41
- // No box header, immediate start of codestream (SOC)
42
- if (head === 0xff4f) {
43
- this.parseCodestream(data, 0, data.length);
44
- return;
45
- }
46
-
47
- const length = data.length;
48
- let position = 0;
49
- while (position < length) {
50
- let headerSize = 8;
51
- let lbox = readUint32(data, position);
52
- const tbox = readUint32(data, position + 4);
53
- position += headerSize;
54
- if (lbox === 1) {
55
- // XLBox: read UInt64 according to spec.
56
- // JavaScript's int precision of 53 bit should be sufficient here.
57
- lbox =
58
- readUint32(data, position) * 4294967296 +
59
- readUint32(data, position + 4);
60
- position += 8;
61
- headerSize += 8;
62
- }
63
- if (lbox === 0) {
64
- lbox = length - position + headerSize;
65
- }
66
- if (lbox < headerSize) {
67
- throw new JpxError("Invalid box field size");
68
- }
69
- const dataLength = lbox - headerSize;
70
- let jumpDataLength = true;
71
- switch (tbox) {
72
- case 0x6a703268: // 'jp2h'
73
- jumpDataLength = false; // parsing child boxes
74
- break;
75
- case 0x636f6c72: // 'colr'
76
- // Colorspaces are not used, the CS from the PDF is used.
77
- const method = data[position];
78
- if (method === 1) {
79
- // enumerated colorspace
80
- const colorspace = readUint32(data, position + 3);
81
- switch (colorspace) {
82
- case 16: // this indicates a sRGB colorspace
83
- case 17: // this indicates a grayscale colorspace
84
- case 18: // this indicates a YUV colorspace
85
- break;
86
- default:
87
- warn("Unknown colorspace " + colorspace);
88
- break;
89
- }
90
- } else if (method === 2) {
91
- info("ICC profile not supported");
92
- }
93
- break;
94
- case 0x6a703263: // 'jp2c'
95
- this.parseCodestream(data, position, position + dataLength);
96
- break;
97
- case 0x6a502020: // 'jP\024\024'
98
- if (readUint32(data, position) !== 0x0d0a870a) {
99
- warn("Invalid JP2 signature");
100
- }
101
- break;
102
- // The following header types are valid but currently not used:
103
- case 0x6a501a1a: // 'jP\032\032'
104
- case 0x66747970: // 'ftyp'
105
- case 0x72726571: // 'rreq'
106
- case 0x72657320: // 'res '
107
- case 0x69686472: // 'ihdr'
108
- break;
109
- default:
110
- const headerType = String.fromCharCode(
111
- (tbox >> 24) & 0xff,
112
- (tbox >> 16) & 0xff,
113
- (tbox >> 8) & 0xff,
114
- tbox & 0xff
115
- );
116
- warn(`Unsupported header type ${tbox} (${headerType}).`);
117
- break;
118
- }
119
- if (jumpDataLength) {
120
- position += dataLength;
121
- }
122
- }
123
- }
124
-
125
- parseImageProperties(stream) {
126
- let newByte = stream.getByte();
127
- while (newByte >= 0) {
128
- const oldByte = newByte;
129
- newByte = stream.getByte();
130
- const code = (oldByte << 8) | newByte;
131
- // Image and tile size (SIZ)
132
- if (code === 0xff51) {
133
- stream.skip(4);
134
- const Xsiz = stream.getInt32() >>> 0; // Byte 4
135
- const Ysiz = stream.getInt32() >>> 0; // Byte 8
136
- const XOsiz = stream.getInt32() >>> 0; // Byte 12
137
- const YOsiz = stream.getInt32() >>> 0; // Byte 16
138
- stream.skip(16);
139
- const Csiz = stream.getUint16(); // Byte 36
140
- this.width = Xsiz - XOsiz;
141
- this.height = Ysiz - YOsiz;
142
- this.componentsCount = Csiz;
143
- // Results are always returned as `Uint8ClampedArray`s.
144
- this.bitsPerComponent = 8;
145
- return;
146
- }
147
- }
148
- throw new JpxError("No size marker found in JPX stream");
149
- }
150
-
151
- parseCodestream(data, start, end) {
152
- const context = {};
153
- let doNotRecover = false;
154
- try {
155
- let position = start;
156
- while (position + 1 < end) {
157
- const code = readUint16(data, position);
158
- position += 2;
159
-
160
- let length = 0,
161
- j,
162
- sqcd,
163
- spqcds,
164
- spqcdSize,
165
- scalarExpounded,
166
- tile;
167
- switch (code) {
168
- case 0xff4f: // Start of codestream (SOC)
169
- context.mainHeader = true;
170
- break;
171
- case 0xffd9: // End of codestream (EOC)
172
- break;
173
- case 0xff51: // Image and tile size (SIZ)
174
- length = readUint16(data, position);
175
- const siz = {};
176
- siz.Xsiz = readUint32(data, position + 4);
177
- siz.Ysiz = readUint32(data, position + 8);
178
- siz.XOsiz = readUint32(data, position + 12);
179
- siz.YOsiz = readUint32(data, position + 16);
180
- siz.XTsiz = readUint32(data, position + 20);
181
- siz.YTsiz = readUint32(data, position + 24);
182
- siz.XTOsiz = readUint32(data, position + 28);
183
- siz.YTOsiz = readUint32(data, position + 32);
184
- const componentsCount = readUint16(data, position + 36);
185
- siz.Csiz = componentsCount;
186
- const components = [];
187
- j = position + 38;
188
- for (let i = 0; i < componentsCount; i++) {
189
- const component = {
190
- precision: (data[j] & 0x7f) + 1,
191
- isSigned: !!(data[j] & 0x80),
192
- XRsiz: data[j + 1],
193
- YRsiz: data[j + 2],
194
- };
195
- j += 3;
196
- calculateComponentDimensions(component, siz);
197
- components.push(component);
198
- }
199
- context.SIZ = siz;
200
- context.components = components;
201
- calculateTileGrids(context, components);
202
- context.QCC = [];
203
- context.COC = [];
204
- break;
205
- case 0xff5c: // Quantization default (QCD)
206
- length = readUint16(data, position);
207
- const qcd = {};
208
- j = position + 2;
209
- sqcd = data[j++];
210
- switch (sqcd & 0x1f) {
211
- case 0:
212
- spqcdSize = 8;
213
- scalarExpounded = true;
214
- break;
215
- case 1:
216
- spqcdSize = 16;
217
- scalarExpounded = false;
218
- break;
219
- case 2:
220
- spqcdSize = 16;
221
- scalarExpounded = true;
222
- break;
223
- default:
224
- throw new Error("Invalid SQcd value " + sqcd);
225
- }
226
- qcd.noQuantization = spqcdSize === 8;
227
- qcd.scalarExpounded = scalarExpounded;
228
- qcd.guardBits = sqcd >> 5;
229
- spqcds = [];
230
- while (j < length + position) {
231
- const spqcd = {};
232
- if (spqcdSize === 8) {
233
- spqcd.epsilon = data[j++] >> 3;
234
- spqcd.mu = 0;
235
- } else {
236
- spqcd.epsilon = data[j] >> 3;
237
- spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
238
- j += 2;
239
- }
240
- spqcds.push(spqcd);
241
- }
242
- qcd.SPqcds = spqcds;
243
- if (context.mainHeader) {
244
- context.QCD = qcd;
245
- } else {
246
- context.currentTile.QCD = qcd;
247
- context.currentTile.QCC = [];
248
- }
249
- break;
250
- case 0xff5d: // Quantization component (QCC)
251
- length = readUint16(data, position);
252
- const qcc = {};
253
- j = position + 2;
254
- let cqcc;
255
- if (context.SIZ.Csiz < 257) {
256
- cqcc = data[j++];
257
- } else {
258
- cqcc = readUint16(data, j);
259
- j += 2;
260
- }
261
- sqcd = data[j++];
262
- switch (sqcd & 0x1f) {
263
- case 0:
264
- spqcdSize = 8;
265
- scalarExpounded = true;
266
- break;
267
- case 1:
268
- spqcdSize = 16;
269
- scalarExpounded = false;
270
- break;
271
- case 2:
272
- spqcdSize = 16;
273
- scalarExpounded = true;
274
- break;
275
- default:
276
- throw new Error("Invalid SQcd value " + sqcd);
277
- }
278
- qcc.noQuantization = spqcdSize === 8;
279
- qcc.scalarExpounded = scalarExpounded;
280
- qcc.guardBits = sqcd >> 5;
281
- spqcds = [];
282
- while (j < length + position) {
283
- const spqcd = {};
284
- if (spqcdSize === 8) {
285
- spqcd.epsilon = data[j++] >> 3;
286
- spqcd.mu = 0;
287
- } else {
288
- spqcd.epsilon = data[j] >> 3;
289
- spqcd.mu = ((data[j] & 0x7) << 8) | data[j + 1];
290
- j += 2;
291
- }
292
- spqcds.push(spqcd);
293
- }
294
- qcc.SPqcds = spqcds;
295
- if (context.mainHeader) {
296
- context.QCC[cqcc] = qcc;
297
- } else {
298
- context.currentTile.QCC[cqcc] = qcc;
299
- }
300
- break;
301
- case 0xff52: // Coding style default (COD)
302
- length = readUint16(data, position);
303
- const cod = {};
304
- j = position + 2;
305
- const scod = data[j++];
306
- cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
307
- cod.sopMarkerUsed = !!(scod & 2);
308
- cod.ephMarkerUsed = !!(scod & 4);
309
- cod.progressionOrder = data[j++];
310
- cod.layersCount = readUint16(data, j);
311
- j += 2;
312
- cod.multipleComponentTransform = data[j++];
313
-
314
- cod.decompositionLevelsCount = data[j++];
315
- cod.xcb = (data[j++] & 0xf) + 2;
316
- cod.ycb = (data[j++] & 0xf) + 2;
317
- const blockStyle = data[j++];
318
- cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
319
- cod.resetContextProbabilities = !!(blockStyle & 2);
320
- cod.terminationOnEachCodingPass = !!(blockStyle & 4);
321
- cod.verticallyStripe = !!(blockStyle & 8);
322
- cod.predictableTermination = !!(blockStyle & 16);
323
- cod.segmentationSymbolUsed = !!(blockStyle & 32);
324
- cod.reversibleTransformation = data[j++];
325
- if (cod.entropyCoderWithCustomPrecincts) {
326
- const precinctsSizes = [];
327
- while (j < length + position) {
328
- const precinctsSize = data[j++];
329
- precinctsSizes.push({
330
- PPx: precinctsSize & 0xf,
331
- PPy: precinctsSize >> 4,
332
- });
333
- }
334
- cod.precinctsSizes = precinctsSizes;
335
- }
336
- const unsupported = [];
337
- if (cod.selectiveArithmeticCodingBypass) {
338
- unsupported.push("selectiveArithmeticCodingBypass");
339
- }
340
- if (cod.resetContextProbabilities) {
341
- unsupported.push("resetContextProbabilities");
342
- }
343
- if (cod.terminationOnEachCodingPass) {
344
- unsupported.push("terminationOnEachCodingPass");
345
- }
346
- if (cod.verticallyStripe) {
347
- unsupported.push("verticallyStripe");
348
- }
349
- if (cod.predictableTermination) {
350
- unsupported.push("predictableTermination");
351
- }
352
- if (unsupported.length > 0) {
353
- doNotRecover = true;
354
- warn(`JPX: Unsupported COD options (${unsupported.join(", ")}).`);
355
- }
356
- if (context.mainHeader) {
357
- context.COD = cod;
358
- } else {
359
- context.currentTile.COD = cod;
360
- context.currentTile.COC = [];
361
- }
362
- break;
363
- case 0xff90: // Start of tile-part (SOT)
364
- length = readUint16(data, position);
365
- tile = {};
366
- tile.index = readUint16(data, position + 2);
367
- tile.length = readUint32(data, position + 4);
368
- tile.dataEnd = tile.length + position - 2;
369
- tile.partIndex = data[position + 8];
370
- tile.partsCount = data[position + 9];
371
-
372
- context.mainHeader = false;
373
- if (tile.partIndex === 0) {
374
- // reset component specific settings
375
- tile.COD = context.COD;
376
- tile.COC = context.COC.slice(0); // clone of the global COC
377
- tile.QCD = context.QCD;
378
- tile.QCC = context.QCC.slice(0); // clone of the global COC
379
- }
380
- context.currentTile = tile;
381
- break;
382
- case 0xff93: // Start of data (SOD)
383
- tile = context.currentTile;
384
- if (tile.partIndex === 0) {
385
- initializeTile(context, tile.index);
386
- buildPackets(context);
387
- }
388
-
389
- // moving to the end of the data
390
- length = tile.dataEnd - position;
391
- parseTilePackets(context, data, position, length);
392
- break;
393
- case 0xff53: // Coding style component (COC)
394
- warn("JPX: Codestream code 0xFF53 (COC) is not implemented.");
395
- /* falls through */
396
- case 0xff55: // Tile-part lengths, main header (TLM)
397
- case 0xff57: // Packet length, main header (PLM)
398
- case 0xff58: // Packet length, tile-part header (PLT)
399
- case 0xff64: // Comment (COM)
400
- length = readUint16(data, position);
401
- // skipping content
402
- break;
403
- default:
404
- throw new Error("Unknown codestream code: " + code.toString(16));
405
- }
406
- position += length;
407
- }
408
- } catch (e) {
409
- if (doNotRecover || this.failOnCorruptedImage) {
410
- throw new JpxError(e.message);
411
- } else {
412
- warn(`JPX: Trying to recover from: "${e.message}".`);
413
- }
414
- }
415
- this.tiles = transformComponents(context);
416
- this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
417
- this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
418
- this.componentsCount = context.SIZ.Csiz;
419
- }
420
- }
421
-
422
- function calculateComponentDimensions(component, siz) {
423
- // Section B.2 Component mapping
424
- component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
425
- component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
426
- component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
427
- component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
428
- component.width = component.x1 - component.x0;
429
- component.height = component.y1 - component.y0;
430
- }
431
- function calculateTileGrids(context, components) {
432
- const siz = context.SIZ;
433
- // Section B.3 Division into tile and tile-components
434
- const tiles = [];
435
- let tile;
436
- const numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
437
- const numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
438
- for (let q = 0; q < numYtiles; q++) {
439
- for (let p = 0; p < numXtiles; p++) {
440
- tile = {};
441
- tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
442
- tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
443
- tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
444
- tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
445
- tile.width = tile.tx1 - tile.tx0;
446
- tile.height = tile.ty1 - tile.ty0;
447
- tile.components = [];
448
- tiles.push(tile);
449
- }
450
- }
451
- context.tiles = tiles;
452
-
453
- const componentsCount = siz.Csiz;
454
- for (let i = 0, ii = componentsCount; i < ii; i++) {
455
- const component = components[i];
456
- for (let j = 0, jj = tiles.length; j < jj; j++) {
457
- const tileComponent = {};
458
- tile = tiles[j];
459
- tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
460
- tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
461
- tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
462
- tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
463
- tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
464
- tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
465
- tile.components[i] = tileComponent;
466
- }
467
- }
468
- }
469
- function getBlocksDimensions(context, component, r) {
470
- const codOrCoc = component.codingStyleParameters;
471
- const result = {};
472
- if (!codOrCoc.entropyCoderWithCustomPrecincts) {
473
- result.PPx = 15;
474
- result.PPy = 15;
475
- } else {
476
- result.PPx = codOrCoc.precinctsSizes[r].PPx;
477
- result.PPy = codOrCoc.precinctsSizes[r].PPy;
478
- }
479
- // calculate codeblock size as described in section B.7
480
- result.xcb_ =
481
- r > 0
482
- ? Math.min(codOrCoc.xcb, result.PPx - 1)
483
- : Math.min(codOrCoc.xcb, result.PPx);
484
- result.ycb_ =
485
- r > 0
486
- ? Math.min(codOrCoc.ycb, result.PPy - 1)
487
- : Math.min(codOrCoc.ycb, result.PPy);
488
- return result;
489
- }
490
- function buildPrecincts(context, resolution, dimensions) {
491
- // Section B.6 Division resolution to precincts
492
- const precinctWidth = 1 << dimensions.PPx;
493
- const precinctHeight = 1 << dimensions.PPy;
494
- // Jasper introduces codeblock groups for mapping each subband codeblocks
495
- // to precincts. Precinct partition divides a resolution according to width
496
- // and height parameters. The subband that belongs to the resolution level
497
- // has a different size than the level, unless it is the zero resolution.
498
-
499
- // From Jasper documentation: jpeg2000.pdf, section K: Tier-2 coding:
500
- // The precinct partitioning for a particular subband is derived from a
501
- // partitioning of its parent LL band (i.e., the LL band at the next higher
502
- // resolution level)... The LL band associated with each resolution level is
503
- // divided into precincts... Each of the resulting precinct regions is then
504
- // mapped into its child subbands (if any) at the next lower resolution
505
- // level. This is accomplished by using the coordinate transformation
506
- // (u, v) = (ceil(x/2), ceil(y/2)) where (x, y) and (u, v) are the
507
- // coordinates of a point in the LL band and child subband, respectively.
508
- const isZeroRes = resolution.resLevel === 0;
509
- const precinctWidthInSubband = 1 << (dimensions.PPx + (isZeroRes ? 0 : -1));
510
- const precinctHeightInSubband = 1 << (dimensions.PPy + (isZeroRes ? 0 : -1));
511
- const numprecinctswide =
512
- resolution.trx1 > resolution.trx0
513
- ? Math.ceil(resolution.trx1 / precinctWidth) -
514
- Math.floor(resolution.trx0 / precinctWidth)
515
- : 0;
516
- const numprecinctshigh =
517
- resolution.try1 > resolution.try0
518
- ? Math.ceil(resolution.try1 / precinctHeight) -
519
- Math.floor(resolution.try0 / precinctHeight)
520
- : 0;
521
- const numprecincts = numprecinctswide * numprecinctshigh;
522
-
523
- resolution.precinctParameters = {
524
- precinctWidth,
525
- precinctHeight,
526
- numprecinctswide,
527
- numprecinctshigh,
528
- numprecincts,
529
- precinctWidthInSubband,
530
- precinctHeightInSubband,
531
- };
532
- }
533
- function buildCodeblocks(context, subband, dimensions) {
534
- // Section B.7 Division sub-band into code-blocks
535
- const xcb_ = dimensions.xcb_;
536
- const ycb_ = dimensions.ycb_;
537
- const codeblockWidth = 1 << xcb_;
538
- const codeblockHeight = 1 << ycb_;
539
- const cbx0 = subband.tbx0 >> xcb_;
540
- const cby0 = subband.tby0 >> ycb_;
541
- const cbx1 = (subband.tbx1 + codeblockWidth - 1) >> xcb_;
542
- const cby1 = (subband.tby1 + codeblockHeight - 1) >> ycb_;
543
- const precinctParameters = subband.resolution.precinctParameters;
544
- const codeblocks = [];
545
- const precincts = [];
546
- let i, j, codeblock, precinctNumber;
547
- for (j = cby0; j < cby1; j++) {
548
- for (i = cbx0; i < cbx1; i++) {
549
- codeblock = {
550
- cbx: i,
551
- cby: j,
552
- tbx0: codeblockWidth * i,
553
- tby0: codeblockHeight * j,
554
- tbx1: codeblockWidth * (i + 1),
555
- tby1: codeblockHeight * (j + 1),
556
- };
557
-
558
- codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
559
- codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
560
- codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
561
- codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
562
-
563
- // Calculate precinct number for this codeblock, codeblock position
564
- // should be relative to its subband, use actual dimension and position
565
- // See comment about codeblock group width and height
566
- const pi = Math.floor(
567
- (codeblock.tbx0_ - subband.tbx0) /
568
- precinctParameters.precinctWidthInSubband
569
- );
570
- const pj = Math.floor(
571
- (codeblock.tby0_ - subband.tby0) /
572
- precinctParameters.precinctHeightInSubband
573
- );
574
- precinctNumber = pi + pj * precinctParameters.numprecinctswide;
575
-
576
- codeblock.precinctNumber = precinctNumber;
577
- codeblock.subbandType = subband.type;
578
- codeblock.Lblock = 3;
579
-
580
- if (
581
- codeblock.tbx1_ <= codeblock.tbx0_ ||
582
- codeblock.tby1_ <= codeblock.tby0_
583
- ) {
584
- continue;
585
- }
586
- codeblocks.push(codeblock);
587
- // building precinct for the sub-band
588
- let precinct = precincts[precinctNumber];
589
- if (precinct !== undefined) {
590
- if (i < precinct.cbxMin) {
591
- precinct.cbxMin = i;
592
- } else if (i > precinct.cbxMax) {
593
- precinct.cbxMax = i;
594
- }
595
- if (j < precinct.cbyMin) {
596
- precinct.cbxMin = j;
597
- } else if (j > precinct.cbyMax) {
598
- precinct.cbyMax = j;
599
- }
600
- } else {
601
- precincts[precinctNumber] = precinct = {
602
- cbxMin: i,
603
- cbyMin: j,
604
- cbxMax: i,
605
- cbyMax: j,
606
- };
607
- }
608
- codeblock.precinct = precinct;
609
- }
610
- }
611
- subband.codeblockParameters = {
612
- codeblockWidth: xcb_,
613
- codeblockHeight: ycb_,
614
- numcodeblockwide: cbx1 - cbx0 + 1,
615
- numcodeblockhigh: cby1 - cby0 + 1,
616
- };
617
- subband.codeblocks = codeblocks;
618
- subband.precincts = precincts;
619
- }
620
- function createPacket(resolution, precinctNumber, layerNumber) {
621
- const precinctCodeblocks = [];
622
- // Section B.10.8 Order of info in packet
623
- const subbands = resolution.subbands;
624
- // sub-bands already ordered in 'LL', 'HL', 'LH', and 'HH' sequence
625
- for (let i = 0, ii = subbands.length; i < ii; i++) {
626
- const subband = subbands[i];
627
- const codeblocks = subband.codeblocks;
628
- for (let j = 0, jj = codeblocks.length; j < jj; j++) {
629
- const codeblock = codeblocks[j];
630
- if (codeblock.precinctNumber !== precinctNumber) {
631
- continue;
632
- }
633
- precinctCodeblocks.push(codeblock);
634
- }
635
- }
636
- return {
637
- layerNumber,
638
- codeblocks: precinctCodeblocks,
639
- };
640
- }
641
- function LayerResolutionComponentPositionIterator(context) {
642
- const siz = context.SIZ;
643
- const tileIndex = context.currentTile.index;
644
- const tile = context.tiles[tileIndex];
645
- const layersCount = tile.codingStyleDefaultParameters.layersCount;
646
- const componentsCount = siz.Csiz;
647
- let maxDecompositionLevelsCount = 0;
648
- for (let q = 0; q < componentsCount; q++) {
649
- maxDecompositionLevelsCount = Math.max(
650
- maxDecompositionLevelsCount,
651
- tile.components[q].codingStyleParameters.decompositionLevelsCount
652
- );
653
- }
654
-
655
- let l = 0,
656
- r = 0,
657
- i = 0,
658
- k = 0;
659
-
660
- this.nextPacket = function JpxImage_nextPacket() {
661
- // Section B.12.1.1 Layer-resolution-component-position
662
- for (; l < layersCount; l++) {
663
- for (; r <= maxDecompositionLevelsCount; r++) {
664
- for (; i < componentsCount; i++) {
665
- const component = tile.components[i];
666
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
667
- continue;
668
- }
669
-
670
- const resolution = component.resolutions[r];
671
- const numprecincts = resolution.precinctParameters.numprecincts;
672
- for (; k < numprecincts; ) {
673
- const packet = createPacket(resolution, k, l);
674
- k++;
675
- return packet;
676
- }
677
- k = 0;
678
- }
679
- i = 0;
680
- }
681
- r = 0;
682
- }
683
- throw new JpxError("Out of packets");
684
- };
685
- }
686
- function ResolutionLayerComponentPositionIterator(context) {
687
- const siz = context.SIZ;
688
- const tileIndex = context.currentTile.index;
689
- const tile = context.tiles[tileIndex];
690
- const layersCount = tile.codingStyleDefaultParameters.layersCount;
691
- const componentsCount = siz.Csiz;
692
- let maxDecompositionLevelsCount = 0;
693
- for (let q = 0; q < componentsCount; q++) {
694
- maxDecompositionLevelsCount = Math.max(
695
- maxDecompositionLevelsCount,
696
- tile.components[q].codingStyleParameters.decompositionLevelsCount
697
- );
698
- }
699
-
700
- let r = 0,
701
- l = 0,
702
- i = 0,
703
- k = 0;
704
-
705
- this.nextPacket = function JpxImage_nextPacket() {
706
- // Section B.12.1.2 Resolution-layer-component-position
707
- for (; r <= maxDecompositionLevelsCount; r++) {
708
- for (; l < layersCount; l++) {
709
- for (; i < componentsCount; i++) {
710
- const component = tile.components[i];
711
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
712
- continue;
713
- }
714
-
715
- const resolution = component.resolutions[r];
716
- const numprecincts = resolution.precinctParameters.numprecincts;
717
- for (; k < numprecincts; ) {
718
- const packet = createPacket(resolution, k, l);
719
- k++;
720
- return packet;
721
- }
722
- k = 0;
723
- }
724
- i = 0;
725
- }
726
- l = 0;
727
- }
728
- throw new JpxError("Out of packets");
729
- };
730
- }
731
- function ResolutionPositionComponentLayerIterator(context) {
732
- const siz = context.SIZ;
733
- const tileIndex = context.currentTile.index;
734
- const tile = context.tiles[tileIndex];
735
- const layersCount = tile.codingStyleDefaultParameters.layersCount;
736
- const componentsCount = siz.Csiz;
737
- let l, r, c, p;
738
- let maxDecompositionLevelsCount = 0;
739
- for (c = 0; c < componentsCount; c++) {
740
- const component = tile.components[c];
741
- maxDecompositionLevelsCount = Math.max(
742
- maxDecompositionLevelsCount,
743
- component.codingStyleParameters.decompositionLevelsCount
744
- );
745
- }
746
- const maxNumPrecinctsInLevel = new Int32Array(
747
- maxDecompositionLevelsCount + 1
748
- );
749
- for (r = 0; r <= maxDecompositionLevelsCount; ++r) {
750
- let maxNumPrecincts = 0;
751
- for (c = 0; c < componentsCount; ++c) {
752
- const resolutions = tile.components[c].resolutions;
753
- if (r < resolutions.length) {
754
- maxNumPrecincts = Math.max(
755
- maxNumPrecincts,
756
- resolutions[r].precinctParameters.numprecincts
757
- );
758
- }
759
- }
760
- maxNumPrecinctsInLevel[r] = maxNumPrecincts;
761
- }
762
- l = 0;
763
- r = 0;
764
- c = 0;
765
- p = 0;
766
-
767
- this.nextPacket = function JpxImage_nextPacket() {
768
- // Section B.12.1.3 Resolution-position-component-layer
769
- for (; r <= maxDecompositionLevelsCount; r++) {
770
- for (; p < maxNumPrecinctsInLevel[r]; p++) {
771
- for (; c < componentsCount; c++) {
772
- const component = tile.components[c];
773
- if (r > component.codingStyleParameters.decompositionLevelsCount) {
774
- continue;
775
- }
776
- const resolution = component.resolutions[r];
777
- const numprecincts = resolution.precinctParameters.numprecincts;
778
- if (p >= numprecincts) {
779
- continue;
780
- }
781
- for (; l < layersCount; ) {
782
- const packet = createPacket(resolution, p, l);
783
- l++;
784
- return packet;
785
- }
786
- l = 0;
787
- }
788
- c = 0;
789
- }
790
- p = 0;
791
- }
792
- throw new JpxError("Out of packets");
793
- };
794
- }
795
- function PositionComponentResolutionLayerIterator(context) {
796
- const siz = context.SIZ;
797
- const tileIndex = context.currentTile.index;
798
- const tile = context.tiles[tileIndex];
799
- const layersCount = tile.codingStyleDefaultParameters.layersCount;
800
- const componentsCount = siz.Csiz;
801
- const precinctsSizes = getPrecinctSizesInImageScale(tile);
802
- const precinctsIterationSizes = precinctsSizes;
803
- let l = 0,
804
- r = 0,
805
- c = 0,
806
- px = 0,
807
- py = 0;
808
-
809
- this.nextPacket = function JpxImage_nextPacket() {
810
- // Section B.12.1.4 Position-component-resolution-layer
811
- for (; py < precinctsIterationSizes.maxNumHigh; py++) {
812
- for (; px < precinctsIterationSizes.maxNumWide; px++) {
813
- for (; c < componentsCount; c++) {
814
- const component = tile.components[c];
815
- const decompositionLevelsCount =
816
- component.codingStyleParameters.decompositionLevelsCount;
817
- for (; r <= decompositionLevelsCount; r++) {
818
- const resolution = component.resolutions[r];
819
- const sizeInImageScale =
820
- precinctsSizes.components[c].resolutions[r];
821
- const k = getPrecinctIndexIfExist(
822
- px,
823
- py,
824
- sizeInImageScale,
825
- precinctsIterationSizes,
826
- resolution
827
- );
828
- if (k === null) {
829
- continue;
830
- }
831
- for (; l < layersCount; ) {
832
- const packet = createPacket(resolution, k, l);
833
- l++;
834
- return packet;
835
- }
836
- l = 0;
837
- }
838
- r = 0;
839
- }
840
- c = 0;
841
- }
842
- px = 0;
843
- }
844
- throw new JpxError("Out of packets");
845
- };
846
- }
847
- function ComponentPositionResolutionLayerIterator(context) {
848
- const siz = context.SIZ;
849
- const tileIndex = context.currentTile.index;
850
- const tile = context.tiles[tileIndex];
851
- const layersCount = tile.codingStyleDefaultParameters.layersCount;
852
- const componentsCount = siz.Csiz;
853
- const precinctsSizes = getPrecinctSizesInImageScale(tile);
854
- let l = 0,
855
- r = 0,
856
- c = 0,
857
- px = 0,
858
- py = 0;
859
-
860
- this.nextPacket = function JpxImage_nextPacket() {
861
- // Section B.12.1.5 Component-position-resolution-layer
862
- for (; c < componentsCount; ++c) {
863
- const component = tile.components[c];
864
- const precinctsIterationSizes = precinctsSizes.components[c];
865
- const decompositionLevelsCount =
866
- component.codingStyleParameters.decompositionLevelsCount;
867
- for (; py < precinctsIterationSizes.maxNumHigh; py++) {
868
- for (; px < precinctsIterationSizes.maxNumWide; px++) {
869
- for (; r <= decompositionLevelsCount; r++) {
870
- const resolution = component.resolutions[r];
871
- const sizeInImageScale = precinctsIterationSizes.resolutions[r];
872
- const k = getPrecinctIndexIfExist(
873
- px,
874
- py,
875
- sizeInImageScale,
876
- precinctsIterationSizes,
877
- resolution
878
- );
879
- if (k === null) {
880
- continue;
881
- }
882
- for (; l < layersCount; ) {
883
- const packet = createPacket(resolution, k, l);
884
- l++;
885
- return packet;
886
- }
887
- l = 0;
888
- }
889
- r = 0;
890
- }
891
- px = 0;
892
- }
893
- py = 0;
894
- }
895
- throw new JpxError("Out of packets");
896
- };
897
- }
898
- function getPrecinctIndexIfExist(
899
- pxIndex,
900
- pyIndex,
901
- sizeInImageScale,
902
- precinctIterationSizes,
903
- resolution
904
- ) {
905
- const posX = pxIndex * precinctIterationSizes.minWidth;
906
- const posY = pyIndex * precinctIterationSizes.minHeight;
907
- if (
908
- posX % sizeInImageScale.width !== 0 ||
909
- posY % sizeInImageScale.height !== 0
910
- ) {
911
- return null;
912
- }
913
- const startPrecinctRowIndex =
914
- (posY / sizeInImageScale.width) *
915
- resolution.precinctParameters.numprecinctswide;
916
- return posX / sizeInImageScale.height + startPrecinctRowIndex;
917
- }
918
- function getPrecinctSizesInImageScale(tile) {
919
- const componentsCount = tile.components.length;
920
- let minWidth = Number.MAX_VALUE;
921
- let minHeight = Number.MAX_VALUE;
922
- let maxNumWide = 0;
923
- let maxNumHigh = 0;
924
- const sizePerComponent = new Array(componentsCount);
925
- for (let c = 0; c < componentsCount; c++) {
926
- const component = tile.components[c];
927
- const decompositionLevelsCount =
928
- component.codingStyleParameters.decompositionLevelsCount;
929
- const sizePerResolution = new Array(decompositionLevelsCount + 1);
930
- let minWidthCurrentComponent = Number.MAX_VALUE;
931
- let minHeightCurrentComponent = Number.MAX_VALUE;
932
- let maxNumWideCurrentComponent = 0;
933
- let maxNumHighCurrentComponent = 0;
934
- let scale = 1;
935
- for (let r = decompositionLevelsCount; r >= 0; --r) {
936
- const resolution = component.resolutions[r];
937
- const widthCurrentResolution =
938
- scale * resolution.precinctParameters.precinctWidth;
939
- const heightCurrentResolution =
940
- scale * resolution.precinctParameters.precinctHeight;
941
- minWidthCurrentComponent = Math.min(
942
- minWidthCurrentComponent,
943
- widthCurrentResolution
944
- );
945
- minHeightCurrentComponent = Math.min(
946
- minHeightCurrentComponent,
947
- heightCurrentResolution
948
- );
949
- maxNumWideCurrentComponent = Math.max(
950
- maxNumWideCurrentComponent,
951
- resolution.precinctParameters.numprecinctswide
952
- );
953
- maxNumHighCurrentComponent = Math.max(
954
- maxNumHighCurrentComponent,
955
- resolution.precinctParameters.numprecinctshigh
956
- );
957
- sizePerResolution[r] = {
958
- width: widthCurrentResolution,
959
- height: heightCurrentResolution,
960
- };
961
- scale <<= 1;
962
- }
963
- minWidth = Math.min(minWidth, minWidthCurrentComponent);
964
- minHeight = Math.min(minHeight, minHeightCurrentComponent);
965
- maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent);
966
- maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent);
967
- sizePerComponent[c] = {
968
- resolutions: sizePerResolution,
969
- minWidth: minWidthCurrentComponent,
970
- minHeight: minHeightCurrentComponent,
971
- maxNumWide: maxNumWideCurrentComponent,
972
- maxNumHigh: maxNumHighCurrentComponent,
973
- };
974
- }
975
- return {
976
- components: sizePerComponent,
977
- minWidth,
978
- minHeight,
979
- maxNumWide,
980
- maxNumHigh,
981
- };
982
- }
983
- function buildPackets(context) {
984
- const siz = context.SIZ;
985
- const tileIndex = context.currentTile.index;
986
- const tile = context.tiles[tileIndex];
987
- const componentsCount = siz.Csiz;
988
- // Creating resolutions and sub-bands for each component
989
- for (let c = 0; c < componentsCount; c++) {
990
- const component = tile.components[c];
991
- const decompositionLevelsCount =
992
- component.codingStyleParameters.decompositionLevelsCount;
993
- // Section B.5 Resolution levels and sub-bands
994
- const resolutions = [];
995
- const subbands = [];
996
- for (let r = 0; r <= decompositionLevelsCount; r++) {
997
- const blocksDimensions = getBlocksDimensions(context, component, r);
998
- const resolution = {};
999
- const scale = 1 << (decompositionLevelsCount - r);
1000
- resolution.trx0 = Math.ceil(component.tcx0 / scale);
1001
- resolution.try0 = Math.ceil(component.tcy0 / scale);
1002
- resolution.trx1 = Math.ceil(component.tcx1 / scale);
1003
- resolution.try1 = Math.ceil(component.tcy1 / scale);
1004
- resolution.resLevel = r;
1005
- buildPrecincts(context, resolution, blocksDimensions);
1006
- resolutions.push(resolution);
1007
-
1008
- let subband;
1009
- if (r === 0) {
1010
- // one sub-band (LL) with last decomposition
1011
- subband = {};
1012
- subband.type = "LL";
1013
- subband.tbx0 = Math.ceil(component.tcx0 / scale);
1014
- subband.tby0 = Math.ceil(component.tcy0 / scale);
1015
- subband.tbx1 = Math.ceil(component.tcx1 / scale);
1016
- subband.tby1 = Math.ceil(component.tcy1 / scale);
1017
- subband.resolution = resolution;
1018
- buildCodeblocks(context, subband, blocksDimensions);
1019
- subbands.push(subband);
1020
- resolution.subbands = [subband];
1021
- } else {
1022
- const bscale = 1 << (decompositionLevelsCount - r + 1);
1023
- const resolutionSubbands = [];
1024
- // three sub-bands (HL, LH and HH) with rest of decompositions
1025
- subband = {};
1026
- subband.type = "HL";
1027
- subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
1028
- subband.tby0 = Math.ceil(component.tcy0 / bscale);
1029
- subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
1030
- subband.tby1 = Math.ceil(component.tcy1 / bscale);
1031
- subband.resolution = resolution;
1032
- buildCodeblocks(context, subband, blocksDimensions);
1033
- subbands.push(subband);
1034
- resolutionSubbands.push(subband);
1035
-
1036
- subband = {};
1037
- subband.type = "LH";
1038
- subband.tbx0 = Math.ceil(component.tcx0 / bscale);
1039
- subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
1040
- subband.tbx1 = Math.ceil(component.tcx1 / bscale);
1041
- subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
1042
- subband.resolution = resolution;
1043
- buildCodeblocks(context, subband, blocksDimensions);
1044
- subbands.push(subband);
1045
- resolutionSubbands.push(subband);
1046
-
1047
- subband = {};
1048
- subband.type = "HH";
1049
- subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
1050
- subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
1051
- subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
1052
- subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
1053
- subband.resolution = resolution;
1054
- buildCodeblocks(context, subband, blocksDimensions);
1055
- subbands.push(subband);
1056
- resolutionSubbands.push(subband);
1057
-
1058
- resolution.subbands = resolutionSubbands;
1059
- }
1060
- }
1061
- component.resolutions = resolutions;
1062
- component.subbands = subbands;
1063
- }
1064
- // Generate the packets sequence
1065
- const progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
1066
- switch (progressionOrder) {
1067
- case 0:
1068
- tile.packetsIterator = new LayerResolutionComponentPositionIterator(
1069
- context
1070
- );
1071
- break;
1072
- case 1:
1073
- tile.packetsIterator = new ResolutionLayerComponentPositionIterator(
1074
- context
1075
- );
1076
- break;
1077
- case 2:
1078
- tile.packetsIterator = new ResolutionPositionComponentLayerIterator(
1079
- context
1080
- );
1081
- break;
1082
- case 3:
1083
- tile.packetsIterator = new PositionComponentResolutionLayerIterator(
1084
- context
1085
- );
1086
- break;
1087
- case 4:
1088
- tile.packetsIterator = new ComponentPositionResolutionLayerIterator(
1089
- context
1090
- );
1091
- break;
1092
- default:
1093
- throw new JpxError(`Unsupported progression order ${progressionOrder}`);
1094
- }
1095
- }
1096
- function parseTilePackets(context, data, offset, dataLength) {
1097
- let position = 0;
1098
- let buffer,
1099
- bufferSize = 0,
1100
- skipNextBit = false;
1101
- function readBits(count) {
1102
- while (bufferSize < count) {
1103
- const b = data[offset + position];
1104
- position++;
1105
- if (skipNextBit) {
1106
- buffer = (buffer << 7) | b;
1107
- bufferSize += 7;
1108
- skipNextBit = false;
1109
- } else {
1110
- buffer = (buffer << 8) | b;
1111
- bufferSize += 8;
1112
- }
1113
- if (b === 0xff) {
1114
- skipNextBit = true;
1115
- }
1116
- }
1117
- bufferSize -= count;
1118
- return (buffer >>> bufferSize) & ((1 << count) - 1);
1119
- }
1120
- function skipMarkerIfEqual(value) {
1121
- if (
1122
- data[offset + position - 1] === 0xff &&
1123
- data[offset + position] === value
1124
- ) {
1125
- skipBytes(1);
1126
- return true;
1127
- } else if (
1128
- data[offset + position] === 0xff &&
1129
- data[offset + position + 1] === value
1130
- ) {
1131
- skipBytes(2);
1132
- return true;
1133
- }
1134
- return false;
1135
- }
1136
- function skipBytes(count) {
1137
- position += count;
1138
- }
1139
- function alignToByte() {
1140
- bufferSize = 0;
1141
- if (skipNextBit) {
1142
- position++;
1143
- skipNextBit = false;
1144
- }
1145
- }
1146
- function readCodingpasses() {
1147
- if (readBits(1) === 0) {
1148
- return 1;
1149
- }
1150
- if (readBits(1) === 0) {
1151
- return 2;
1152
- }
1153
- let value = readBits(2);
1154
- if (value < 3) {
1155
- return value + 3;
1156
- }
1157
- value = readBits(5);
1158
- if (value < 31) {
1159
- return value + 6;
1160
- }
1161
- value = readBits(7);
1162
- return value + 37;
1163
- }
1164
- const tileIndex = context.currentTile.index;
1165
- const tile = context.tiles[tileIndex];
1166
- const sopMarkerUsed = context.COD.sopMarkerUsed;
1167
- const ephMarkerUsed = context.COD.ephMarkerUsed;
1168
- const packetsIterator = tile.packetsIterator;
1169
- while (position < dataLength) {
1170
- alignToByte();
1171
- if (sopMarkerUsed && skipMarkerIfEqual(0x91)) {
1172
- // Skip also marker segment length and packet sequence ID
1173
- skipBytes(4);
1174
- }
1175
- const packet = packetsIterator.nextPacket();
1176
- if (!readBits(1)) {
1177
- continue;
1178
- }
1179
- const layerNumber = packet.layerNumber,
1180
- queue = [];
1181
- let codeblock;
1182
- for (let i = 0, ii = packet.codeblocks.length; i < ii; i++) {
1183
- codeblock = packet.codeblocks[i];
1184
- let precinct = codeblock.precinct;
1185
- const codeblockColumn = codeblock.cbx - precinct.cbxMin;
1186
- const codeblockRow = codeblock.cby - precinct.cbyMin;
1187
- let codeblockIncluded = false;
1188
- let firstTimeInclusion = false;
1189
- let valueReady, zeroBitPlanesTree;
1190
- if (codeblock.included !== undefined) {
1191
- codeblockIncluded = !!readBits(1);
1192
- } else {
1193
- // reading inclusion tree
1194
- precinct = codeblock.precinct;
1195
- let inclusionTree;
1196
- if (precinct.inclusionTree !== undefined) {
1197
- inclusionTree = precinct.inclusionTree;
1198
- } else {
1199
- // building inclusion and zero bit-planes trees
1200
- const width = precinct.cbxMax - precinct.cbxMin + 1;
1201
- const height = precinct.cbyMax - precinct.cbyMin + 1;
1202
- inclusionTree = new InclusionTree(width, height, layerNumber);
1203
- zeroBitPlanesTree = new TagTree(width, height);
1204
- precinct.inclusionTree = inclusionTree;
1205
- precinct.zeroBitPlanesTree = zeroBitPlanesTree;
1206
- }
1207
-
1208
- if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
1209
- while (true) {
1210
- if (readBits(1)) {
1211
- valueReady = !inclusionTree.nextLevel();
1212
- if (valueReady) {
1213
- codeblock.included = true;
1214
- codeblockIncluded = firstTimeInclusion = true;
1215
- break;
1216
- }
1217
- } else {
1218
- inclusionTree.incrementValue(layerNumber);
1219
- break;
1220
- }
1221
- }
1222
- }
1223
- }
1224
- if (!codeblockIncluded) {
1225
- continue;
1226
- }
1227
- if (firstTimeInclusion) {
1228
- zeroBitPlanesTree = precinct.zeroBitPlanesTree;
1229
- zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
1230
- while (true) {
1231
- if (readBits(1)) {
1232
- valueReady = !zeroBitPlanesTree.nextLevel();
1233
- if (valueReady) {
1234
- break;
1235
- }
1236
- } else {
1237
- zeroBitPlanesTree.incrementValue();
1238
- }
1239
- }
1240
- codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
1241
- }
1242
- const codingpasses = readCodingpasses();
1243
- while (readBits(1)) {
1244
- codeblock.Lblock++;
1245
- }
1246
- const codingpassesLog2 = log2(codingpasses);
1247
- // rounding down log2
1248
- const bits =
1249
- (codingpasses < 1 << codingpassesLog2
1250
- ? codingpassesLog2 - 1
1251
- : codingpassesLog2) + codeblock.Lblock;
1252
- const codedDataLength = readBits(bits);
1253
- queue.push({
1254
- codeblock,
1255
- codingpasses,
1256
- dataLength: codedDataLength,
1257
- });
1258
- }
1259
- alignToByte();
1260
- if (ephMarkerUsed) {
1261
- skipMarkerIfEqual(0x92);
1262
- }
1263
- while (queue.length > 0) {
1264
- const packetItem = queue.shift();
1265
- codeblock = packetItem.codeblock;
1266
- if (codeblock.data === undefined) {
1267
- codeblock.data = [];
1268
- }
1269
- codeblock.data.push({
1270
- data,
1271
- start: offset + position,
1272
- end: offset + position + packetItem.dataLength,
1273
- codingpasses: packetItem.codingpasses,
1274
- });
1275
- position += packetItem.dataLength;
1276
- }
1277
- }
1278
- return position;
1279
- }
1280
- function copyCoefficients(
1281
- coefficients,
1282
- levelWidth,
1283
- levelHeight,
1284
- subband,
1285
- delta,
1286
- mb,
1287
- reversible,
1288
- segmentationSymbolUsed
1289
- ) {
1290
- const x0 = subband.tbx0;
1291
- const y0 = subband.tby0;
1292
- const width = subband.tbx1 - subband.tbx0;
1293
- const codeblocks = subband.codeblocks;
1294
- const right = subband.type.charAt(0) === "H" ? 1 : 0;
1295
- const bottom = subband.type.charAt(1) === "H" ? levelWidth : 0;
1296
-
1297
- for (let i = 0, ii = codeblocks.length; i < ii; ++i) {
1298
- const codeblock = codeblocks[i];
1299
- const blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
1300
- const blockHeight = codeblock.tby1_ - codeblock.tby0_;
1301
- if (blockWidth === 0 || blockHeight === 0) {
1302
- continue;
1303
- }
1304
- if (codeblock.data === undefined) {
1305
- continue;
1306
- }
1307
-
1308
- const bitModel = new BitModel(
1309
- blockWidth,
1310
- blockHeight,
1311
- codeblock.subbandType,
1312
- codeblock.zeroBitPlanes,
1313
- mb
1314
- );
1315
- let currentCodingpassType = 2; // first bit plane starts from cleanup
1316
-
1317
- // collect data
1318
- const data = codeblock.data;
1319
- let totalLength = 0,
1320
- codingpasses = 0;
1321
- let j, jj, dataItem;
1322
- for (j = 0, jj = data.length; j < jj; j++) {
1323
- dataItem = data[j];
1324
- totalLength += dataItem.end - dataItem.start;
1325
- codingpasses += dataItem.codingpasses;
1326
- }
1327
- const encodedData = new Uint8Array(totalLength);
1328
- let position = 0;
1329
- for (j = 0, jj = data.length; j < jj; j++) {
1330
- dataItem = data[j];
1331
- const chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
1332
- encodedData.set(chunk, position);
1333
- position += chunk.length;
1334
- }
1335
- // decoding the item
1336
- const decoder = new ArithmeticDecoder(encodedData, 0, totalLength);
1337
- bitModel.setDecoder(decoder);
1338
-
1339
- for (j = 0; j < codingpasses; j++) {
1340
- switch (currentCodingpassType) {
1341
- case 0:
1342
- bitModel.runSignificancePropagationPass();
1343
- break;
1344
- case 1:
1345
- bitModel.runMagnitudeRefinementPass();
1346
- break;
1347
- case 2:
1348
- bitModel.runCleanupPass();
1349
- if (segmentationSymbolUsed) {
1350
- bitModel.checkSegmentationSymbol();
1351
- }
1352
- break;
1353
- }
1354
- currentCodingpassType = (currentCodingpassType + 1) % 3;
1355
- }
1356
-
1357
- let offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width;
1358
- const sign = bitModel.coefficentsSign;
1359
- const magnitude = bitModel.coefficentsMagnitude;
1360
- const bitsDecoded = bitModel.bitsDecoded;
1361
- const magnitudeCorrection = reversible ? 0 : 0.5;
1362
- let k, n, nb;
1363
- position = 0;
1364
- // Do the interleaving of Section F.3.3 here, so we do not need
1365
- // to copy later. LL level is not interleaved, just copied.
1366
- const interleave = subband.type !== "LL";
1367
- for (j = 0; j < blockHeight; j++) {
1368
- const row = (offset / width) | 0; // row in the non-interleaved subband
1369
- const levelOffset = 2 * row * (levelWidth - width) + right + bottom;
1370
- for (k = 0; k < blockWidth; k++) {
1371
- n = magnitude[position];
1372
- if (n !== 0) {
1373
- n = (n + magnitudeCorrection) * delta;
1374
- if (sign[position] !== 0) {
1375
- n = -n;
1376
- }
1377
- nb = bitsDecoded[position];
1378
- const pos = interleave ? levelOffset + (offset << 1) : offset;
1379
- if (reversible && nb >= mb) {
1380
- coefficients[pos] = n;
1381
- } else {
1382
- coefficients[pos] = n * (1 << (mb - nb));
1383
- }
1384
- }
1385
- offset++;
1386
- position++;
1387
- }
1388
- offset += width - blockWidth;
1389
- }
1390
- }
1391
- }
1392
- function transformTile(context, tile, c) {
1393
- const component = tile.components[c];
1394
- const codingStyleParameters = component.codingStyleParameters;
1395
- const quantizationParameters = component.quantizationParameters;
1396
- const decompositionLevelsCount =
1397
- codingStyleParameters.decompositionLevelsCount;
1398
- const spqcds = quantizationParameters.SPqcds;
1399
- const scalarExpounded = quantizationParameters.scalarExpounded;
1400
- const guardBits = quantizationParameters.guardBits;
1401
- const segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
1402
- const precision = context.components[c].precision;
1403
-
1404
- const reversible = codingStyleParameters.reversibleTransformation;
1405
- const transform = reversible
1406
- ? new ReversibleTransform()
1407
- : new IrreversibleTransform();
1408
-
1409
- const subbandCoefficients = [];
1410
- let b = 0;
1411
- for (let i = 0; i <= decompositionLevelsCount; i++) {
1412
- const resolution = component.resolutions[i];
1413
-
1414
- const width = resolution.trx1 - resolution.trx0;
1415
- const height = resolution.try1 - resolution.try0;
1416
- // Allocate space for the whole sublevel.
1417
- const coefficients = new Float32Array(width * height);
1418
-
1419
- for (let j = 0, jj = resolution.subbands.length; j < jj; j++) {
1420
- let mu, epsilon;
1421
- if (!scalarExpounded) {
1422
- // formula E-5
1423
- mu = spqcds[0].mu;
1424
- epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
1425
- } else {
1426
- mu = spqcds[b].mu;
1427
- epsilon = spqcds[b].epsilon;
1428
- b++;
1429
- }
1430
-
1431
- const subband = resolution.subbands[j];
1432
- const gainLog2 = SubbandsGainLog2[subband.type];
1433
-
1434
- // calculate quantization coefficient (Section E.1.1.1)
1435
- const delta = reversible
1436
- ? 1
1437
- : 2 ** (precision + gainLog2 - epsilon) * (1 + mu / 2048);
1438
- const mb = guardBits + epsilon - 1;
1439
-
1440
- // In the first resolution level, copyCoefficients will fill the
1441
- // whole array with coefficients. In the succeeding passes,
1442
- // copyCoefficients will consecutively fill in the values that belong
1443
- // to the interleaved positions of the HL, LH, and HH coefficients.
1444
- // The LL coefficients will then be interleaved in Transform.iterate().
1445
- copyCoefficients(
1446
- coefficients,
1447
- width,
1448
- height,
1449
- subband,
1450
- delta,
1451
- mb,
1452
- reversible,
1453
- segmentationSymbolUsed
1454
- );
1455
- }
1456
- subbandCoefficients.push({
1457
- width,
1458
- height,
1459
- items: coefficients,
1460
- });
1461
- }
1462
-
1463
- const result = transform.calculate(
1464
- subbandCoefficients,
1465
- component.tcx0,
1466
- component.tcy0
1467
- );
1468
- return {
1469
- left: component.tcx0,
1470
- top: component.tcy0,
1471
- width: result.width,
1472
- height: result.height,
1473
- items: result.items,
1474
- };
1475
- }
1476
- function transformComponents(context) {
1477
- const siz = context.SIZ;
1478
- const components = context.components;
1479
- const componentsCount = siz.Csiz;
1480
- const resultImages = [];
1481
- for (let i = 0, ii = context.tiles.length; i < ii; i++) {
1482
- const tile = context.tiles[i];
1483
- const transformedTiles = [];
1484
- for (let c = 0; c < componentsCount; c++) {
1485
- transformedTiles[c] = transformTile(context, tile, c);
1486
- }
1487
- const tile0 = transformedTiles[0];
1488
- const out = new Uint8ClampedArray(tile0.items.length * componentsCount);
1489
- const result = {
1490
- left: tile0.left,
1491
- top: tile0.top,
1492
- width: tile0.width,
1493
- height: tile0.height,
1494
- items: out,
1495
- };
1496
-
1497
- // Section G.2.2 Inverse multi component transform
1498
- let shift, offset;
1499
- let pos = 0,
1500
- j,
1501
- jj,
1502
- y0,
1503
- y1,
1504
- y2;
1505
- if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
1506
- const fourComponents = componentsCount === 4;
1507
- const y0items = transformedTiles[0].items;
1508
- const y1items = transformedTiles[1].items;
1509
- const y2items = transformedTiles[2].items;
1510
- const y3items = fourComponents ? transformedTiles[3].items : null;
1511
-
1512
- // HACK: The multiple component transform formulas below assume that
1513
- // all components have the same precision. With this in mind, we
1514
- // compute shift and offset only once.
1515
- shift = components[0].precision - 8;
1516
- offset = (128 << shift) + 0.5;
1517
-
1518
- const component0 = tile.components[0];
1519
- const alpha01 = componentsCount - 3;
1520
- jj = y0items.length;
1521
- if (!component0.codingStyleParameters.reversibleTransformation) {
1522
- // inverse irreversible multiple component transform
1523
- for (j = 0; j < jj; j++, pos += alpha01) {
1524
- y0 = y0items[j] + offset;
1525
- y1 = y1items[j];
1526
- y2 = y2items[j];
1527
- out[pos++] = (y0 + 1.402 * y2) >> shift;
1528
- out[pos++] = (y0 - 0.34413 * y1 - 0.71414 * y2) >> shift;
1529
- out[pos++] = (y0 + 1.772 * y1) >> shift;
1530
- }
1531
- } else {
1532
- // inverse reversible multiple component transform
1533
- for (j = 0; j < jj; j++, pos += alpha01) {
1534
- y0 = y0items[j] + offset;
1535
- y1 = y1items[j];
1536
- y2 = y2items[j];
1537
- const g = y0 - ((y2 + y1) >> 2);
1538
-
1539
- out[pos++] = (g + y2) >> shift;
1540
- out[pos++] = g >> shift;
1541
- out[pos++] = (g + y1) >> shift;
1542
- }
1543
- }
1544
- if (fourComponents) {
1545
- for (j = 0, pos = 3; j < jj; j++, pos += 4) {
1546
- out[pos] = (y3items[j] + offset) >> shift;
1547
- }
1548
- }
1549
- } else {
1550
- // no multi-component transform
1551
- for (let c = 0; c < componentsCount; c++) {
1552
- const items = transformedTiles[c].items;
1553
- shift = components[c].precision - 8;
1554
- offset = (128 << shift) + 0.5;
1555
- for (pos = c, j = 0, jj = items.length; j < jj; j++) {
1556
- out[pos] = (items[j] + offset) >> shift;
1557
- pos += componentsCount;
1558
- }
1559
- }
1560
- }
1561
- resultImages.push(result);
1562
- }
1563
- return resultImages;
1564
- }
1565
- function initializeTile(context, tileIndex) {
1566
- const siz = context.SIZ;
1567
- const componentsCount = siz.Csiz;
1568
- const tile = context.tiles[tileIndex];
1569
- for (let c = 0; c < componentsCount; c++) {
1570
- const component = tile.components[c];
1571
- const qcdOrQcc =
1572
- context.currentTile.QCC[c] !== undefined
1573
- ? context.currentTile.QCC[c]
1574
- : context.currentTile.QCD;
1575
- component.quantizationParameters = qcdOrQcc;
1576
- const codOrCoc =
1577
- context.currentTile.COC[c] !== undefined
1578
- ? context.currentTile.COC[c]
1579
- : context.currentTile.COD;
1580
- component.codingStyleParameters = codOrCoc;
1581
- }
1582
- tile.codingStyleDefaultParameters = context.currentTile.COD;
1583
- }
1584
-
1585
- // Section B.10.2 Tag trees
1586
- class TagTree {
1587
- constructor(width, height) {
1588
- const levelsLength = log2(Math.max(width, height)) + 1;
1589
- this.levels = [];
1590
- for (let i = 0; i < levelsLength; i++) {
1591
- const level = {
1592
- width,
1593
- height,
1594
- items: [],
1595
- };
1596
- this.levels.push(level);
1597
- width = Math.ceil(width / 2);
1598
- height = Math.ceil(height / 2);
1599
- }
1600
- }
1601
-
1602
- reset(i, j) {
1603
- let currentLevel = 0,
1604
- value = 0,
1605
- level;
1606
- while (currentLevel < this.levels.length) {
1607
- level = this.levels[currentLevel];
1608
- const index = i + j * level.width;
1609
- if (level.items[index] !== undefined) {
1610
- value = level.items[index];
1611
- break;
1612
- }
1613
- level.index = index;
1614
- i >>= 1;
1615
- j >>= 1;
1616
- currentLevel++;
1617
- }
1618
- currentLevel--;
1619
- level = this.levels[currentLevel];
1620
- level.items[level.index] = value;
1621
- this.currentLevel = currentLevel;
1622
- delete this.value;
1623
- }
1624
-
1625
- incrementValue() {
1626
- const level = this.levels[this.currentLevel];
1627
- level.items[level.index]++;
1628
- }
1629
-
1630
- nextLevel() {
1631
- let currentLevel = this.currentLevel;
1632
- let level = this.levels[currentLevel];
1633
- const value = level.items[level.index];
1634
- currentLevel--;
1635
- if (currentLevel < 0) {
1636
- this.value = value;
1637
- return false;
1638
- }
1639
-
1640
- this.currentLevel = currentLevel;
1641
- level = this.levels[currentLevel];
1642
- level.items[level.index] = value;
1643
- return true;
1644
- }
1645
- }
1646
-
1647
- class InclusionTree {
1648
- constructor(width, height, defaultValue) {
1649
- const levelsLength = log2(Math.max(width, height)) + 1;
1650
- this.levels = [];
1651
- for (let i = 0; i < levelsLength; i++) {
1652
- const items = new Uint8Array(width * height);
1653
- for (let j = 0, jj = items.length; j < jj; j++) {
1654
- items[j] = defaultValue;
1655
- }
1656
-
1657
- const level = {
1658
- width,
1659
- height,
1660
- items,
1661
- };
1662
- this.levels.push(level);
1663
-
1664
- width = Math.ceil(width / 2);
1665
- height = Math.ceil(height / 2);
1666
- }
1667
- }
1668
-
1669
- reset(i, j, stopValue) {
1670
- let currentLevel = 0;
1671
- while (currentLevel < this.levels.length) {
1672
- const level = this.levels[currentLevel];
1673
- const index = i + j * level.width;
1674
- level.index = index;
1675
- const value = level.items[index];
1676
-
1677
- if (value === 0xff) {
1678
- break;
1679
- }
1680
-
1681
- if (value > stopValue) {
1682
- this.currentLevel = currentLevel;
1683
- // already know about this one, propagating the value to top levels
1684
- this.propagateValues();
1685
- return false;
1686
- }
1687
-
1688
- i >>= 1;
1689
- j >>= 1;
1690
- currentLevel++;
1691
- }
1692
- this.currentLevel = currentLevel - 1;
1693
- return true;
1694
- }
1695
-
1696
- incrementValue(stopValue) {
1697
- const level = this.levels[this.currentLevel];
1698
- level.items[level.index] = stopValue + 1;
1699
- this.propagateValues();
1700
- }
1701
-
1702
- propagateValues() {
1703
- let levelIndex = this.currentLevel;
1704
- let level = this.levels[levelIndex];
1705
- const currentValue = level.items[level.index];
1706
- while (--levelIndex >= 0) {
1707
- level = this.levels[levelIndex];
1708
- level.items[level.index] = currentValue;
1709
- }
1710
- }
1711
-
1712
- nextLevel() {
1713
- let currentLevel = this.currentLevel;
1714
- let level = this.levels[currentLevel];
1715
- const value = level.items[level.index];
1716
- level.items[level.index] = 0xff;
1717
- currentLevel--;
1718
- if (currentLevel < 0) {
1719
- return false;
1720
- }
1721
-
1722
- this.currentLevel = currentLevel;
1723
- level = this.levels[currentLevel];
1724
- level.items[level.index] = value;
1725
- return true;
1726
- }
1727
- }
1728
-
1729
- // Section D. Coefficient bit modeling
1730
- const BitModel = (function BitModelClosure() {
1731
- const UNIFORM_CONTEXT = 17;
1732
- const RUNLENGTH_CONTEXT = 18;
1733
- // Table D-1
1734
- // The index is binary presentation: 0dddvvhh, ddd - sum of Di (0..4),
1735
- // vv - sum of Vi (0..2), and hh - sum of Hi (0..2)
1736
- const LLAndLHContextsLabel = new Uint8Array([
1737
- 0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4,
1738
- 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6,
1739
- 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8,
1740
- ]);
1741
- const HLContextLabel = new Uint8Array([
1742
- 0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8,
1743
- 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3,
1744
- 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8,
1745
- ]);
1746
- const HHContextLabel = new Uint8Array([
1747
- 0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5,
1748
- 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8,
1749
- 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8,
1750
- ]);
1751
-
1752
- // eslint-disable-next-line no-shadow
1753
- class BitModel {
1754
- constructor(width, height, subband, zeroBitPlanes, mb) {
1755
- this.width = width;
1756
- this.height = height;
1757
-
1758
- let contextLabelTable;
1759
- if (subband === "HH") {
1760
- contextLabelTable = HHContextLabel;
1761
- } else if (subband === "HL") {
1762
- contextLabelTable = HLContextLabel;
1763
- } else {
1764
- contextLabelTable = LLAndLHContextsLabel;
1765
- }
1766
- this.contextLabelTable = contextLabelTable;
1767
-
1768
- const coefficientCount = width * height;
1769
-
1770
- // coefficients outside the encoding region treated as insignificant
1771
- // add border state cells for significanceState
1772
- this.neighborsSignificance = new Uint8Array(coefficientCount);
1773
- this.coefficentsSign = new Uint8Array(coefficientCount);
1774
- let coefficentsMagnitude;
1775
- if (mb > 14) {
1776
- coefficentsMagnitude = new Uint32Array(coefficientCount);
1777
- } else if (mb > 6) {
1778
- coefficentsMagnitude = new Uint16Array(coefficientCount);
1779
- } else {
1780
- coefficentsMagnitude = new Uint8Array(coefficientCount);
1781
- }
1782
- this.coefficentsMagnitude = coefficentsMagnitude;
1783
- this.processingFlags = new Uint8Array(coefficientCount);
1784
-
1785
- const bitsDecoded = new Uint8Array(coefficientCount);
1786
- if (zeroBitPlanes !== 0) {
1787
- for (let i = 0; i < coefficientCount; i++) {
1788
- bitsDecoded[i] = zeroBitPlanes;
1789
- }
1790
- }
1791
- this.bitsDecoded = bitsDecoded;
1792
-
1793
- this.reset();
1794
- }
1795
-
1796
- setDecoder(decoder) {
1797
- this.decoder = decoder;
1798
- }
1799
-
1800
- reset() {
1801
- // We have 17 contexts that are accessed via context labels,
1802
- // plus the uniform and runlength context.
1803
- this.contexts = new Int8Array(19);
1804
-
1805
- // Contexts are packed into 1 byte:
1806
- // highest 7 bits carry the index, lowest bit carries mps
1807
- this.contexts[0] = (4 << 1) | 0;
1808
- this.contexts[UNIFORM_CONTEXT] = (46 << 1) | 0;
1809
- this.contexts[RUNLENGTH_CONTEXT] = (3 << 1) | 0;
1810
- }
1811
-
1812
- setNeighborsSignificance(row, column, index) {
1813
- const neighborsSignificance = this.neighborsSignificance;
1814
- const width = this.width,
1815
- height = this.height;
1816
- const left = column > 0;
1817
- const right = column + 1 < width;
1818
- let i;
1819
-
1820
- if (row > 0) {
1821
- i = index - width;
1822
- if (left) {
1823
- neighborsSignificance[i - 1] += 0x10;
1824
- }
1825
- if (right) {
1826
- neighborsSignificance[i + 1] += 0x10;
1827
- }
1828
- neighborsSignificance[i] += 0x04;
1829
- }
1830
-
1831
- if (row + 1 < height) {
1832
- i = index + width;
1833
- if (left) {
1834
- neighborsSignificance[i - 1] += 0x10;
1835
- }
1836
- if (right) {
1837
- neighborsSignificance[i + 1] += 0x10;
1838
- }
1839
- neighborsSignificance[i] += 0x04;
1840
- }
1841
-
1842
- if (left) {
1843
- neighborsSignificance[index - 1] += 0x01;
1844
- }
1845
- if (right) {
1846
- neighborsSignificance[index + 1] += 0x01;
1847
- }
1848
- neighborsSignificance[index] |= 0x80;
1849
- }
1850
-
1851
- runSignificancePropagationPass() {
1852
- const decoder = this.decoder;
1853
- const width = this.width,
1854
- height = this.height;
1855
- const coefficentsMagnitude = this.coefficentsMagnitude;
1856
- const coefficentsSign = this.coefficentsSign;
1857
- const neighborsSignificance = this.neighborsSignificance;
1858
- const processingFlags = this.processingFlags;
1859
- const contexts = this.contexts;
1860
- const labels = this.contextLabelTable;
1861
- const bitsDecoded = this.bitsDecoded;
1862
- const processedInverseMask = ~1;
1863
- const processedMask = 1;
1864
- const firstMagnitudeBitMask = 2;
1865
-
1866
- for (let i0 = 0; i0 < height; i0 += 4) {
1867
- for (let j = 0; j < width; j++) {
1868
- let index = i0 * width + j;
1869
- for (let i1 = 0; i1 < 4; i1++, index += width) {
1870
- const i = i0 + i1;
1871
- if (i >= height) {
1872
- break;
1873
- }
1874
- // clear processed flag first
1875
- processingFlags[index] &= processedInverseMask;
1876
-
1877
- if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
1878
- continue;
1879
- }
1880
-
1881
- const contextLabel = labels[neighborsSignificance[index]];
1882
- const decision = decoder.readBit(contexts, contextLabel);
1883
- if (decision) {
1884
- const sign = this.decodeSignBit(i, j, index);
1885
- coefficentsSign[index] = sign;
1886
- coefficentsMagnitude[index] = 1;
1887
- this.setNeighborsSignificance(i, j, index);
1888
- processingFlags[index] |= firstMagnitudeBitMask;
1889
- }
1890
- bitsDecoded[index]++;
1891
- processingFlags[index] |= processedMask;
1892
- }
1893
- }
1894
- }
1895
- }
1896
-
1897
- decodeSignBit(row, column, index) {
1898
- const width = this.width,
1899
- height = this.height;
1900
- const coefficentsMagnitude = this.coefficentsMagnitude;
1901
- const coefficentsSign = this.coefficentsSign;
1902
- let contribution, sign0, sign1, significance1;
1903
- let contextLabel, decoded;
1904
-
1905
- // calculate horizontal contribution
1906
- significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
1907
- if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
1908
- sign1 = coefficentsSign[index + 1];
1909
- if (significance1) {
1910
- sign0 = coefficentsSign[index - 1];
1911
- contribution = 1 - sign1 - sign0;
1912
- } else {
1913
- contribution = 1 - sign1 - sign1;
1914
- }
1915
- } else if (significance1) {
1916
- sign0 = coefficentsSign[index - 1];
1917
- contribution = 1 - sign0 - sign0;
1918
- } else {
1919
- contribution = 0;
1920
- }
1921
- const horizontalContribution = 3 * contribution;
1922
-
1923
- // calculate vertical contribution and combine with the horizontal
1924
- significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
1925
- if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
1926
- sign1 = coefficentsSign[index + width];
1927
- if (significance1) {
1928
- sign0 = coefficentsSign[index - width];
1929
- contribution = 1 - sign1 - sign0 + horizontalContribution;
1930
- } else {
1931
- contribution = 1 - sign1 - sign1 + horizontalContribution;
1932
- }
1933
- } else if (significance1) {
1934
- sign0 = coefficentsSign[index - width];
1935
- contribution = 1 - sign0 - sign0 + horizontalContribution;
1936
- } else {
1937
- contribution = horizontalContribution;
1938
- }
1939
-
1940
- if (contribution >= 0) {
1941
- contextLabel = 9 + contribution;
1942
- decoded = this.decoder.readBit(this.contexts, contextLabel);
1943
- } else {
1944
- contextLabel = 9 - contribution;
1945
- decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
1946
- }
1947
- return decoded;
1948
- }
1949
-
1950
- runMagnitudeRefinementPass() {
1951
- const decoder = this.decoder;
1952
- const width = this.width,
1953
- height = this.height;
1954
- const coefficentsMagnitude = this.coefficentsMagnitude;
1955
- const neighborsSignificance = this.neighborsSignificance;
1956
- const contexts = this.contexts;
1957
- const bitsDecoded = this.bitsDecoded;
1958
- const processingFlags = this.processingFlags;
1959
- const processedMask = 1;
1960
- const firstMagnitudeBitMask = 2;
1961
- const length = width * height;
1962
- const width4 = width * 4;
1963
-
1964
- for (let index0 = 0, indexNext; index0 < length; index0 = indexNext) {
1965
- indexNext = Math.min(length, index0 + width4);
1966
- for (let j = 0; j < width; j++) {
1967
- for (let index = index0 + j; index < indexNext; index += width) {
1968
- // significant but not those that have just become
1969
- if (
1970
- !coefficentsMagnitude[index] ||
1971
- (processingFlags[index] & processedMask) !== 0
1972
- ) {
1973
- continue;
1974
- }
1975
-
1976
- let contextLabel = 16;
1977
- if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
1978
- processingFlags[index] ^= firstMagnitudeBitMask;
1979
- // first refinement
1980
- const significance = neighborsSignificance[index] & 127;
1981
- contextLabel = significance === 0 ? 15 : 14;
1982
- }
1983
-
1984
- const bit = decoder.readBit(contexts, contextLabel);
1985
- coefficentsMagnitude[index] =
1986
- (coefficentsMagnitude[index] << 1) | bit;
1987
- bitsDecoded[index]++;
1988
- processingFlags[index] |= processedMask;
1989
- }
1990
- }
1991
- }
1992
- }
1993
-
1994
- runCleanupPass() {
1995
- const decoder = this.decoder;
1996
- const width = this.width,
1997
- height = this.height;
1998
- const neighborsSignificance = this.neighborsSignificance;
1999
- const coefficentsMagnitude = this.coefficentsMagnitude;
2000
- const coefficentsSign = this.coefficentsSign;
2001
- const contexts = this.contexts;
2002
- const labels = this.contextLabelTable;
2003
- const bitsDecoded = this.bitsDecoded;
2004
- const processingFlags = this.processingFlags;
2005
- const processedMask = 1;
2006
- const firstMagnitudeBitMask = 2;
2007
- const oneRowDown = width;
2008
- const twoRowsDown = width * 2;
2009
- const threeRowsDown = width * 3;
2010
- let iNext;
2011
- for (let i0 = 0; i0 < height; i0 = iNext) {
2012
- iNext = Math.min(i0 + 4, height);
2013
- const indexBase = i0 * width;
2014
- const checkAllEmpty = i0 + 3 < height;
2015
- for (let j = 0; j < width; j++) {
2016
- const index0 = indexBase + j;
2017
- // using the property: labels[neighborsSignificance[index]] === 0
2018
- // when neighborsSignificance[index] === 0
2019
- const allEmpty =
2020
- checkAllEmpty &&
2021
- processingFlags[index0] === 0 &&
2022
- processingFlags[index0 + oneRowDown] === 0 &&
2023
- processingFlags[index0 + twoRowsDown] === 0 &&
2024
- processingFlags[index0 + threeRowsDown] === 0 &&
2025
- neighborsSignificance[index0] === 0 &&
2026
- neighborsSignificance[index0 + oneRowDown] === 0 &&
2027
- neighborsSignificance[index0 + twoRowsDown] === 0 &&
2028
- neighborsSignificance[index0 + threeRowsDown] === 0;
2029
- let i1 = 0,
2030
- index = index0;
2031
- let i = i0,
2032
- sign;
2033
- if (allEmpty) {
2034
- const hasSignificantCoefficent = decoder.readBit(
2035
- contexts,
2036
- RUNLENGTH_CONTEXT
2037
- );
2038
- if (!hasSignificantCoefficent) {
2039
- bitsDecoded[index0]++;
2040
- bitsDecoded[index0 + oneRowDown]++;
2041
- bitsDecoded[index0 + twoRowsDown]++;
2042
- bitsDecoded[index0 + threeRowsDown]++;
2043
- continue; // next column
2044
- }
2045
- i1 =
2046
- (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
2047
- decoder.readBit(contexts, UNIFORM_CONTEXT);
2048
- if (i1 !== 0) {
2049
- i = i0 + i1;
2050
- index += i1 * width;
2051
- }
2052
-
2053
- sign = this.decodeSignBit(i, j, index);
2054
- coefficentsSign[index] = sign;
2055
- coefficentsMagnitude[index] = 1;
2056
- this.setNeighborsSignificance(i, j, index);
2057
- processingFlags[index] |= firstMagnitudeBitMask;
2058
-
2059
- index = index0;
2060
- for (let i2 = i0; i2 <= i; i2++, index += width) {
2061
- bitsDecoded[index]++;
2062
- }
2063
-
2064
- i1++;
2065
- }
2066
- for (i = i0 + i1; i < iNext; i++, index += width) {
2067
- if (
2068
- coefficentsMagnitude[index] ||
2069
- (processingFlags[index] & processedMask) !== 0
2070
- ) {
2071
- continue;
2072
- }
2073
-
2074
- const contextLabel = labels[neighborsSignificance[index]];
2075
- const decision = decoder.readBit(contexts, contextLabel);
2076
- if (decision === 1) {
2077
- sign = this.decodeSignBit(i, j, index);
2078
- coefficentsSign[index] = sign;
2079
- coefficentsMagnitude[index] = 1;
2080
- this.setNeighborsSignificance(i, j, index);
2081
- processingFlags[index] |= firstMagnitudeBitMask;
2082
- }
2083
- bitsDecoded[index]++;
2084
- }
2085
- }
2086
- }
2087
- }
2088
-
2089
- checkSegmentationSymbol() {
2090
- const decoder = this.decoder;
2091
- const contexts = this.contexts;
2092
- const symbol =
2093
- (decoder.readBit(contexts, UNIFORM_CONTEXT) << 3) |
2094
- (decoder.readBit(contexts, UNIFORM_CONTEXT) << 2) |
2095
- (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
2096
- decoder.readBit(contexts, UNIFORM_CONTEXT);
2097
- if (symbol !== 0xa) {
2098
- throw new JpxError("Invalid segmentation symbol");
2099
- }
2100
- }
2101
- }
2102
-
2103
- return BitModel;
2104
- })();
2105
-
2106
- // Section F, Discrete wavelet transformation
2107
- class Transform {
2108
- constructor() {
2109
- if (this.constructor === Transform) {
2110
- unreachable("Cannot initialize Transform.");
2111
- }
2112
- }
2113
-
2114
- calculate(subbands, u0, v0) {
2115
- let ll = subbands[0];
2116
- for (let i = 1, ii = subbands.length; i < ii; i++) {
2117
- ll = this.iterate(ll, subbands[i], u0, v0);
2118
- }
2119
- return ll;
2120
- }
2121
-
2122
- extend(buffer, offset, size) {
2123
- // Section F.3.7 extending... using max extension of 4
2124
- let i1 = offset - 1,
2125
- j1 = offset + 1;
2126
- let i2 = offset + size - 2,
2127
- j2 = offset + size;
2128
- buffer[i1--] = buffer[j1++];
2129
- buffer[j2++] = buffer[i2--];
2130
- buffer[i1--] = buffer[j1++];
2131
- buffer[j2++] = buffer[i2--];
2132
- buffer[i1--] = buffer[j1++];
2133
- buffer[j2++] = buffer[i2--];
2134
- buffer[i1] = buffer[j1];
2135
- buffer[j2] = buffer[i2];
2136
- }
2137
-
2138
- filter(x, offset, length) {
2139
- unreachable("Abstract method `filter` called");
2140
- }
2141
-
2142
- iterate(ll, hl_lh_hh, u0, v0) {
2143
- const llWidth = ll.width,
2144
- llHeight = ll.height;
2145
- let llItems = ll.items;
2146
- const width = hl_lh_hh.width;
2147
- const height = hl_lh_hh.height;
2148
- const items = hl_lh_hh.items;
2149
- let i, j, k, l, u, v;
2150
-
2151
- // Interleave LL according to Section F.3.3
2152
- for (k = 0, i = 0; i < llHeight; i++) {
2153
- l = i * 2 * width;
2154
- for (j = 0; j < llWidth; j++, k++, l += 2) {
2155
- items[l] = llItems[k];
2156
- }
2157
- }
2158
- // The LL band is not needed anymore.
2159
- llItems = ll.items = null;
2160
-
2161
- const bufferPadding = 4;
2162
- const rowBuffer = new Float32Array(width + 2 * bufferPadding);
2163
-
2164
- // Section F.3.4 HOR_SR
2165
- if (width === 1) {
2166
- // if width = 1, when u0 even keep items as is, when odd divide by 2
2167
- if ((u0 & 1) !== 0) {
2168
- for (v = 0, k = 0; v < height; v++, k += width) {
2169
- items[k] *= 0.5;
2170
- }
2171
- }
2172
- } else {
2173
- for (v = 0, k = 0; v < height; v++, k += width) {
2174
- rowBuffer.set(items.subarray(k, k + width), bufferPadding);
2175
-
2176
- this.extend(rowBuffer, bufferPadding, width);
2177
- this.filter(rowBuffer, bufferPadding, width);
2178
-
2179
- items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k);
2180
- }
2181
- }
2182
-
2183
- // Accesses to the items array can take long, because it may not fit into
2184
- // CPU cache and has to be fetched from main memory. Since subsequent
2185
- // accesses to the items array are not local when reading columns, we
2186
- // have a cache miss every time. To reduce cache misses, get up to
2187
- // 'numBuffers' items at a time and store them into the individual
2188
- // buffers. The colBuffers should be small enough to fit into CPU cache.
2189
- let numBuffers = 16;
2190
- const colBuffers = [];
2191
- for (i = 0; i < numBuffers; i++) {
2192
- colBuffers.push(new Float32Array(height + 2 * bufferPadding));
2193
- }
2194
- let b,
2195
- currentBuffer = 0;
2196
- ll = bufferPadding + height;
2197
-
2198
- // Section F.3.5 VER_SR
2199
- if (height === 1) {
2200
- // if height = 1, when v0 even keep items as is, when odd divide by 2
2201
- if ((v0 & 1) !== 0) {
2202
- for (u = 0; u < width; u++) {
2203
- items[u] *= 0.5;
2204
- }
2205
- }
2206
- } else {
2207
- for (u = 0; u < width; u++) {
2208
- // if we ran out of buffers, copy several image columns at once
2209
- if (currentBuffer === 0) {
2210
- numBuffers = Math.min(width - u, numBuffers);
2211
- for (k = u, l = bufferPadding; l < ll; k += width, l++) {
2212
- for (b = 0; b < numBuffers; b++) {
2213
- colBuffers[b][l] = items[k + b];
2214
- }
2215
- }
2216
- currentBuffer = numBuffers;
2217
- }
2218
-
2219
- currentBuffer--;
2220
- const buffer = colBuffers[currentBuffer];
2221
- this.extend(buffer, bufferPadding, height);
2222
- this.filter(buffer, bufferPadding, height);
2223
-
2224
- // If this is last buffer in this group of buffers, flush all buffers.
2225
- if (currentBuffer === 0) {
2226
- k = u - numBuffers + 1;
2227
- for (l = bufferPadding; l < ll; k += width, l++) {
2228
- for (b = 0; b < numBuffers; b++) {
2229
- items[k + b] = colBuffers[b][l];
2230
- }
2231
- }
2232
- }
2233
- }
2234
- }
2235
-
2236
- return { width, height, items };
2237
- }
2238
- }
2239
-
2240
- // Section 3.8.2 Irreversible 9-7 filter
2241
- class IrreversibleTransform extends Transform {
2242
- filter(x, offset, length) {
2243
- const len = length >> 1;
2244
- offset |= 0;
2245
- let j, n, current, next;
2246
-
2247
- const alpha = -1.586134342059924;
2248
- const beta = -0.052980118572961;
2249
- const gamma = 0.882911075530934;
2250
- const delta = 0.443506852043971;
2251
- const K = 1.230174104914001;
2252
- const K_ = 1 / K;
2253
-
2254
- // step 1 is combined with step 3
2255
-
2256
- // step 2
2257
- j = offset - 3;
2258
- for (n = len + 4; n--; j += 2) {
2259
- x[j] *= K_;
2260
- }
2261
-
2262
- // step 1 & 3
2263
- j = offset - 2;
2264
- current = delta * x[j - 1];
2265
- for (n = len + 3; n--; j += 2) {
2266
- next = delta * x[j + 1];
2267
- x[j] = K * x[j] - current - next;
2268
- if (n--) {
2269
- j += 2;
2270
- current = delta * x[j + 1];
2271
- x[j] = K * x[j] - current - next;
2272
- } else {
2273
- break;
2274
- }
2275
- }
2276
-
2277
- // step 4
2278
- j = offset - 1;
2279
- current = gamma * x[j - 1];
2280
- for (n = len + 2; n--; j += 2) {
2281
- next = gamma * x[j + 1];
2282
- x[j] -= current + next;
2283
- if (n--) {
2284
- j += 2;
2285
- current = gamma * x[j + 1];
2286
- x[j] -= current + next;
2287
- } else {
2288
- break;
2289
- }
2290
- }
2291
-
2292
- // step 5
2293
- j = offset;
2294
- current = beta * x[j - 1];
2295
- for (n = len + 1; n--; j += 2) {
2296
- next = beta * x[j + 1];
2297
- x[j] -= current + next;
2298
- if (n--) {
2299
- j += 2;
2300
- current = beta * x[j + 1];
2301
- x[j] -= current + next;
2302
- } else {
2303
- break;
2304
- }
2305
- }
2306
-
2307
- // step 6
2308
- if (len !== 0) {
2309
- j = offset + 1;
2310
- current = alpha * x[j - 1];
2311
- for (n = len; n--; j += 2) {
2312
- next = alpha * x[j + 1];
2313
- x[j] -= current + next;
2314
- if (n--) {
2315
- j += 2;
2316
- current = alpha * x[j + 1];
2317
- x[j] -= current + next;
2318
- } else {
2319
- break;
2320
- }
2321
- }
2322
- }
2323
- }
2324
- }
2325
-
2326
- // Section 3.8.1 Reversible 5-3 filter
2327
- class ReversibleTransform extends Transform {
2328
- filter(x, offset, length) {
2329
- const len = length >> 1;
2330
- offset |= 0;
2331
- let j, n;
2332
-
2333
- for (j = offset, n = len + 1; n--; j += 2) {
2334
- x[j] -= (x[j - 1] + x[j + 1] + 2) >> 2;
2335
- }
2336
-
2337
- for (j = offset + 1, n = len; n--; j += 2) {
2338
- x[j] += (x[j - 1] + x[j + 1]) >> 1;
2339
- }
2340
- }
2341
- }
2342
-
2343
- export { JpxImage };