pdfjs-dist
Version:
Generic build of Mozilla's PDF.js library.
217 lines (216 loc) • 6.68 kB
JavaScript
/**
* @licstart The following is the entire license notice for the
* JavaScript code in this page
*
* Copyright 2022 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @licend The above is the entire license notice for the
* JavaScript code in this page
*/
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PredictorStream = void 0;
var _decode_stream = require("./decode_stream.js");
var _primitives = require("./primitives.js");
var _util = require("../shared/util.js");
class PredictorStream extends _decode_stream.DecodeStream {
constructor(str, maybeLength, params) {
super(maybeLength);
if (!(params instanceof _primitives.Dict)) {
return str;
}
const predictor = this.predictor = params.get("Predictor") || 1;
if (predictor <= 1) {
return str;
}
if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
throw new _util.FormatError(`Unsupported predictor: ${predictor}`);
}
if (predictor === 2) {
this.readBlock = this.readBlockTiff;
} else {
this.readBlock = this.readBlockPng;
}
this.str = str;
this.dict = str.dict;
const colors = this.colors = params.get("Colors") || 1;
const bits = this.bits = params.get("BPC", "BitsPerComponent") || 8;
const columns = this.columns = params.get("Columns") || 1;
this.pixBytes = colors * bits + 7 >> 3;
this.rowBytes = columns * colors * bits + 7 >> 3;
return this;
}
readBlockTiff() {
const rowBytes = this.rowBytes;
const bufferLength = this.bufferLength;
const buffer = this.ensureBuffer(bufferLength + rowBytes);
const bits = this.bits;
const colors = this.colors;
const rawBytes = this.str.getBytes(rowBytes);
this.eof = !rawBytes.length;
if (this.eof) {
return;
}
let inbuf = 0,
outbuf = 0;
let inbits = 0,
outbits = 0;
let pos = bufferLength;
let i;
if (bits === 1 && colors === 1) {
for (i = 0; i < rowBytes; ++i) {
let c = rawBytes[i] ^ inbuf;
c ^= c >> 1;
c ^= c >> 2;
c ^= c >> 4;
inbuf = (c & 1) << 7;
buffer[pos++] = c;
}
} else if (bits === 8) {
for (i = 0; i < colors; ++i) {
buffer[pos++] = rawBytes[i];
}
for (; i < rowBytes; ++i) {
buffer[pos] = buffer[pos - colors] + rawBytes[i];
pos++;
}
} else if (bits === 16) {
const bytesPerPixel = colors * 2;
for (i = 0; i < bytesPerPixel; ++i) {
buffer[pos++] = rawBytes[i];
}
for (; i < rowBytes; i += 2) {
const sum = ((rawBytes[i] & 0xff) << 8) + (rawBytes[i + 1] & 0xff) + ((buffer[pos - bytesPerPixel] & 0xff) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xff);
buffer[pos++] = sum >> 8 & 0xff;
buffer[pos++] = sum & 0xff;
}
} else {
const compArray = new Uint8Array(colors + 1);
const bitMask = (1 << bits) - 1;
let j = 0,
k = bufferLength;
const columns = this.columns;
for (i = 0; i < columns; ++i) {
for (let kk = 0; kk < colors; ++kk) {
if (inbits < bits) {
inbuf = inbuf << 8 | rawBytes[j++] & 0xff;
inbits += 8;
}
compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;
inbits -= bits;
outbuf = outbuf << bits | compArray[kk];
outbits += bits;
if (outbits >= 8) {
buffer[k++] = outbuf >> outbits - 8 & 0xff;
outbits -= 8;
}
}
}
if (outbits > 0) {
buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);
}
}
this.bufferLength += rowBytes;
}
readBlockPng() {
const rowBytes = this.rowBytes;
const pixBytes = this.pixBytes;
const predictor = this.str.getByte();
const rawBytes = this.str.getBytes(rowBytes);
this.eof = !rawBytes.length;
if (this.eof) {
return;
}
const bufferLength = this.bufferLength;
const buffer = this.ensureBuffer(bufferLength + rowBytes);
let prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
if (prevRow.length === 0) {
prevRow = new Uint8Array(rowBytes);
}
let i,
j = bufferLength,
up,
c;
switch (predictor) {
case 0:
for (i = 0; i < rowBytes; ++i) {
buffer[j++] = rawBytes[i];
}
break;
case 1:
for (i = 0; i < pixBytes; ++i) {
buffer[j++] = rawBytes[i];
}
for (; i < rowBytes; ++i) {
buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xff;
j++;
}
break;
case 2:
for (i = 0; i < rowBytes; ++i) {
buffer[j++] = prevRow[i] + rawBytes[i] & 0xff;
}
break;
case 3:
for (i = 0; i < pixBytes; ++i) {
buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
}
for (; i < rowBytes; ++i) {
buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xff;
j++;
}
break;
case 4:
for (i = 0; i < pixBytes; ++i) {
up = prevRow[i];
c = rawBytes[i];
buffer[j++] = up + c;
}
for (; i < rowBytes; ++i) {
up = prevRow[i];
const upLeft = prevRow[i - pixBytes];
const left = buffer[j - pixBytes];
const p = left + up - upLeft;
let pa = p - left;
if (pa < 0) {
pa = -pa;
}
let pb = p - up;
if (pb < 0) {
pb = -pb;
}
let pc = p - upLeft;
if (pc < 0) {
pc = -pc;
}
c = rawBytes[i];
if (pa <= pb && pa <= pc) {
buffer[j++] = left + c;
} else if (pb <= pc) {
buffer[j++] = up + c;
} else {
buffer[j++] = upLeft + c;
}
}
break;
default:
throw new _util.FormatError(`Unsupported predictor: ${predictor}`);
}
this.bufferLength += rowBytes;
}
}
exports.PredictorStream = PredictorStream;