|
@@ -30,6 +30,8 @@ var _util = require('../shared/util');
|
|
|
|
|
|
var _arithmetic_decoder = require('./arithmetic_decoder');
|
|
var _arithmetic_decoder = require('./arithmetic_decoder');
|
|
|
|
|
|
|
|
+var _ccitt = require('./ccitt');
|
|
|
|
+
|
|
var Jbig2Error = function Jbig2ErrorClosure() {
|
|
var Jbig2Error = function Jbig2ErrorClosure() {
|
|
function Jbig2Error(msg) {
|
|
function Jbig2Error(msg) {
|
|
this.message = 'JBIG2 error: ' + msg;
|
|
this.message = 'JBIG2 error: ' + msg;
|
|
@@ -318,7 +320,8 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {
|
|
function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {
|
|
if (mmr) {
|
|
if (mmr) {
|
|
- throw new Jbig2Error('MMR encoding is not supported');
|
|
|
|
|
|
+ var input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
|
|
|
|
+ return decodeMMRBitmap(input, width, height, false);
|
|
}
|
|
}
|
|
if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
|
|
if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
|
|
return decodeBitmapTemplate0(width, height, decodingContext);
|
|
return decodeBitmapTemplate0(width, height, decodingContext);
|
|
@@ -491,30 +494,40 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
return bitmap;
|
|
return bitmap;
|
|
}
|
|
}
|
|
- function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext) {
|
|
|
|
- if (huffman) {
|
|
|
|
- throw new Jbig2Error('huffman is not supported');
|
|
|
|
|
|
+ function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) {
|
|
|
|
+ if (huffman && refinement) {
|
|
|
|
+ throw new Jbig2Error('symbol refinement with Huffman is not supported');
|
|
}
|
|
}
|
|
var newSymbols = [];
|
|
var newSymbols = [];
|
|
var currentHeight = 0;
|
|
var currentHeight = 0;
|
|
var symbolCodeLength = (0, _util.log2)(symbols.length + numberOfNewSymbols);
|
|
var symbolCodeLength = (0, _util.log2)(symbols.length + numberOfNewSymbols);
|
|
var decoder = decodingContext.decoder;
|
|
var decoder = decodingContext.decoder;
|
|
var contextCache = decodingContext.contextCache;
|
|
var contextCache = decodingContext.contextCache;
|
|
|
|
+ var tableB1 = void 0,
|
|
|
|
+ symbolWidths = void 0;
|
|
|
|
+ if (huffman) {
|
|
|
|
+ tableB1 = getStandardTable(1);
|
|
|
|
+ symbolWidths = [];
|
|
|
|
+ symbolCodeLength = Math.max(symbolCodeLength, 1);
|
|
|
|
+ }
|
|
while (newSymbols.length < numberOfNewSymbols) {
|
|
while (newSymbols.length < numberOfNewSymbols) {
|
|
- var deltaHeight = decodeInteger(contextCache, 'IADH', decoder);
|
|
|
|
|
|
+ var deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, 'IADH', decoder);
|
|
currentHeight += deltaHeight;
|
|
currentHeight += deltaHeight;
|
|
- var currentWidth = 0;
|
|
|
|
|
|
+ var currentWidth = 0,
|
|
|
|
+ totalWidth = 0;
|
|
|
|
+ var firstSymbol = huffman ? symbolWidths.length : 0;
|
|
while (true) {
|
|
while (true) {
|
|
- var deltaWidth = decodeInteger(contextCache, 'IADW', decoder);
|
|
|
|
|
|
+ var deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, 'IADW', decoder);
|
|
if (deltaWidth === null) {
|
|
if (deltaWidth === null) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
currentWidth += deltaWidth;
|
|
currentWidth += deltaWidth;
|
|
|
|
+ totalWidth += currentWidth;
|
|
var bitmap;
|
|
var bitmap;
|
|
if (refinement) {
|
|
if (refinement) {
|
|
var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
|
|
var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
|
|
if (numberOfInstances > 1) {
|
|
if (numberOfInstances > 1) {
|
|
- bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext);
|
|
|
|
|
|
+ bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput);
|
|
} else {
|
|
} else {
|
|
var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
|
|
var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
|
|
var rdx = decodeInteger(contextCache, 'IARDX', decoder);
|
|
var rdx = decodeInteger(contextCache, 'IARDX', decoder);
|
|
@@ -522,10 +535,49 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
var symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];
|
|
var symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];
|
|
bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);
|
|
bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);
|
|
}
|
|
}
|
|
|
|
+ newSymbols.push(bitmap);
|
|
|
|
+ } else if (huffman) {
|
|
|
|
+ symbolWidths.push(currentWidth);
|
|
} else {
|
|
} else {
|
|
bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);
|
|
bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);
|
|
|
|
+ newSymbols.push(bitmap);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (huffman && !refinement) {
|
|
|
|
+ var bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);
|
|
|
|
+ huffmanInput.byteAlign();
|
|
|
|
+ var collectiveBitmap = void 0;
|
|
|
|
+ if (bitmapSize === 0) {
|
|
|
|
+ collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight);
|
|
|
|
+ } else {
|
|
|
|
+ var originalEnd = huffmanInput.end;
|
|
|
|
+ var bitmapEnd = huffmanInput.position + bitmapSize;
|
|
|
|
+ huffmanInput.end = bitmapEnd;
|
|
|
|
+ collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false);
|
|
|
|
+ huffmanInput.end = originalEnd;
|
|
|
|
+ huffmanInput.position = bitmapEnd;
|
|
|
|
+ }
|
|
|
|
+ var numberOfSymbolsDecoded = symbolWidths.length;
|
|
|
|
+ if (firstSymbol === numberOfSymbolsDecoded - 1) {
|
|
|
|
+ newSymbols.push(collectiveBitmap);
|
|
|
|
+ } else {
|
|
|
|
+ var _i = void 0,
|
|
|
|
+ y = void 0,
|
|
|
|
+ xMin = 0,
|
|
|
|
+ xMax = void 0,
|
|
|
|
+ bitmapWidth = void 0,
|
|
|
|
+ symbolBitmap = void 0;
|
|
|
|
+ for (_i = firstSymbol; _i < numberOfSymbolsDecoded; _i++) {
|
|
|
|
+ bitmapWidth = symbolWidths[_i];
|
|
|
|
+ xMax = xMin + bitmapWidth;
|
|
|
|
+ symbolBitmap = [];
|
|
|
|
+ for (y = 0; y < currentHeight; y++) {
|
|
|
|
+ symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
|
|
|
|
+ }
|
|
|
|
+ newSymbols.push(symbolBitmap);
|
|
|
|
+ xMin = xMax;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- newSymbols.push(bitmap);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var exportedSymbols = [];
|
|
var exportedSymbols = [];
|
|
@@ -533,7 +585,7 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
currentFlag = false;
|
|
currentFlag = false;
|
|
var totalSymbolsLength = symbols.length + numberOfNewSymbols;
|
|
var totalSymbolsLength = symbols.length + numberOfNewSymbols;
|
|
while (flags.length < totalSymbolsLength) {
|
|
while (flags.length < totalSymbolsLength) {
|
|
- var runLength = decodeInteger(contextCache, 'IAEX', decoder);
|
|
|
|
|
|
+ var runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, 'IAEX', decoder);
|
|
while (runLength--) {
|
|
while (runLength--) {
|
|
flags.push(currentFlag);
|
|
flags.push(currentFlag);
|
|
}
|
|
}
|
|
@@ -551,9 +603,9 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
return exportedSymbols;
|
|
return exportedSymbols;
|
|
}
|
|
}
|
|
- function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext) {
|
|
|
|
- if (huffman) {
|
|
|
|
- throw new Jbig2Error('huffman is not supported');
|
|
|
|
|
|
+ function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) {
|
|
|
|
+ if (huffman && refinement) {
|
|
|
|
+ throw new Jbig2Error('refinement with Huffman is not supported');
|
|
}
|
|
}
|
|
var bitmap = [];
|
|
var bitmap = [];
|
|
var i, row;
|
|
var i, row;
|
|
@@ -568,20 +620,23 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
var decoder = decodingContext.decoder;
|
|
var decoder = decodingContext.decoder;
|
|
var contextCache = decodingContext.contextCache;
|
|
var contextCache = decodingContext.contextCache;
|
|
- var stripT = -decodeInteger(contextCache, 'IADT', decoder);
|
|
|
|
|
|
+ var stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, 'IADT', decoder);
|
|
var firstS = 0;
|
|
var firstS = 0;
|
|
i = 0;
|
|
i = 0;
|
|
while (i < numberOfSymbolInstances) {
|
|
while (i < numberOfSymbolInstances) {
|
|
- var deltaT = decodeInteger(contextCache, 'IADT', decoder);
|
|
|
|
|
|
+ var deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, 'IADT', decoder);
|
|
stripT += deltaT;
|
|
stripT += deltaT;
|
|
- var deltaFirstS = decodeInteger(contextCache, 'IAFS', decoder);
|
|
|
|
|
|
+ var deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, 'IAFS', decoder);
|
|
firstS += deltaFirstS;
|
|
firstS += deltaFirstS;
|
|
var currentS = firstS;
|
|
var currentS = firstS;
|
|
do {
|
|
do {
|
|
- var currentT = stripSize === 1 ? 0 : decodeInteger(contextCache, 'IAIT', decoder);
|
|
|
|
|
|
+ var currentT = 0;
|
|
|
|
+ if (stripSize > 1) {
|
|
|
|
+ currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, 'IAIT', decoder);
|
|
|
|
+ }
|
|
var t = stripSize * stripT + currentT;
|
|
var t = stripSize * stripT + currentT;
|
|
- var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
|
|
|
|
- var applyRefinement = refinement && decodeInteger(contextCache, 'IARI', decoder);
|
|
|
|
|
|
+ var symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength);
|
|
|
|
+ var applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, 'IARI', decoder));
|
|
var symbolBitmap = inputSymbols[symbolId];
|
|
var symbolBitmap = inputSymbols[symbolId];
|
|
var symbolWidth = symbolBitmap[0].length;
|
|
var symbolWidth = symbolBitmap[0].length;
|
|
var symbolHeight = symbolBitmap.length;
|
|
var symbolHeight = symbolBitmap.length;
|
|
@@ -646,7 +701,7 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
currentS += symbolWidth - 1;
|
|
currentS += symbolWidth - 1;
|
|
}
|
|
}
|
|
i++;
|
|
i++;
|
|
- var deltaS = decodeInteger(contextCache, 'IADS', decoder);
|
|
|
|
|
|
+ var deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, 'IADS', decoder);
|
|
if (deltaS === null) {
|
|
if (deltaS === null) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -657,23 +712,25 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) {
|
|
function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) {
|
|
var at = [];
|
|
var at = [];
|
|
- at.push({
|
|
|
|
- x: -patternWidth,
|
|
|
|
- y: 0
|
|
|
|
- });
|
|
|
|
- if (template === 0) {
|
|
|
|
- at.push({
|
|
|
|
- x: -3,
|
|
|
|
- y: -1
|
|
|
|
- });
|
|
|
|
|
|
+ if (!mmr) {
|
|
at.push({
|
|
at.push({
|
|
- x: 2,
|
|
|
|
- y: -2
|
|
|
|
- });
|
|
|
|
- at.push({
|
|
|
|
- x: -2,
|
|
|
|
- y: -2
|
|
|
|
|
|
+ x: -patternWidth,
|
|
|
|
+ y: 0
|
|
});
|
|
});
|
|
|
|
+ if (template === 0) {
|
|
|
|
+ at.push({
|
|
|
|
+ x: -3,
|
|
|
|
+ y: -1
|
|
|
|
+ });
|
|
|
|
+ at.push({
|
|
|
|
+ x: 2,
|
|
|
|
+ y: -2
|
|
|
|
+ });
|
|
|
|
+ at.push({
|
|
|
|
+ x: -2,
|
|
|
|
+ y: -2
|
|
|
|
+ });
|
|
|
|
+ }
|
|
}
|
|
}
|
|
var collectiveWidth = (maxPatternIndex + 1) * patternWidth;
|
|
var collectiveWidth = (maxPatternIndex + 1) * patternWidth;
|
|
var collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext);
|
|
var collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext);
|
|
@@ -722,27 +779,39 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
patternHeight = pattern0.length;
|
|
patternHeight = pattern0.length;
|
|
var bitsPerValue = (0, _util.log2)(numberOfPatterns);
|
|
var bitsPerValue = (0, _util.log2)(numberOfPatterns);
|
|
var at = [];
|
|
var at = [];
|
|
- at.push({
|
|
|
|
- x: template <= 1 ? 3 : 2,
|
|
|
|
- y: -1
|
|
|
|
- });
|
|
|
|
- if (template === 0) {
|
|
|
|
|
|
+ if (!mmr) {
|
|
at.push({
|
|
at.push({
|
|
- x: -3,
|
|
|
|
|
|
+ x: template <= 1 ? 3 : 2,
|
|
y: -1
|
|
y: -1
|
|
});
|
|
});
|
|
- at.push({
|
|
|
|
- x: 2,
|
|
|
|
- y: -2
|
|
|
|
- });
|
|
|
|
- at.push({
|
|
|
|
- x: -2,
|
|
|
|
- y: -2
|
|
|
|
- });
|
|
|
|
|
|
+ if (template === 0) {
|
|
|
|
+ at.push({
|
|
|
|
+ x: -3,
|
|
|
|
+ y: -1
|
|
|
|
+ });
|
|
|
|
+ at.push({
|
|
|
|
+ x: 2,
|
|
|
|
+ y: -2
|
|
|
|
+ });
|
|
|
|
+ at.push({
|
|
|
|
+ x: -2,
|
|
|
|
+ y: -2
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var grayScaleBitPlanes = [],
|
|
|
|
+ mmrInput = void 0,
|
|
|
|
+ bitmap = void 0;
|
|
|
|
+ if (mmr) {
|
|
|
|
+ mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
|
|
}
|
|
}
|
|
- var grayScaleBitPlanes = [];
|
|
|
|
for (i = bitsPerValue - 1; i >= 0; i--) {
|
|
for (i = bitsPerValue - 1; i >= 0; i--) {
|
|
- grayScaleBitPlanes[i] = decodeBitmap(mmr, gridWidth, gridHeight, template, false, skip, at, decodingContext);
|
|
|
|
|
|
+ if (mmr) {
|
|
|
|
+ bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);
|
|
|
|
+ } else {
|
|
|
|
+ bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext);
|
|
|
|
+ }
|
|
|
|
+ grayScaleBitPlanes[i] = bitmap;
|
|
}
|
|
}
|
|
var mg = void 0,
|
|
var mg = void 0,
|
|
ng = void 0,
|
|
ng = void 0,
|
|
@@ -972,7 +1041,8 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
position += 2;
|
|
position += 2;
|
|
textRegion.huffman = !!(textRegionSegmentFlags & 1);
|
|
textRegion.huffman = !!(textRegionSegmentFlags & 1);
|
|
textRegion.refinement = !!(textRegionSegmentFlags & 2);
|
|
textRegion.refinement = !!(textRegionSegmentFlags & 2);
|
|
- textRegion.stripSize = 1 << (textRegionSegmentFlags >> 2 & 3);
|
|
|
|
|
|
+ textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3;
|
|
|
|
+ textRegion.stripSize = 1 << textRegion.logStripSize;
|
|
textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;
|
|
textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;
|
|
textRegion.transposed = !!(textRegionSegmentFlags & 64);
|
|
textRegion.transposed = !!(textRegionSegmentFlags & 64);
|
|
textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;
|
|
textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;
|
|
@@ -989,7 +1059,7 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;
|
|
textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;
|
|
textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;
|
|
textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;
|
|
textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;
|
|
textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;
|
|
- textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 14);
|
|
|
|
|
|
+ textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 0x4000);
|
|
}
|
|
}
|
|
if (textRegion.refinement && !textRegion.refinementTemplate) {
|
|
if (textRegion.refinement && !textRegion.refinementTemplate) {
|
|
at = [];
|
|
at = [];
|
|
@@ -1004,9 +1074,6 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
textRegion.numberOfSymbolInstances = (0, _util.readUint32)(data, position);
|
|
textRegion.numberOfSymbolInstances = (0, _util.readUint32)(data, position);
|
|
position += 4;
|
|
position += 4;
|
|
- if (textRegion.huffman) {
|
|
|
|
- throw new Jbig2Error('huffman is not supported');
|
|
|
|
- }
|
|
|
|
args = [textRegion, header.referredTo, data, position, end];
|
|
args = [textRegion, header.referredTo, data, position, end];
|
|
break;
|
|
break;
|
|
case 16:
|
|
case 16:
|
|
@@ -1094,6 +1161,9 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
break;
|
|
break;
|
|
case 51:
|
|
case 51:
|
|
break;
|
|
break;
|
|
|
|
+ case 53:
|
|
|
|
+ args = [header.number, data, position, end];
|
|
|
|
+ break;
|
|
case 62:
|
|
case 62:
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
@@ -1190,9 +1260,11 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
this.onImmediateGenericRegion.apply(this, arguments);
|
|
this.onImmediateGenericRegion.apply(this, arguments);
|
|
},
|
|
},
|
|
onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {
|
|
onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {
|
|
- var huffmanTables;
|
|
|
|
|
|
+ var huffmanTables = void 0,
|
|
|
|
+ huffmanInput = void 0;
|
|
if (dictionary.huffman) {
|
|
if (dictionary.huffman) {
|
|
- throw new Jbig2Error('huffman is not supported');
|
|
|
|
|
|
+ huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables);
|
|
|
|
+ huffmanInput = new Reader(data, start, end);
|
|
}
|
|
}
|
|
var symbols = this.symbols;
|
|
var symbols = this.symbols;
|
|
if (!symbols) {
|
|
if (!symbols) {
|
|
@@ -1200,22 +1272,33 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
}
|
|
}
|
|
var inputSymbols = [];
|
|
var inputSymbols = [];
|
|
for (var i = 0, ii = referredSegments.length; i < ii; i++) {
|
|
for (var i = 0, ii = referredSegments.length; i < ii; i++) {
|
|
- inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
|
|
|
|
|
|
+ var referredSymbols = symbols[referredSegments[i]];
|
|
|
|
+ if (referredSymbols) {
|
|
|
|
+ inputSymbols = inputSymbols.concat(referredSymbols);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
var decodingContext = new DecodingContext(data, start, end);
|
|
var decodingContext = new DecodingContext(data, start, end);
|
|
- symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext);
|
|
|
|
|
|
+ symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput);
|
|
},
|
|
},
|
|
onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(region, referredSegments, data, start, end) {
|
|
onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(region, referredSegments, data, start, end) {
|
|
var regionInfo = region.info;
|
|
var regionInfo = region.info;
|
|
- var huffmanTables;
|
|
|
|
|
|
+ var huffmanTables = void 0,
|
|
|
|
+ huffmanInput = void 0;
|
|
var symbols = this.symbols;
|
|
var symbols = this.symbols;
|
|
var inputSymbols = [];
|
|
var inputSymbols = [];
|
|
for (var i = 0, ii = referredSegments.length; i < ii; i++) {
|
|
for (var i = 0, ii = referredSegments.length; i < ii; i++) {
|
|
- inputSymbols = inputSymbols.concat(symbols[referredSegments[i]]);
|
|
|
|
|
|
+ var referredSymbols = symbols[referredSegments[i]];
|
|
|
|
+ if (referredSymbols) {
|
|
|
|
+ inputSymbols = inputSymbols.concat(referredSymbols);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
var symbolCodeLength = (0, _util.log2)(inputSymbols.length);
|
|
var symbolCodeLength = (0, _util.log2)(inputSymbols.length);
|
|
|
|
+ if (region.huffman) {
|
|
|
|
+ huffmanInput = new Reader(data, start, end);
|
|
|
|
+ huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput);
|
|
|
|
+ }
|
|
var decodingContext = new DecodingContext(data, start, end);
|
|
var decodingContext = new DecodingContext(data, start, end);
|
|
- var bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext);
|
|
|
|
|
|
+ var bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput);
|
|
this.drawBitmap(regionInfo, bitmap);
|
|
this.drawBitmap(regionInfo, bitmap);
|
|
},
|
|
},
|
|
onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
|
|
onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
|
|
@@ -1238,8 +1321,475 @@ var Jbig2Image = function Jbig2ImageClosure() {
|
|
},
|
|
},
|
|
onImmediateLosslessHalftoneRegion: function onImmediateLosslessHalftoneRegion() {
|
|
onImmediateLosslessHalftoneRegion: function onImmediateLosslessHalftoneRegion() {
|
|
this.onImmediateHalftoneRegion.apply(this, arguments);
|
|
this.onImmediateHalftoneRegion.apply(this, arguments);
|
|
|
|
+ },
|
|
|
|
+ onTables: function onTables(currentSegment, data, start, end) {
|
|
|
|
+ var customTables = this.customTables;
|
|
|
|
+ if (!customTables) {
|
|
|
|
+ this.customTables = customTables = {};
|
|
|
|
+ }
|
|
|
|
+ customTables[currentSegment] = decodeTablesSegment(data, start, end);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ function HuffmanLine(lineData) {
|
|
|
|
+ if (lineData.length === 2) {
|
|
|
|
+ this.isOOB = true;
|
|
|
|
+ this.rangeLow = 0;
|
|
|
|
+ this.prefixLength = lineData[0];
|
|
|
|
+ this.rangeLength = 0;
|
|
|
|
+ this.prefixCode = lineData[1];
|
|
|
|
+ this.isLowerRange = false;
|
|
|
|
+ } else {
|
|
|
|
+ this.isOOB = false;
|
|
|
|
+ this.rangeLow = lineData[0];
|
|
|
|
+ this.prefixLength = lineData[1];
|
|
|
|
+ this.rangeLength = lineData[2];
|
|
|
|
+ this.prefixCode = lineData[3];
|
|
|
|
+ this.isLowerRange = lineData[4] === 'lower';
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ function HuffmanTreeNode(line) {
|
|
|
|
+ this.children = [];
|
|
|
|
+ if (line) {
|
|
|
|
+ this.isLeaf = true;
|
|
|
|
+ this.rangeLength = line.rangeLength;
|
|
|
|
+ this.rangeLow = line.rangeLow;
|
|
|
|
+ this.isLowerRange = line.isLowerRange;
|
|
|
|
+ this.isOOB = line.isOOB;
|
|
|
|
+ } else {
|
|
|
|
+ this.isLeaf = false;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ HuffmanTreeNode.prototype = {
|
|
|
|
+ buildTree: function buildTree(line, shift) {
|
|
|
|
+ var bit = line.prefixCode >> shift & 1;
|
|
|
|
+ if (shift <= 0) {
|
|
|
|
+ this.children[bit] = new HuffmanTreeNode(line);
|
|
|
|
+ } else {
|
|
|
|
+ var node = this.children[bit];
|
|
|
|
+ if (!node) {
|
|
|
|
+ this.children[bit] = node = new HuffmanTreeNode(null);
|
|
|
|
+ }
|
|
|
|
+ node.buildTree(line, shift - 1);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ decodeNode: function decodeNode(reader) {
|
|
|
|
+ if (this.isLeaf) {
|
|
|
|
+ if (this.isOOB) {
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ var htOffset = reader.readBits(this.rangeLength);
|
|
|
|
+ return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);
|
|
|
|
+ }
|
|
|
|
+ var node = this.children[reader.readBit()];
|
|
|
|
+ if (!node) {
|
|
|
|
+ throw new Jbig2Error('invalid Huffman data');
|
|
|
|
+ }
|
|
|
|
+ return node.decodeNode(reader);
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ function HuffmanTable(lines, prefixCodesDone) {
|
|
|
|
+ if (!prefixCodesDone) {
|
|
|
|
+ this.assignPrefixCodes(lines);
|
|
|
|
+ }
|
|
|
|
+ this.rootNode = new HuffmanTreeNode(null);
|
|
|
|
+ var i = void 0,
|
|
|
|
+ ii = lines.length,
|
|
|
|
+ line = void 0;
|
|
|
|
+ for (i = 0; i < ii; i++) {
|
|
|
|
+ line = lines[i];
|
|
|
|
+ if (line.prefixLength > 0) {
|
|
|
|
+ this.rootNode.buildTree(line, line.prefixLength - 1);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ HuffmanTable.prototype = {
|
|
|
|
+ decode: function decode(reader) {
|
|
|
|
+ return this.rootNode.decodeNode(reader);
|
|
|
|
+ },
|
|
|
|
+ assignPrefixCodes: function assignPrefixCodes(lines) {
|
|
|
|
+ var linesLength = lines.length,
|
|
|
|
+ prefixLengthMax = 0,
|
|
|
|
+ i = void 0;
|
|
|
|
+ for (i = 0; i < linesLength; i++) {
|
|
|
|
+ prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);
|
|
|
|
+ }
|
|
|
|
+ var histogram = new Uint32Array(prefixLengthMax + 1);
|
|
|
|
+ for (i = 0; i < linesLength; i++) {
|
|
|
|
+ histogram[lines[i].prefixLength]++;
|
|
|
|
+ }
|
|
|
|
+ var currentLength = 1,
|
|
|
|
+ firstCode = 0,
|
|
|
|
+ currentCode = void 0,
|
|
|
|
+ currentTemp = void 0,
|
|
|
|
+ line = void 0;
|
|
|
|
+ histogram[0] = 0;
|
|
|
|
+ while (currentLength <= prefixLengthMax) {
|
|
|
|
+ firstCode = firstCode + histogram[currentLength - 1] << 1;
|
|
|
|
+ currentCode = firstCode;
|
|
|
|
+ currentTemp = 0;
|
|
|
|
+ while (currentTemp < linesLength) {
|
|
|
|
+ line = lines[currentTemp];
|
|
|
|
+ if (line.prefixLength === currentLength) {
|
|
|
|
+ line.prefixCode = currentCode;
|
|
|
|
+ currentCode++;
|
|
|
|
+ }
|
|
|
|
+ currentTemp++;
|
|
|
|
+ }
|
|
|
|
+ currentLength++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ function decodeTablesSegment(data, start, end) {
|
|
|
|
+ var flags = data[start];
|
|
|
|
+ var lowestValue = (0, _util.readUint32)(data, start + 1) & 0xFFFFFFFF;
|
|
|
|
+ var highestValue = (0, _util.readUint32)(data, start + 5) & 0xFFFFFFFF;
|
|
|
|
+ var reader = new Reader(data, start + 9, end);
|
|
|
|
+ var prefixSizeBits = (flags >> 1 & 7) + 1;
|
|
|
|
+ var rangeSizeBits = (flags >> 4 & 7) + 1;
|
|
|
|
+ var lines = [];
|
|
|
|
+ var prefixLength = void 0,
|
|
|
|
+ rangeLength = void 0,
|
|
|
|
+ currentRangeLow = lowestValue;
|
|
|
|
+ do {
|
|
|
|
+ prefixLength = reader.readBits(prefixSizeBits);
|
|
|
|
+ rangeLength = reader.readBits(rangeSizeBits);
|
|
|
|
+ lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0]));
|
|
|
|
+ currentRangeLow += 1 << rangeLength;
|
|
|
|
+ } while (currentRangeLow < highestValue);
|
|
|
|
+ prefixLength = reader.readBits(prefixSizeBits);
|
|
|
|
+ lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, 'lower']));
|
|
|
|
+ prefixLength = reader.readBits(prefixSizeBits);
|
|
|
|
+ lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));
|
|
|
|
+ if (flags & 1) {
|
|
|
|
+ prefixLength = reader.readBits(prefixSizeBits);
|
|
|
|
+ lines.push(new HuffmanLine([prefixLength, 0]));
|
|
|
|
+ }
|
|
|
|
+ return new HuffmanTable(lines, false);
|
|
|
|
+ }
|
|
|
|
+ var standardTablesCache = {};
|
|
|
|
+ function getStandardTable(number) {
|
|
|
|
+ var table = standardTablesCache[number];
|
|
|
|
+ if (table) {
|
|
|
|
+ return table;
|
|
|
|
+ }
|
|
|
|
+ var lines = void 0;
|
|
|
|
+ switch (number) {
|
|
|
|
+ case 1:
|
|
|
|
+ lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]];
|
|
|
|
+ break;
|
|
|
|
+ case 2:
|
|
|
|
+ lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xE], [11, 5, 6, 0x1E], [75, 6, 32, 0x3E], [6, 0x3F]];
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ lines = [[-256, 8, 8, 0xFE], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xE], [11, 5, 6, 0x1E], [-257, 8, 32, 0xFF, 'lower'], [75, 7, 32, 0x7E], [6, 0x3E]];
|
|
|
|
+ break;
|
|
|
|
+ case 4:
|
|
|
|
+ lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xE], [12, 5, 6, 0x1E], [76, 5, 32, 0x1F]];
|
|
|
|
+ break;
|
|
|
|
+ case 5:
|
|
|
|
+ lines = [[-255, 7, 8, 0x7E], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xE], [12, 5, 6, 0x1E], [-256, 7, 32, 0x7F, 'lower'], [76, 6, 32, 0x3E]];
|
|
|
|
+ break;
|
|
|
|
+ case 6:
|
|
|
|
+ lines = [[-2048, 5, 10, 0x1C], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xA], [-128, 5, 6, 0x1D], [-64, 5, 5, 0x1E], [-32, 4, 5, 0xB], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xC], [1024, 4, 10, 0xD], [-2049, 6, 32, 0x3E, 'lower'], [2048, 6, 32, 0x3F]];
|
|
|
|
+ break;
|
|
|
|
+ case 7:
|
|
|
|
+ lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1A], [-64, 5, 5, 0x1B], [-32, 4, 5, 0xA], [0, 4, 5, 0xB], [32, 5, 5, 0x1C], [64, 5, 6, 0x1D], [128, 4, 7, 0xC], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1E, 'lower'], [2048, 5, 32, 0x1F]];
|
|
|
|
+ break;
|
|
|
|
+ case 8:
|
|
|
|
+ lines = [[-15, 8, 3, 0xFC], [-7, 9, 1, 0x1FC], [-5, 8, 1, 0xFD], [-3, 9, 0, 0x1FD], [-2, 7, 0, 0x7C], [-1, 4, 0, 0xA], [0, 2, 1, 0x0], [2, 5, 0, 0x1A], [3, 6, 0, 0x3A], [4, 3, 4, 0x4], [20, 6, 1, 0x3B], [22, 4, 4, 0xB], [38, 4, 5, 0xC], [70, 5, 6, 0x1B], [134, 5, 7, 0x1C], [262, 6, 7, 0x3C], [390, 7, 8, 0x7D], [646, 6, 10, 0x3D], [-16, 9, 32, 0x1FE, 'lower'], [1670, 9, 32, 0x1FF], [2, 0x1]];
|
|
|
|
+ break;
|
|
|
|
+ case 9:
|
|
|
|
+ lines = [[-31, 8, 4, 0xFC], [-15, 9, 2, 0x1FC], [-11, 8, 2, 0xFD], [-7, 9, 1, 0x1FD], [-5, 7, 1, 0x7C], [-3, 4, 1, 0xA], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1A], [5, 6, 1, 0x3A], [7, 3, 5, 0x4], [39, 6, 2, 0x3B], [43, 4, 5, 0xB], [75, 4, 6, 0xC], [139, 5, 7, 0x1B], [267, 5, 8, 0x1C], [523, 6, 8, 0x3C], [779, 7, 9, 0x7D], [1291, 6, 11, 0x3D], [-32, 9, 32, 0x1FE, 'lower'], [3339, 9, 32, 0x1FF], [2, 0x0]];
|
|
|
|
+ break;
|
|
|
|
+ case 10:
|
|
|
|
+ lines = [[-21, 7, 4, 0x7A], [-5, 8, 0, 0xFC], [-4, 7, 0, 0x7B], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7C], [5, 8, 0, 0xFD], [6, 2, 6, 0x1], [70, 5, 5, 0x1A], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3A], [582, 6, 9, 0x3B], [1094, 6, 10, 0x3C], [2118, 7, 11, 0x7D], [-22, 8, 32, 0xFE, 'lower'], [4166, 8, 32, 0xFF], [2, 0x2]];
|
|
|
|
+ break;
|
|
|
|
+ case 11:
|
|
|
|
+ lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xC], [5, 4, 1, 0xD], [7, 5, 1, 0x1C], [9, 5, 2, 0x1D], [13, 6, 2, 0x3C], [17, 7, 2, 0x7A], [21, 7, 3, 0x7B], [29, 7, 4, 0x7C], [45, 7, 5, 0x7D], [77, 7, 6, 0x7E], [141, 7, 32, 0x7F]];
|
|
|
|
+ break;
|
|
|
|
+ case 12:
|
|
|
|
+ lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1C], [6, 5, 1, 0x1D], [8, 6, 1, 0x3C], [10, 7, 0, 0x7A], [11, 7, 1, 0x7B], [13, 7, 2, 0x7C], [17, 7, 3, 0x7D], [25, 7, 4, 0x7E], [41, 8, 5, 0xFE], [73, 8, 32, 0xFF]];
|
|
|
|
+ break;
|
|
|
|
+ case 13:
|
|
|
|
+ lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xC], [4, 5, 0, 0x1C], [5, 4, 1, 0xD], [7, 3, 3, 0x5], [15, 6, 1, 0x3A], [17, 6, 2, 0x3B], [21, 6, 3, 0x3C], [29, 6, 4, 0x3D], [45, 6, 5, 0x3E], [77, 7, 6, 0x7E], [141, 7, 32, 0x7F]];
|
|
|
|
+ break;
|
|
|
|
+ case 14:
|
|
|
|
+ lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]];
|
|
|
|
+ break;
|
|
|
|
+ case 15:
|
|
|
|
+ lines = [[-24, 7, 4, 0x7C], [-8, 6, 2, 0x3C], [-4, 5, 1, 0x1C], [-2, 4, 0, 0xC], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xD], [3, 5, 1, 0x1D], [5, 6, 2, 0x3D], [9, 7, 4, 0x7D], [-25, 7, 32, 0x7E, 'lower'], [25, 7, 32, 0x7F]];
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('standard table B.' + number + ' does not exist');
|
|
|
|
+ }
|
|
|
|
+ var length = lines.length,
|
|
|
|
+ i = void 0;
|
|
|
|
+ for (i = 0; i < length; i++) {
|
|
|
|
+ lines[i] = new HuffmanLine(lines[i]);
|
|
|
|
+ }
|
|
|
|
+ table = new HuffmanTable(lines, true);
|
|
|
|
+ standardTablesCache[number] = table;
|
|
|
|
+ return table;
|
|
|
|
+ }
|
|
|
|
+ function Reader(data, start, end) {
|
|
|
|
+ this.data = data;
|
|
|
|
+ this.start = start;
|
|
|
|
+ this.end = end;
|
|
|
|
+ this.position = start;
|
|
|
|
+ this.shift = -1;
|
|
|
|
+ this.currentByte = 0;
|
|
|
|
+ }
|
|
|
|
+ Reader.prototype = {
|
|
|
|
+ readBit: function readBit() {
|
|
|
|
+ if (this.shift < 0) {
|
|
|
|
+ if (this.position >= this.end) {
|
|
|
|
+ throw new Jbig2Error('end of data while reading bit');
|
|
|
|
+ }
|
|
|
|
+ this.currentByte = this.data[this.position++];
|
|
|
|
+ this.shift = 7;
|
|
|
|
+ }
|
|
|
|
+ var bit = this.currentByte >> this.shift & 1;
|
|
|
|
+ this.shift--;
|
|
|
|
+ return bit;
|
|
|
|
+ },
|
|
|
|
+ readBits: function readBits(numBits) {
|
|
|
|
+ var result = 0,
|
|
|
|
+ i = void 0;
|
|
|
|
+ for (i = numBits - 1; i >= 0; i--) {
|
|
|
|
+ result |= this.readBit() << i;
|
|
|
|
+ }
|
|
|
|
+ return result;
|
|
|
|
+ },
|
|
|
|
+ byteAlign: function byteAlign() {
|
|
|
|
+ this.shift = -1;
|
|
|
|
+ },
|
|
|
|
+ next: function next() {
|
|
|
|
+ if (this.position >= this.end) {
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+ return this.data[this.position++];
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
+ function getCustomHuffmanTable(index, referredTo, customTables) {
|
|
|
|
+ var currentIndex = 0,
|
|
|
|
+ i = void 0,
|
|
|
|
+ ii = referredTo.length,
|
|
|
|
+ table = void 0;
|
|
|
|
+ for (i = 0; i < ii; i++) {
|
|
|
|
+ table = customTables[referredTo[i]];
|
|
|
|
+ if (table) {
|
|
|
|
+ if (index === currentIndex) {
|
|
|
|
+ return table;
|
|
|
|
+ }
|
|
|
|
+ currentIndex++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ throw new Jbig2Error('can\'t find custom Huffman table');
|
|
|
|
+ }
|
|
|
|
+ function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) {
|
|
|
|
+ var codes = [],
|
|
|
|
+ i = void 0,
|
|
|
|
+ codeLength = void 0;
|
|
|
|
+ for (i = 0; i <= 34; i++) {
|
|
|
|
+ codeLength = reader.readBits(4);
|
|
|
|
+ codes.push(new HuffmanLine([i, codeLength, 0, 0]));
|
|
|
|
+ }
|
|
|
|
+ var runCodesTable = new HuffmanTable(codes, false);
|
|
|
|
+ codes.length = 0;
|
|
|
|
+ for (i = 0; i < numberOfSymbols;) {
|
|
|
|
+ codeLength = runCodesTable.decode(reader);
|
|
|
|
+ if (codeLength >= 32) {
|
|
|
|
+ var repeatedLength = void 0,
|
|
|
|
+ numberOfRepeats = void 0,
|
|
|
|
+ j = void 0;
|
|
|
|
+ switch (codeLength) {
|
|
|
|
+ case 32:
|
|
|
|
+ if (i === 0) {
|
|
|
|
+ throw new Jbig2Error('no previous value in symbol ID table');
|
|
|
|
+ }
|
|
|
|
+ numberOfRepeats = reader.readBits(2) + 3;
|
|
|
|
+ repeatedLength = codes[i - 1].prefixLength;
|
|
|
|
+ break;
|
|
|
|
+ case 33:
|
|
|
|
+ numberOfRepeats = reader.readBits(3) + 3;
|
|
|
|
+ repeatedLength = 0;
|
|
|
|
+ break;
|
|
|
|
+ case 34:
|
|
|
|
+ numberOfRepeats = reader.readBits(7) + 11;
|
|
|
|
+ repeatedLength = 0;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('invalid code length in symbol ID table');
|
|
|
|
+ }
|
|
|
|
+ for (j = 0; j < numberOfRepeats; j++) {
|
|
|
|
+ codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));
|
|
|
|
+ i++;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ codes.push(new HuffmanLine([i, codeLength, 0, 0]));
|
|
|
|
+ i++;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ reader.byteAlign();
|
|
|
|
+ var symbolIDTable = new HuffmanTable(codes, false);
|
|
|
|
+ var customIndex = 0,
|
|
|
|
+ tableFirstS = void 0,
|
|
|
|
+ tableDeltaS = void 0,
|
|
|
|
+ tableDeltaT = void 0;
|
|
|
|
+ switch (textRegion.huffmanFS) {
|
|
|
|
+ case 0:
|
|
|
|
+ case 1:
|
|
|
|
+ tableFirstS = getStandardTable(textRegion.huffmanFS + 6);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ customIndex++;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('invalid Huffman FS selector');
|
|
|
|
+ }
|
|
|
|
+ switch (textRegion.huffmanDS) {
|
|
|
|
+ case 0:
|
|
|
|
+ case 1:
|
|
|
|
+ case 2:
|
|
|
|
+ tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ customIndex++;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('invalid Huffman DS selector');
|
|
|
|
+ }
|
|
|
|
+ switch (textRegion.huffmanDT) {
|
|
|
|
+ case 0:
|
|
|
|
+ case 1:
|
|
|
|
+ case 2:
|
|
|
|
+ tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ customIndex++;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('invalid Huffman DT selector');
|
|
|
|
+ }
|
|
|
|
+ if (textRegion.refinement) {
|
|
|
|
+ throw new Jbig2Error('refinement with Huffman is not supported');
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ symbolIDTable: symbolIDTable,
|
|
|
|
+ tableFirstS: tableFirstS,
|
|
|
|
+ tableDeltaS: tableDeltaS,
|
|
|
|
+ tableDeltaT: tableDeltaT
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) {
|
|
|
|
+ var customIndex = 0,
|
|
|
|
+ tableDeltaHeight = void 0,
|
|
|
|
+ tableDeltaWidth = void 0;
|
|
|
|
+ switch (dictionary.huffmanDHSelector) {
|
|
|
|
+ case 0:
|
|
|
|
+ case 1:
|
|
|
|
+ tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ customIndex++;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('invalid Huffman DH selector');
|
|
|
|
+ }
|
|
|
|
+ switch (dictionary.huffmanDWSelector) {
|
|
|
|
+ case 0:
|
|
|
|
+ case 1:
|
|
|
|
+ tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);
|
|
|
|
+ break;
|
|
|
|
+ case 3:
|
|
|
|
+ tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ customIndex++;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ throw new Jbig2Error('invalid Huffman DW selector');
|
|
|
|
+ }
|
|
|
|
+ var tableBitmapSize = void 0,
|
|
|
|
+ tableAggregateInstances = void 0;
|
|
|
|
+ if (dictionary.bitmapSizeSelector) {
|
|
|
|
+ tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ customIndex++;
|
|
|
|
+ } else {
|
|
|
|
+ tableBitmapSize = getStandardTable(1);
|
|
|
|
+ }
|
|
|
|
+ if (dictionary.aggregationInstancesSelector) {
|
|
|
|
+ tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables);
|
|
|
|
+ } else {
|
|
|
|
+ tableAggregateInstances = getStandardTable(1);
|
|
|
|
+ }
|
|
|
|
+ return {
|
|
|
|
+ tableDeltaHeight: tableDeltaHeight,
|
|
|
|
+ tableDeltaWidth: tableDeltaWidth,
|
|
|
|
+ tableBitmapSize: tableBitmapSize,
|
|
|
|
+ tableAggregateInstances: tableAggregateInstances
|
|
|
|
+ };
|
|
|
|
+ }
|
|
|
|
+ function readUncompressedBitmap(reader, width, height) {
|
|
|
|
+ var bitmap = [],
|
|
|
|
+ x = void 0,
|
|
|
|
+ y = void 0,
|
|
|
|
+ row = void 0;
|
|
|
|
+ for (y = 0; y < height; y++) {
|
|
|
|
+ row = new Uint8Array(width);
|
|
|
|
+ bitmap.push(row);
|
|
|
|
+ for (x = 0; x < width; x++) {
|
|
|
|
+ row[x] = reader.readBit();
|
|
|
|
+ }
|
|
|
|
+ reader.byteAlign();
|
|
|
|
+ }
|
|
|
|
+ return bitmap;
|
|
|
|
+ }
|
|
|
|
+ function decodeMMRBitmap(input, width, height, endOfBlock) {
|
|
|
|
+ var params = {
|
|
|
|
+ K: -1,
|
|
|
|
+ Columns: width,
|
|
|
|
+ Rows: height,
|
|
|
|
+ BlackIs1: true,
|
|
|
|
+ EndOfBlock: endOfBlock
|
|
|
|
+ };
|
|
|
|
+ var decoder = new _ccitt.CCITTFaxDecoder(input, params);
|
|
|
|
+ var bitmap = [],
|
|
|
|
+ x = void 0,
|
|
|
|
+ y = void 0,
|
|
|
|
+ row = void 0,
|
|
|
|
+ currentByte = void 0,
|
|
|
|
+ shift = void 0,
|
|
|
|
+ eof = false;
|
|
|
|
+ for (y = 0; y < height; y++) {
|
|
|
|
+ row = new Uint8Array(width);
|
|
|
|
+ bitmap.push(row);
|
|
|
|
+ shift = -1;
|
|
|
|
+ for (x = 0; x < width; x++) {
|
|
|
|
+ if (shift < 0) {
|
|
|
|
+ currentByte = decoder.readNextChar();
|
|
|
|
+ if (currentByte === -1) {
|
|
|
|
+ currentByte = 0;
|
|
|
|
+ eof = true;
|
|
|
|
+ }
|
|
|
|
+ shift = 7;
|
|
|
|
+ }
|
|
|
|
+ row[x] = currentByte >> shift & 1;
|
|
|
|
+ shift--;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (endOfBlock && !eof) {
|
|
|
|
+ var lookForEOFLimit = 5;
|
|
|
|
+ for (var i = 0; i < lookForEOFLimit; i++) {
|
|
|
|
+ if (decoder.readNextChar() === -1) {
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return bitmap;
|
|
|
|
+ }
|
|
function Jbig2Image() {}
|
|
function Jbig2Image() {}
|
|
Jbig2Image.prototype = {
|
|
Jbig2Image.prototype = {
|
|
parseChunks: function Jbig2Image_parseChunks(chunks) {
|
|
parseChunks: function Jbig2Image_parseChunks(chunks) {
|