Convert src/core/jbig2.js
to use standard classes
*Please note:* Ignoring whitespace-only changes is probably necessary in order to review this.
This commit is contained in:
parent
d59c9ab3ab
commit
0addf3a0d4
@ -24,39 +24,37 @@ class Jbig2Error extends BaseException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Jbig2Image = (function Jbig2ImageClosure() {
|
// Utility data structures
|
||||||
// Utility data structures
|
class ContextCache {
|
||||||
function ContextCache() {}
|
|
||||||
|
|
||||||
ContextCache.prototype = {
|
|
||||||
getContexts(id) {
|
getContexts(id) {
|
||||||
if (id in this) {
|
if (id in this) {
|
||||||
return this[id];
|
return this[id];
|
||||||
}
|
}
|
||||||
return (this[id] = new Int8Array(1 << 16));
|
return (this[id] = new Int8Array(1 << 16));
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function DecodingContext(data, start, end) {
|
class DecodingContext {
|
||||||
|
constructor(data, start, end) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
DecodingContext.prototype = {
|
|
||||||
get decoder() {
|
get decoder() {
|
||||||
const decoder = new ArithmeticDecoder(this.data, this.start, this.end);
|
const decoder = new ArithmeticDecoder(this.data, this.start, this.end);
|
||||||
return shadow(this, "decoder", decoder);
|
return shadow(this, "decoder", decoder);
|
||||||
},
|
}
|
||||||
|
|
||||||
get contextCache() {
|
get contextCache() {
|
||||||
const cache = new ContextCache();
|
const cache = new ContextCache();
|
||||||
return shadow(this, "contextCache", cache);
|
return shadow(this, "contextCache", cache);
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Annex A. Arithmetic Integer Decoding Procedure
|
// Annex A. Arithmetic Integer Decoding Procedure
|
||||||
// A.2 Procedure for decoding values
|
// A.2 Procedure for decoding values
|
||||||
function decodeInteger(contextCache, procedure, decoder) {
|
function decodeInteger(contextCache, procedure, decoder) {
|
||||||
const contexts = contextCache.getContexts(procedure);
|
const contexts = contextCache.getContexts(procedure);
|
||||||
let prev = 1;
|
let prev = 1;
|
||||||
|
|
||||||
@ -64,8 +62,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
let v = 0;
|
let v = 0;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
const bit = decoder.readBit(contexts, prev);
|
const bit = decoder.readBit(contexts, prev);
|
||||||
prev =
|
prev = prev < 256 ? (prev << 1) | bit : (((prev << 1) | bit) & 511) | 256;
|
||||||
prev < 256 ? (prev << 1) | bit : (((prev << 1) | bit) & 511) | 256;
|
|
||||||
v = (v << 1) | bit;
|
v = (v << 1) | bit;
|
||||||
}
|
}
|
||||||
return v >>> 0;
|
return v >>> 0;
|
||||||
@ -92,10 +89,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
return -value;
|
return -value;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A.3 The IAID decoding procedure
|
// A.3 The IAID decoding procedure
|
||||||
function decodeIAID(contextCache, decoder, codeLength) {
|
function decodeIAID(contextCache, decoder, codeLength) {
|
||||||
const contexts = contextCache.getContexts("IAID");
|
const contexts = contextCache.getContexts("IAID");
|
||||||
|
|
||||||
let prev = 1;
|
let prev = 1;
|
||||||
@ -107,10 +104,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
return prev & ((1 << codeLength) - 1);
|
return prev & ((1 << codeLength) - 1);
|
||||||
}
|
}
|
||||||
return prev & 0x7fffffff;
|
return prev & 0x7fffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.3 Segment types
|
// 7.3 Segment types
|
||||||
const SegmentTypes = [
|
const SegmentTypes = [
|
||||||
"SymbolDictionary",
|
"SymbolDictionary",
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@ -174,9 +171,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
"Extension",
|
"Extension",
|
||||||
];
|
];
|
||||||
|
|
||||||
const CodingTemplates = [
|
const CodingTemplates = [
|
||||||
[
|
[
|
||||||
{ x: -1, y: -2 },
|
{ x: -1, y: -2 },
|
||||||
{ x: 0, y: -2 },
|
{ x: 0, y: -2 },
|
||||||
@ -227,9 +224,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
{ x: -2, y: 0 },
|
{ x: -2, y: 0 },
|
||||||
{ x: -1, y: 0 },
|
{ x: -1, y: 0 },
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
const RefinementTemplates = [
|
const RefinementTemplates = [
|
||||||
{
|
{
|
||||||
coding: [
|
coding: [
|
||||||
{ x: 0, y: -1 },
|
{ x: 0, y: -1 },
|
||||||
@ -263,22 +260,22 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
{ x: 1, y: 1 },
|
{ x: 1, y: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// See 6.2.5.7 Decoding the bitmap.
|
// See 6.2.5.7 Decoding the bitmap.
|
||||||
const ReusedContexts = [
|
const ReusedContexts = [
|
||||||
0x9b25, // 10011 0110010 0101
|
0x9b25, // 10011 0110010 0101
|
||||||
0x0795, // 0011 110010 101
|
0x0795, // 0011 110010 101
|
||||||
0x00e5, // 001 11001 01
|
0x00e5, // 001 11001 01
|
||||||
0x0195, // 011001 0101
|
0x0195, // 011001 0101
|
||||||
];
|
];
|
||||||
|
|
||||||
const RefinementReusedContexts = [
|
const RefinementReusedContexts = [
|
||||||
0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference)
|
0x0020, // '000' + '0' (coding) + '00010000' + '0' (reference)
|
||||||
0x0008, // '0000' + '001000'
|
0x0008, // '0000' + '001000'
|
||||||
];
|
];
|
||||||
|
|
||||||
function decodeBitmapTemplate0(width, height, decodingContext) {
|
function decodeBitmapTemplate0(width, height, decodingContext) {
|
||||||
const decoder = decodingContext.decoder;
|
const decoder = decodingContext.decoder;
|
||||||
const contexts = decodingContext.contextCache.getContexts("GB");
|
const contexts = decodingContext.contextCache.getContexts("GB");
|
||||||
const bitmap = [];
|
const bitmap = [];
|
||||||
@ -319,10 +316,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.2 Generic Region Decoding Procedure
|
// 6.2 Generic Region Decoding Procedure
|
||||||
function decodeBitmap(
|
function decodeBitmap(
|
||||||
mmr,
|
mmr,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@ -331,7 +328,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
skip,
|
skip,
|
||||||
at,
|
at,
|
||||||
decodingContext
|
decodingContext
|
||||||
) {
|
) {
|
||||||
if (mmr) {
|
if (mmr) {
|
||||||
const input = new Reader(
|
const input = new Reader(
|
||||||
decodingContext.data,
|
decodingContext.data,
|
||||||
@ -482,10 +479,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.3.2 Generic Refinement Region Decoding Procedure
|
// 6.3.2 Generic Refinement Region Decoding Procedure
|
||||||
function decodeRefinement(
|
function decodeRefinement(
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
templateIndex,
|
templateIndex,
|
||||||
@ -495,7 +492,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
prediction,
|
prediction,
|
||||||
at,
|
at,
|
||||||
decodingContext
|
decodingContext
|
||||||
) {
|
) {
|
||||||
let codingTemplate = RefinementTemplates[templateIndex].coding;
|
let codingTemplate = RefinementTemplates[templateIndex].coding;
|
||||||
if (templateIndex === 0) {
|
if (templateIndex === 0) {
|
||||||
codingTemplate = codingTemplate.concat([at[0]]);
|
codingTemplate = codingTemplate.concat([at[0]]);
|
||||||
@ -555,12 +552,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
for (k = 0; k < referenceTemplateLength; k++) {
|
for (k = 0; k < referenceTemplateLength; k++) {
|
||||||
i0 = i + referenceTemplateY[k] - offsetY;
|
i0 = i + referenceTemplateY[k] - offsetY;
|
||||||
j0 = j + referenceTemplateX[k] - offsetX;
|
j0 = j + referenceTemplateX[k] - offsetX;
|
||||||
if (
|
if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {
|
||||||
i0 < 0 ||
|
|
||||||
i0 >= referenceHeight ||
|
|
||||||
j0 < 0 ||
|
|
||||||
j0 >= referenceWidth
|
|
||||||
) {
|
|
||||||
contextLabel <<= 1; // out of bound pixel
|
contextLabel <<= 1; // out of bound pixel
|
||||||
} else {
|
} else {
|
||||||
contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
|
contextLabel = (contextLabel << 1) | referenceBitmap[i0][j0];
|
||||||
@ -572,10 +564,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.5.5 Decoding the symbol dictionary
|
// 6.5.5 Decoding the symbol dictionary
|
||||||
function decodeSymbolDictionary(
|
function decodeSymbolDictionary(
|
||||||
huffman,
|
huffman,
|
||||||
refinement,
|
refinement,
|
||||||
symbols,
|
symbols,
|
||||||
@ -588,7 +580,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
refinementAt,
|
refinementAt,
|
||||||
decodingContext,
|
decodingContext,
|
||||||
huffmanInput
|
huffmanInput
|
||||||
) {
|
) {
|
||||||
if (huffman && refinement) {
|
if (huffman && refinement) {
|
||||||
throw new Jbig2Error("symbol refinement with Huffman is not supported");
|
throw new Jbig2Error("symbol refinement with Huffman is not supported");
|
||||||
}
|
}
|
||||||
@ -626,11 +618,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
let bitmap;
|
let bitmap;
|
||||||
if (refinement) {
|
if (refinement) {
|
||||||
// 6.5.8.2 Refinement/aggregate-coded symbol bitmap
|
// 6.5.8.2 Refinement/aggregate-coded symbol bitmap
|
||||||
const numberOfInstances = decodeInteger(
|
const numberOfInstances = decodeInteger(contextCache, "IAAI", decoder);
|
||||||
contextCache,
|
|
||||||
"IAAI",
|
|
||||||
decoder
|
|
||||||
);
|
|
||||||
if (numberOfInstances > 1) {
|
if (numberOfInstances > 1) {
|
||||||
bitmap = decodeTextRegion(
|
bitmap = decodeTextRegion(
|
||||||
huffman,
|
huffman,
|
||||||
@ -654,11 +642,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
huffmanInput
|
huffmanInput
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const symbolId = decodeIAID(
|
const symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
|
||||||
contextCache,
|
|
||||||
decoder,
|
|
||||||
symbolCodeLength
|
|
||||||
);
|
|
||||||
const rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
|
const rdx = decodeInteger(contextCache, "IARDX", decoder); // 6.4.11.3
|
||||||
const rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
|
const rdy = decodeInteger(contextCache, "IARDY", decoder); // 6.4.11.4
|
||||||
const symbol =
|
const symbol =
|
||||||
@ -776,9 +760,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return exportedSymbols;
|
return exportedSymbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeTextRegion(
|
function decodeTextRegion(
|
||||||
huffman,
|
huffman,
|
||||||
refinement,
|
refinement,
|
||||||
width,
|
width,
|
||||||
@ -798,7 +782,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
decodingContext,
|
decodingContext,
|
||||||
logStripSize,
|
logStripSize,
|
||||||
huffmanInput
|
huffmanInput
|
||||||
) {
|
) {
|
||||||
if (huffman && refinement) {
|
if (huffman && refinement) {
|
||||||
throw new Jbig2Error("refinement with Huffman is not supported");
|
throw new Jbig2Error("refinement with Huffman is not supported");
|
||||||
}
|
}
|
||||||
@ -942,16 +926,16 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodePatternDictionary(
|
function decodePatternDictionary(
|
||||||
mmr,
|
mmr,
|
||||||
patternWidth,
|
patternWidth,
|
||||||
patternHeight,
|
patternHeight,
|
||||||
maxPatternIndex,
|
maxPatternIndex,
|
||||||
template,
|
template,
|
||||||
decodingContext
|
decodingContext
|
||||||
) {
|
) {
|
||||||
const at = [];
|
const at = [];
|
||||||
if (!mmr) {
|
if (!mmr) {
|
||||||
at.push({
|
at.push({
|
||||||
@ -996,9 +980,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
patterns.push(patternBitmap);
|
patterns.push(patternBitmap);
|
||||||
}
|
}
|
||||||
return patterns;
|
return patterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeHalftoneRegion(
|
function decodeHalftoneRegion(
|
||||||
mmr,
|
mmr,
|
||||||
patterns,
|
patterns,
|
||||||
template,
|
template,
|
||||||
@ -1014,16 +998,14 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
gridVectorX,
|
gridVectorX,
|
||||||
gridVectorY,
|
gridVectorY,
|
||||||
decodingContext
|
decodingContext
|
||||||
) {
|
) {
|
||||||
const skip = null;
|
const skip = null;
|
||||||
if (enableSkip) {
|
if (enableSkip) {
|
||||||
throw new Jbig2Error("skip is not supported");
|
throw new Jbig2Error("skip is not supported");
|
||||||
}
|
}
|
||||||
if (combinationOperator !== 0) {
|
if (combinationOperator !== 0) {
|
||||||
throw new Jbig2Error(
|
throw new Jbig2Error(
|
||||||
"operator " +
|
`operator "${combinationOperator}" is not supported in halftone region`
|
||||||
combinationOperator +
|
|
||||||
" is not supported in halftone region"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1142,9 +1124,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return regionBitmap;
|
return regionBitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readSegmentHeader(data, start) {
|
function readSegmentHeader(data, start) {
|
||||||
const segmentHeader = {};
|
const segmentHeader = {};
|
||||||
segmentHeader.number = readUint32(data, start);
|
segmentHeader.number = readUint32(data, start);
|
||||||
const flags = data[start + 4];
|
const flags = data[start + 4];
|
||||||
@ -1243,9 +1225,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
segmentHeader.headerEnd = position;
|
segmentHeader.headerEnd = position;
|
||||||
return segmentHeader;
|
return segmentHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
function readSegments(header, data, start, end) {
|
function readSegments(header, data, start, end) {
|
||||||
const segments = [];
|
const segments = [];
|
||||||
let position = start;
|
let position = start;
|
||||||
while (position < end) {
|
while (position < end) {
|
||||||
@ -1273,10 +1255,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return segments;
|
return segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7.4.1 Region segment information field
|
// 7.4.1 Region segment information field
|
||||||
function readRegionSegmentInformation(data, start) {
|
function readRegionSegmentInformation(data, start) {
|
||||||
return {
|
return {
|
||||||
width: readUint32(data, start),
|
width: readUint32(data, start),
|
||||||
height: readUint32(data, start + 4),
|
height: readUint32(data, start + 4),
|
||||||
@ -1284,10 +1266,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
y: readUint32(data, start + 12),
|
y: readUint32(data, start + 12),
|
||||||
combinationOperator: data[start + 16] & 7,
|
combinationOperator: data[start + 16] & 7,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const RegionSegmentInformationFieldLength = 17;
|
const RegionSegmentInformationFieldLength = 17;
|
||||||
|
|
||||||
function processSegment(segment, visitor) {
|
function processSegment(segment, visitor) {
|
||||||
const header = segment.header;
|
const header = segment.header;
|
||||||
|
|
||||||
const data = segment.data,
|
const data = segment.data,
|
||||||
@ -1495,15 +1477,15 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
if (callbackName in visitor) {
|
if (callbackName in visitor) {
|
||||||
visitor[callbackName].apply(visitor, args);
|
visitor[callbackName].apply(visitor, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processSegments(segments, visitor) {
|
function processSegments(segments, visitor) {
|
||||||
for (let i = 0, ii = segments.length; i < ii; i++) {
|
for (let i = 0, ii = segments.length; i < ii; i++) {
|
||||||
processSegment(segments[i], visitor);
|
processSegment(segments[i], visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseJbig2Chunks(chunks) {
|
function parseJbig2Chunks(chunks) {
|
||||||
const visitor = new SimpleSegmentVisitor();
|
const visitor = new SimpleSegmentVisitor();
|
||||||
for (let i = 0, ii = chunks.length; i < ii; i++) {
|
for (let i = 0, ii = chunks.length; i < ii; i++) {
|
||||||
const chunk = chunks[i];
|
const chunk = chunks[i];
|
||||||
@ -1511,9 +1493,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
processSegments(segments, visitor);
|
processSegments(segments, visitor);
|
||||||
}
|
}
|
||||||
return visitor.buffer;
|
return visitor.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseJbig2(data) {
|
function parseJbig2(data) {
|
||||||
const end = data.length;
|
const end = data.length;
|
||||||
let position = 0;
|
let position = 0;
|
||||||
|
|
||||||
@ -1562,12 +1544,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return { imgData, width, height };
|
return { imgData, width, height };
|
||||||
}
|
}
|
||||||
|
|
||||||
function SimpleSegmentVisitor() {}
|
class SimpleSegmentVisitor {
|
||||||
|
onPageInformation(info) {
|
||||||
SimpleSegmentVisitor.prototype = {
|
|
||||||
onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
|
|
||||||
this.currentPageInfo = info;
|
this.currentPageInfo = info;
|
||||||
const rowSize = (info.width + 7) >> 3;
|
const rowSize = (info.width + 7) >> 3;
|
||||||
const buffer = new Uint8ClampedArray(rowSize * info.height);
|
const buffer = new Uint8ClampedArray(rowSize * info.height);
|
||||||
@ -1579,8 +1559,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
},
|
}
|
||||||
drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
|
|
||||||
|
drawBitmap(regionInfo, bitmap) {
|
||||||
const pageInfo = this.currentPageInfo;
|
const pageInfo = this.currentPageInfo;
|
||||||
const width = regionInfo.width,
|
const width = regionInfo.width,
|
||||||
height = regionInfo.height;
|
height = regionInfo.height;
|
||||||
@ -1632,13 +1613,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
`operator ${combinationOperator} is not supported`
|
`operator ${combinationOperator} is not supported`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
onImmediateGenericRegion: function SimpleSegmentVisitor_onImmediateGenericRegion(
|
|
||||||
region,
|
onImmediateGenericRegion(region, data, start, end) {
|
||||||
data,
|
|
||||||
start,
|
|
||||||
end
|
|
||||||
) {
|
|
||||||
const regionInfo = region.info;
|
const regionInfo = region.info;
|
||||||
const decodingContext = new DecodingContext(data, start, end);
|
const decodingContext = new DecodingContext(data, start, end);
|
||||||
const bitmap = decodeBitmap(
|
const bitmap = decodeBitmap(
|
||||||
@ -1652,11 +1629,13 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
decodingContext
|
decodingContext
|
||||||
);
|
);
|
||||||
this.drawBitmap(regionInfo, bitmap);
|
this.drawBitmap(regionInfo, bitmap);
|
||||||
},
|
}
|
||||||
onImmediateLosslessGenericRegion: function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
|
|
||||||
|
onImmediateLosslessGenericRegion() {
|
||||||
this.onImmediateGenericRegion.apply(this, arguments);
|
this.onImmediateGenericRegion.apply(this, arguments);
|
||||||
},
|
}
|
||||||
onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(
|
|
||||||
|
onSymbolDictionary(
|
||||||
dictionary,
|
dictionary,
|
||||||
currentSegment,
|
currentSegment,
|
||||||
referredSegments,
|
referredSegments,
|
||||||
@ -1705,14 +1684,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
decodingContext,
|
decodingContext,
|
||||||
huffmanInput
|
huffmanInput
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(
|
|
||||||
region,
|
onImmediateTextRegion(region, referredSegments, data, start, end) {
|
||||||
referredSegments,
|
|
||||||
data,
|
|
||||||
start,
|
|
||||||
end
|
|
||||||
) {
|
|
||||||
const regionInfo = region.info;
|
const regionInfo = region.info;
|
||||||
let huffmanTables, huffmanInput;
|
let huffmanTables, huffmanInput;
|
||||||
|
|
||||||
@ -1762,10 +1736,12 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
huffmanInput
|
huffmanInput
|
||||||
);
|
);
|
||||||
this.drawBitmap(regionInfo, bitmap);
|
this.drawBitmap(regionInfo, bitmap);
|
||||||
},
|
}
|
||||||
onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
|
|
||||||
|
onImmediateLosslessTextRegion() {
|
||||||
this.onImmediateTextRegion.apply(this, arguments);
|
this.onImmediateTextRegion.apply(this, arguments);
|
||||||
},
|
}
|
||||||
|
|
||||||
onPatternDictionary(dictionary, currentSegment, data, start, end) {
|
onPatternDictionary(dictionary, currentSegment, data, start, end) {
|
||||||
let patterns = this.patterns;
|
let patterns = this.patterns;
|
||||||
if (!patterns) {
|
if (!patterns) {
|
||||||
@ -1780,7 +1756,8 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
dictionary.template,
|
dictionary.template,
|
||||||
decodingContext
|
decodingContext
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
|
|
||||||
onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
|
onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
|
||||||
// HalftoneRegion refers to exactly one PatternDictionary.
|
// HalftoneRegion refers to exactly one PatternDictionary.
|
||||||
const patterns = this.patterns[referredSegments[0]];
|
const patterns = this.patterns[referredSegments[0]];
|
||||||
@ -1804,20 +1781,23 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
decodingContext
|
decodingContext
|
||||||
);
|
);
|
||||||
this.drawBitmap(regionInfo, bitmap);
|
this.drawBitmap(regionInfo, bitmap);
|
||||||
},
|
}
|
||||||
|
|
||||||
onImmediateLosslessHalftoneRegion() {
|
onImmediateLosslessHalftoneRegion() {
|
||||||
this.onImmediateHalftoneRegion.apply(this, arguments);
|
this.onImmediateHalftoneRegion.apply(this, arguments);
|
||||||
},
|
}
|
||||||
|
|
||||||
onTables(currentSegment, data, start, end) {
|
onTables(currentSegment, data, start, end) {
|
||||||
let customTables = this.customTables;
|
let customTables = this.customTables;
|
||||||
if (!customTables) {
|
if (!customTables) {
|
||||||
this.customTables = customTables = {};
|
this.customTables = customTables = {};
|
||||||
}
|
}
|
||||||
customTables[currentSegment] = decodeTablesSegment(data, start, end);
|
customTables[currentSegment] = decodeTablesSegment(data, start, end);
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function HuffmanLine(lineData) {
|
class HuffmanLine {
|
||||||
|
constructor(lineData) {
|
||||||
if (lineData.length === 2) {
|
if (lineData.length === 2) {
|
||||||
// OOB line.
|
// OOB line.
|
||||||
this.isOOB = true;
|
this.isOOB = true;
|
||||||
@ -1837,8 +1817,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
this.isLowerRange = lineData[4] === "lower";
|
this.isLowerRange = lineData[4] === "lower";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function HuffmanTreeNode(line) {
|
class HuffmanTreeNode {
|
||||||
|
constructor(line) {
|
||||||
this.children = [];
|
this.children = [];
|
||||||
if (line) {
|
if (line) {
|
||||||
// Leaf node
|
// Leaf node
|
||||||
@ -1853,7 +1835,6 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HuffmanTreeNode.prototype = {
|
|
||||||
buildTree(line, shift) {
|
buildTree(line, shift) {
|
||||||
const bit = (line.prefixCode >> shift) & 1;
|
const bit = (line.prefixCode >> shift) & 1;
|
||||||
if (shift <= 0) {
|
if (shift <= 0) {
|
||||||
@ -1867,7 +1848,8 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
node.buildTree(line, shift - 1);
|
node.buildTree(line, shift - 1);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
decodeNode(reader) {
|
decodeNode(reader) {
|
||||||
if (this.isLeaf) {
|
if (this.isLeaf) {
|
||||||
if (this.isOOB) {
|
if (this.isOOB) {
|
||||||
@ -1881,10 +1863,11 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
throw new Jbig2Error("invalid Huffman data");
|
throw new Jbig2Error("invalid Huffman data");
|
||||||
}
|
}
|
||||||
return node.decodeNode(reader);
|
return node.decodeNode(reader);
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function HuffmanTable(lines, prefixCodesDone) {
|
class HuffmanTable {
|
||||||
|
constructor(lines, prefixCodesDone) {
|
||||||
if (!prefixCodesDone) {
|
if (!prefixCodesDone) {
|
||||||
this.assignPrefixCodes(lines);
|
this.assignPrefixCodes(lines);
|
||||||
}
|
}
|
||||||
@ -1898,10 +1881,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HuffmanTable.prototype = {
|
|
||||||
decode(reader) {
|
decode(reader) {
|
||||||
return this.rootNode.decodeNode(reader);
|
return this.rootNode.decodeNode(reader);
|
||||||
},
|
}
|
||||||
|
|
||||||
assignPrefixCodes(lines) {
|
assignPrefixCodes(lines) {
|
||||||
// Annex B.3 Assigning the prefix codes.
|
// Annex B.3 Assigning the prefix codes.
|
||||||
const linesLength = lines.length;
|
const linesLength = lines.length;
|
||||||
@ -1935,10 +1918,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
currentLength++;
|
currentLength++;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function decodeTablesSegment(data, start, end) {
|
function decodeTablesSegment(data, start, end) {
|
||||||
// Decodes a Tables segment, i.e., a custom Huffman table.
|
// Decodes a Tables segment, i.e., a custom Huffman table.
|
||||||
// Annex B.2 Code table structure.
|
// Annex B.2 Code table structure.
|
||||||
const flags = data[start];
|
const flags = data[start];
|
||||||
@ -1965,9 +1948,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
|
|
||||||
// Lower range table line
|
// Lower range table line
|
||||||
prefixLength = reader.readBits(prefixSizeBits);
|
prefixLength = reader.readBits(prefixSizeBits);
|
||||||
lines.push(
|
lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"]));
|
||||||
new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, "lower"])
|
|
||||||
);
|
|
||||||
|
|
||||||
// Upper range table line
|
// Upper range table line
|
||||||
prefixLength = reader.readBits(prefixSizeBits);
|
prefixLength = reader.readBits(prefixSizeBits);
|
||||||
@ -1980,11 +1961,11 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new HuffmanTable(lines, false);
|
return new HuffmanTable(lines, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const standardTablesCache = {};
|
const standardTablesCache = {};
|
||||||
|
|
||||||
function getStandardTable(number) {
|
function getStandardTable(number) {
|
||||||
// Annex B.5 Standard Huffman tables.
|
// Annex B.5 Standard Huffman tables.
|
||||||
let table = standardTablesCache[number];
|
let table = standardTablesCache[number];
|
||||||
if (table) {
|
if (table) {
|
||||||
@ -2246,9 +2227,10 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
table = new HuffmanTable(lines, true);
|
table = new HuffmanTable(lines, true);
|
||||||
standardTablesCache[number] = table;
|
standardTablesCache[number] = table;
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Reader(data, start, end) {
|
class Reader {
|
||||||
|
constructor(data, start, end) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
@ -2257,7 +2239,6 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
this.currentByte = 0;
|
this.currentByte = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Reader.prototype = {
|
|
||||||
readBit() {
|
readBit() {
|
||||||
if (this.shift < 0) {
|
if (this.shift < 0) {
|
||||||
if (this.position >= this.end) {
|
if (this.position >= this.end) {
|
||||||
@ -2269,7 +2250,7 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
const bit = (this.currentByte >> this.shift) & 1;
|
const bit = (this.currentByte >> this.shift) & 1;
|
||||||
this.shift--;
|
this.shift--;
|
||||||
return bit;
|
return bit;
|
||||||
},
|
}
|
||||||
|
|
||||||
readBits(numBits) {
|
readBits(numBits) {
|
||||||
let result = 0,
|
let result = 0,
|
||||||
@ -2278,21 +2259,21 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
result |= this.readBit() << i;
|
result |= this.readBit() << i;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
}
|
||||||
|
|
||||||
byteAlign() {
|
byteAlign() {
|
||||||
this.shift = -1;
|
this.shift = -1;
|
||||||
},
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
if (this.position >= this.end) {
|
if (this.position >= this.end) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return this.data[this.position++];
|
return this.data[this.position++];
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
function getCustomHuffmanTable(index, referredTo, customTables) {
|
function getCustomHuffmanTable(index, referredTo, customTables) {
|
||||||
// Returns a Tables segment that has been earlier decoded.
|
// Returns a Tables segment that has been earlier decoded.
|
||||||
// See 7.4.2.1.6 (symbol dictionary) or 7.4.3.1.6 (text region).
|
// See 7.4.2.1.6 (symbol dictionary) or 7.4.3.1.6 (text region).
|
||||||
let currentIndex = 0;
|
let currentIndex = 0;
|
||||||
@ -2306,15 +2287,15 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Jbig2Error("can't find custom Huffman table");
|
throw new Jbig2Error("can't find custom Huffman table");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTextRegionHuffmanTables(
|
function getTextRegionHuffmanTables(
|
||||||
textRegion,
|
textRegion,
|
||||||
referredTo,
|
referredTo,
|
||||||
customTables,
|
customTables,
|
||||||
numberOfSymbols,
|
numberOfSymbols,
|
||||||
reader
|
reader
|
||||||
) {
|
) {
|
||||||
// 7.4.3.1.7 Symbol ID Huffman table decoding
|
// 7.4.3.1.7 Symbol ID Huffman table decoding
|
||||||
|
|
||||||
// Read code lengths for RUNCODEs 0...34.
|
// Read code lengths for RUNCODEs 0...34.
|
||||||
@ -2435,13 +2416,13 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
tableDeltaS,
|
tableDeltaS,
|
||||||
tableDeltaT,
|
tableDeltaT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSymbolDictionaryHuffmanTables(
|
function getSymbolDictionaryHuffmanTables(
|
||||||
dictionary,
|
dictionary,
|
||||||
referredTo,
|
referredTo,
|
||||||
customTables
|
customTables
|
||||||
) {
|
) {
|
||||||
// 7.4.2.1.6 Symbol dictionary segment Huffman table selection
|
// 7.4.2.1.6 Symbol dictionary segment Huffman table selection
|
||||||
|
|
||||||
let customIndex = 0,
|
let customIndex = 0,
|
||||||
@ -2509,9 +2490,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
tableBitmapSize,
|
tableBitmapSize,
|
||||||
tableAggregateInstances,
|
tableAggregateInstances,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function readUncompressedBitmap(reader, width, height) {
|
function readUncompressedBitmap(reader, width, height) {
|
||||||
const bitmap = [];
|
const bitmap = [];
|
||||||
for (let y = 0; y < height; y++) {
|
for (let y = 0; y < height; y++) {
|
||||||
const row = new Uint8Array(width);
|
const row = new Uint8Array(width);
|
||||||
@ -2522,9 +2503,9 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
reader.byteAlign();
|
reader.byteAlign();
|
||||||
}
|
}
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeMMRBitmap(input, width, height, endOfBlock) {
|
function decodeMMRBitmap(input, width, height, endOfBlock) {
|
||||||
// MMR is the same compression algorithm as the PDF filter
|
// MMR is the same compression algorithm as the PDF filter
|
||||||
// CCITTFaxDecode with /K -1.
|
// CCITTFaxDecode with /K -1.
|
||||||
const params = {
|
const params = {
|
||||||
@ -2569,25 +2550,19 @@ const Jbig2Image = (function Jbig2ImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
class Jbig2Image {
|
||||||
function Jbig2Image() {}
|
|
||||||
|
|
||||||
Jbig2Image.prototype = {
|
|
||||||
parseChunks(chunks) {
|
parseChunks(chunks) {
|
||||||
return parseJbig2Chunks(chunks);
|
return parseJbig2Chunks(chunks);
|
||||||
},
|
}
|
||||||
|
|
||||||
parse(data) {
|
parse(data) {
|
||||||
const { imgData, width, height } = parseJbig2(data);
|
const { imgData, width, height } = parseJbig2(data);
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
return imgData;
|
return imgData;
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return Jbig2Image;
|
|
||||||
})();
|
|
||||||
|
|
||||||
export { Jbig2Image };
|
export { Jbig2Image };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user