in src/core/jbig2.js [1451:1604]
x: readInt8(data, position),
y: readInt8(data, position + 1),
});
position += 2;
}
genericRegion.at = at;
}
args = [genericRegion, data, position, end];
break;
case 48: // PageInformation
const pageInfo = {
width: readUint32(data, position),
height: readUint32(data, position + 4),
resolutionX: readUint32(data, position + 8),
resolutionY: readUint32(data, position + 12),
};
if (pageInfo.height === 0xffffffff) {
delete pageInfo.height;
}
const pageSegmentFlags = data[position + 16];
readUint16(data, position + 17); // pageStripingInformation
pageInfo.lossless = !!(pageSegmentFlags & 1);
pageInfo.refinement = !!(pageSegmentFlags & 2);
pageInfo.defaultPixelValue = (pageSegmentFlags >> 2) & 1;
pageInfo.combinationOperator = (pageSegmentFlags >> 3) & 3;
pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
args = [pageInfo];
break;
case 49: // EndOfPage
break;
case 50: // EndOfStripe
break;
case 51: // EndOfFile
break;
case 53: // Tables
args = [header.number, data, position, end];
break;
case 62: // 7.4.15 defines 2 extension types which
// are comments and can be ignored.
break;
default:
throw new Jbig2Error(
`segment type ${header.typeName}(${header.type}) is not implemented`
);
}
const callbackName = "on" + header.typeName;
if (callbackName in visitor) {
// eslint-disable-next-line prefer-spread
visitor[callbackName].apply(visitor, args);
}
}
function processSegments(segments, visitor) {
for (let i = 0, ii = segments.length; i < ii; i++) {
processSegment(segments[i], visitor);
}
}
function parseJbig2Chunks(chunks) {
const visitor = new SimpleSegmentVisitor();
for (let i = 0, ii = chunks.length; i < ii; i++) {
const chunk = chunks[i];
const segments = readSegments({}, chunk.data, chunk.start, chunk.end);
processSegments(segments, visitor);
}
return visitor.buffer;
}
function parseJbig2(data) {
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("IMAGE_DECODERS")) {
throw new Error("Not implemented: parseJbig2");
}
const end = data.length;
let position = 0;
if (
data[position] !== 0x97 ||
data[position + 1] !== 0x4a ||
data[position + 2] !== 0x42 ||
data[position + 3] !== 0x32 ||
data[position + 4] !== 0x0d ||
data[position + 5] !== 0x0a ||
data[position + 6] !== 0x1a ||
data[position + 7] !== 0x0a
) {
throw new Jbig2Error("parseJbig2 - invalid header.");
}
const header = Object.create(null);
position += 8;
const flags = data[position++];
header.randomAccess = !(flags & 1);
if (!(flags & 2)) {
header.numberOfPages = readUint32(data, position);
position += 4;
}
const segments = readSegments(header, data, position, end);
const visitor = new SimpleSegmentVisitor();
processSegments(segments, visitor);
const { width, height } = visitor.currentPageInfo;
const bitPacked = visitor.buffer;
const imgData = new Uint8ClampedArray(width * height);
let q = 0,
k = 0;
for (let i = 0; i < height; i++) {
let mask = 0,
buffer;
for (let j = 0; j < width; j++) {
if (!mask) {
mask = 128;
buffer = bitPacked[k++];
}
imgData[q++] = buffer & mask ? 0 : 255;
mask >>= 1;
}
}
return { imgData, width, height };
}
class SimpleSegmentVisitor {
onPageInformation(info) {
this.currentPageInfo = info;
const rowSize = (info.width + 7) >> 3;
const buffer = new Uint8ClampedArray(rowSize * info.height);
// The contents of ArrayBuffers are initialized to 0.
// Fill the buffer with 0xFF only if info.defaultPixelValue is set
if (info.defaultPixelValue) {
buffer.fill(0xff);
}
this.buffer = buffer;
}
drawBitmap(regionInfo, bitmap) {
const pageInfo = this.currentPageInfo;
const width = regionInfo.width,
height = regionInfo.height;
const rowSize = (pageInfo.width + 7) >> 3;
const combinationOperator = pageInfo.combinationOperatorOverride
? regionInfo.combinationOperator
: pageInfo.combinationOperator;
const buffer = this.buffer;
const mask0 = 128 >> (regionInfo.x & 7);
let offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
let i, j, mask, offset;
switch (combinationOperator) {
case 0: // OR
for (i = 0; i < height; i++) {
mask = mask0;
offset = offset0;
for (j = 0; j < width; j++) {