mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-07-27 09:27:20 +02:00
Merge pull request #20613 from calixteman/ccittfax_pdfium
Use the ccittfax decoder from pdfium
This commit is contained in:
commit
1c12b07726
2
external/jbig2/jbig2.js
vendored
2
external/jbig2/jbig2.js
vendored
File diff suppressed because one or more lines are too long
BIN
external/jbig2/jbig2.wasm
vendored
BIN
external/jbig2/jbig2.wasm
vendored
Binary file not shown.
@ -465,20 +465,33 @@ const blackTable3 = [
|
|||||||
* @param {Object} [options] - Decoding options.
|
* @param {Object} [options] - Decoding options.
|
||||||
*/
|
*/
|
||||||
class CCITTFaxDecoder {
|
class CCITTFaxDecoder {
|
||||||
constructor(source, options = {}) {
|
constructor(
|
||||||
|
source,
|
||||||
|
options = {
|
||||||
|
K: 0,
|
||||||
|
EndOfLine: false,
|
||||||
|
EncodedByteAlign: false,
|
||||||
|
Columns: 1728,
|
||||||
|
Rows: 0,
|
||||||
|
EndOfBlock: true,
|
||||||
|
BlackIs1: false,
|
||||||
|
}
|
||||||
|
) {
|
||||||
if (typeof source?.next !== "function") {
|
if (typeof source?.next !== "function") {
|
||||||
throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
|
throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
|
||||||
}
|
}
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.eof = false;
|
this.eof = false;
|
||||||
|
|
||||||
this.encoding = options.K || 0;
|
({
|
||||||
this.eoline = options.EndOfLine || false;
|
K: this.encoding,
|
||||||
this.byteAlign = options.EncodedByteAlign || false;
|
EndOfLine: this.eoline,
|
||||||
this.columns = options.Columns || 1728;
|
EncodedByteAlign: this.byteAlign,
|
||||||
this.rows = options.Rows || 0;
|
Columns: this.columns,
|
||||||
this.eoblock = options.EndOfBlock ?? true;
|
Rows: this.rows,
|
||||||
this.black = options.BlackIs1 || false;
|
EndOfBlock: this.eoblock,
|
||||||
|
BlackIs1: this.black,
|
||||||
|
} = options);
|
||||||
|
|
||||||
this.codingLine = new Uint32Array(this.columns + 1);
|
this.codingLine = new Uint32Array(this.columns + 1);
|
||||||
this.refLine = new Uint32Array(this.columns + 2);
|
this.refLine = new Uint32Array(this.columns + 2);
|
||||||
|
|||||||
@ -13,52 +13,115 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { shadow, warn } from "../shared/util.js";
|
||||||
import { CCITTFaxDecoder } from "./ccitt.js";
|
import { CCITTFaxDecoder } from "./ccitt.js";
|
||||||
import { DecodeStream } from "./decode_stream.js";
|
import { DecodeStream } from "./decode_stream.js";
|
||||||
import { Dict } from "./primitives.js";
|
import { Dict } from "./primitives.js";
|
||||||
|
import { JBig2CCITTFaxWasmImage } from "./jbig2_ccittFax_wasm.js";
|
||||||
|
|
||||||
class CCITTFaxStream extends DecodeStream {
|
class CCITTFaxStream extends DecodeStream {
|
||||||
constructor(str, maybeLength, params) {
|
constructor(str, maybeLength, params) {
|
||||||
super(maybeLength);
|
super(maybeLength);
|
||||||
|
|
||||||
this.stream = str;
|
this.stream = str;
|
||||||
|
this.maybeLength = maybeLength;
|
||||||
this.dict = str.dict;
|
this.dict = str.dict;
|
||||||
|
|
||||||
if (!(params instanceof Dict)) {
|
if (!(params instanceof Dict)) {
|
||||||
params = Dict.empty;
|
params = Dict.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = {
|
this.params = {
|
||||||
next() {
|
K: params.get("K") || 0,
|
||||||
return str.getByte();
|
EndOfLine: !!params.get("EndOfLine"),
|
||||||
},
|
EncodedByteAlign: !!params.get("EncodedByteAlign"),
|
||||||
|
Columns: params.get("Columns") || 1728,
|
||||||
|
Rows: params.get("Rows") || 0,
|
||||||
|
EndOfBlock: !!(params.get("EndOfBlock") ?? true),
|
||||||
|
BlackIs1: !!params.get("BlackIs1"),
|
||||||
};
|
};
|
||||||
this.ccittFaxDecoder = new CCITTFaxDecoder(source, {
|
}
|
||||||
K: params.get("K"),
|
|
||||||
EndOfLine: params.get("EndOfLine"),
|
get bytes() {
|
||||||
EncodedByteAlign: params.get("EncodedByteAlign"),
|
// If `this.maybeLength` is null, we'll get the entire stream.
|
||||||
Columns: params.get("Columns"),
|
return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
|
||||||
Rows: params.get("Rows"),
|
|
||||||
EndOfBlock: params.get("EndOfBlock"),
|
|
||||||
BlackIs1: params.get("BlackIs1"),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readBlock() {
|
readBlock() {
|
||||||
while (!this.eof) {
|
this.decodeImageFallback();
|
||||||
const c = this.ccittFaxDecoder.readNextChar();
|
|
||||||
if (c === -1) {
|
|
||||||
this.eof = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.ensureBuffer(this.bufferLength + 1);
|
|
||||||
this.buffer[this.bufferLength++] = c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get isImageStream() {
|
get isImageStream() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isAsyncDecoder() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async decodeImage(bytes, length, _decoderOptions) {
|
||||||
|
if (this.eof) {
|
||||||
|
return this.buffer;
|
||||||
|
}
|
||||||
|
if (!bytes) {
|
||||||
|
bytes = this.stream.isAsync
|
||||||
|
? (await this.stream.asyncGetBytes()) || this.bytes
|
||||||
|
: this.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.buffer = await JBig2CCITTFaxWasmImage.decode(
|
||||||
|
bytes,
|
||||||
|
this.dict.get("W", "Width"),
|
||||||
|
this.dict.get("H", "Height"),
|
||||||
|
null,
|
||||||
|
this.params
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
warn("CCITTFaxStream: Falling back to JS CCITTFax decoder.");
|
||||||
|
return this.decodeImageFallback(bytes, length);
|
||||||
|
}
|
||||||
|
this.bufferLength = this.buffer.length;
|
||||||
|
this.eof = true;
|
||||||
|
|
||||||
|
return this.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeImageFallback(bytes, length) {
|
||||||
|
if (this.eof) {
|
||||||
|
return this.buffer;
|
||||||
|
}
|
||||||
|
const { params } = this;
|
||||||
|
if (!bytes) {
|
||||||
|
this.stream.reset();
|
||||||
|
bytes = this.bytes;
|
||||||
|
}
|
||||||
|
let pos = 0;
|
||||||
|
const source = {
|
||||||
|
next() {
|
||||||
|
return bytes[pos++] ?? -1;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (length && this.buffer.byteLength < length) {
|
||||||
|
this.buffer = new Uint8Array(length);
|
||||||
|
}
|
||||||
|
this.ccittFaxDecoder = new CCITTFaxDecoder(source, params);
|
||||||
|
let outPos = 0;
|
||||||
|
while (!this.eof) {
|
||||||
|
const c = this.ccittFaxDecoder.readNextChar();
|
||||||
|
if (c === -1) {
|
||||||
|
this.eof = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!length) {
|
||||||
|
this.ensureBuffer(outPos + 1);
|
||||||
|
}
|
||||||
|
this.buffer[outPos++] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bufferLength = this.buffer.length;
|
||||||
|
return this.buffer.subarray(0, length || this.bufferLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { CCITTFaxStream };
|
export { CCITTFaxStream };
|
||||||
|
|||||||
@ -102,12 +102,12 @@ class DecodeStream extends BaseStream {
|
|||||||
async getImageData(length, decoderOptions) {
|
async getImageData(length, decoderOptions) {
|
||||||
if (!this.canAsyncDecodeImageFromBuffer) {
|
if (!this.canAsyncDecodeImageFromBuffer) {
|
||||||
if (this.isAsyncDecoder) {
|
if (this.isAsyncDecoder) {
|
||||||
return this.decodeImage(null, decoderOptions);
|
return this.decodeImage(null, length, decoderOptions);
|
||||||
}
|
}
|
||||||
return this.getBytes(length, decoderOptions);
|
return this.getBytes(length, decoderOptions);
|
||||||
}
|
}
|
||||||
const data = await this.stream.asyncGetBytes();
|
const data = await this.stream.asyncGetBytes();
|
||||||
return this.decodeImage(data, decoderOptions);
|
return this.decodeImage(data, length, decoderOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
async asyncGetBytesFromDecompressionStream(name) {
|
async asyncGetBytesFromDecompressionStream(name) {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class JBig2Error extends BaseException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class JBig2WasmImage {
|
class JBig2CCITTFaxWasmImage {
|
||||||
static #buffer = null;
|
static #buffer = null;
|
||||||
|
|
||||||
static #handler = null;
|
static #handler = null;
|
||||||
@ -69,7 +69,7 @@ class JBig2WasmImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async decode(bytes, width, height, globals) {
|
static async decode(bytes, width, height, globals, CCITTOptions) {
|
||||||
if (!this.#modulePromise) {
|
if (!this.#modulePromise) {
|
||||||
const { promise, resolve } = Promise.withResolvers();
|
const { promise, resolve } = Promise.withResolvers();
|
||||||
const promises = [promise];
|
const promises = [promise];
|
||||||
@ -95,13 +95,28 @@ class JBig2WasmImage {
|
|||||||
const size = bytes.length;
|
const size = bytes.length;
|
||||||
ptr = module._malloc(size);
|
ptr = module._malloc(size);
|
||||||
module.writeArrayToMemory(bytes, ptr);
|
module.writeArrayToMemory(bytes, ptr);
|
||||||
|
|
||||||
|
if (CCITTOptions) {
|
||||||
|
module._ccitt_decode(
|
||||||
|
ptr,
|
||||||
|
size,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
CCITTOptions.K,
|
||||||
|
CCITTOptions.EndOfLine ? 1 : 0,
|
||||||
|
CCITTOptions.EncodedByteAlign ? 1 : 0,
|
||||||
|
CCITTOptions.BlackIs1 ? 1 : 0,
|
||||||
|
CCITTOptions.Columns,
|
||||||
|
CCITTOptions.Rows
|
||||||
|
);
|
||||||
|
} else {
|
||||||
const globalsSize = globals ? globals.length : 0;
|
const globalsSize = globals ? globals.length : 0;
|
||||||
if (globalsSize > 0) {
|
if (globalsSize > 0) {
|
||||||
globalsPtr = module._malloc(globalsSize);
|
globalsPtr = module._malloc(globalsSize);
|
||||||
module.writeArrayToMemory(globals, globalsPtr);
|
module.writeArrayToMemory(globals, globalsPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
module._jbig2_decode(ptr, size, width, height, globalsPtr, globalsSize);
|
module._jbig2_decode(ptr, size, width, height, globalsPtr, globalsSize);
|
||||||
|
}
|
||||||
if (!module.imageData) {
|
if (!module.imageData) {
|
||||||
throw new JBig2Error("Unknown error");
|
throw new JBig2Error("Unknown error");
|
||||||
}
|
}
|
||||||
@ -124,4 +139,4 @@ class JBig2WasmImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { JBig2Error, JBig2WasmImage };
|
export { JBig2CCITTFaxWasmImage, JBig2Error };
|
||||||
@ -17,8 +17,8 @@ import { shadow, warn } from "../shared/util.js";
|
|||||||
import { BaseStream } from "./base_stream.js";
|
import { BaseStream } from "./base_stream.js";
|
||||||
import { DecodeStream } from "./decode_stream.js";
|
import { DecodeStream } from "./decode_stream.js";
|
||||||
import { Dict } from "./primitives.js";
|
import { Dict } from "./primitives.js";
|
||||||
|
import { JBig2CCITTFaxWasmImage } from "./jbig2_ccittFax_wasm.js";
|
||||||
import { Jbig2Image } from "./jbig2.js";
|
import { Jbig2Image } from "./jbig2.js";
|
||||||
import { JBig2WasmImage } from "./jbig2_wasm.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For JBIG2's we use a library to decode these images and
|
* For JBIG2's we use a library to decode these images and
|
||||||
@ -45,7 +45,7 @@ class Jbig2Stream extends DecodeStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
readBlock() {
|
readBlock() {
|
||||||
this.decodeImage();
|
this.decodeImageFallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
get isAsyncDecoder() {
|
get isAsyncDecoder() {
|
||||||
@ -56,7 +56,7 @@ class Jbig2Stream extends DecodeStream {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async decodeImage(bytes, _decoderOptions) {
|
async decodeImage(bytes, length, _decoderOptions) {
|
||||||
if (this.eof) {
|
if (this.eof) {
|
||||||
return this.buffer;
|
return this.buffer;
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ class Jbig2Stream extends DecodeStream {
|
|||||||
globals = globalsStream.getBytes();
|
globals = globalsStream.getBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.buffer = await JBig2WasmImage.decode(
|
this.buffer = await JBig2CCITTFaxWasmImage.decode(
|
||||||
bytes,
|
bytes,
|
||||||
this.dict.get("Width"),
|
this.dict.get("Width"),
|
||||||
this.dict.get("Height"),
|
this.dict.get("Height"),
|
||||||
@ -77,7 +77,7 @@ class Jbig2Stream extends DecodeStream {
|
|||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
warn("Jbig2Stream: Falling back to JS JBIG2 decoder.");
|
warn("Jbig2Stream: Falling back to JS JBIG2 decoder.");
|
||||||
return this.decodeImageFallback(bytes);
|
return this.decodeImageFallback(bytes, length);
|
||||||
}
|
}
|
||||||
this.bufferLength = this.buffer.length;
|
this.bufferLength = this.buffer.length;
|
||||||
this.eof = true;
|
this.eof = true;
|
||||||
@ -85,7 +85,7 @@ class Jbig2Stream extends DecodeStream {
|
|||||||
return this.buffer;
|
return this.buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
async decodeImageFallback(bytes) {
|
decodeImageFallback(bytes, _length) {
|
||||||
if (this.eof) {
|
if (this.eof) {
|
||||||
return this.buffer;
|
return this.buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class JpxStream extends DecodeStream {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async decodeImage(bytes, decoderOptions) {
|
async decodeImage(bytes, _length, decoderOptions) {
|
||||||
if (this.eof) {
|
if (this.eof) {
|
||||||
return this.buffer;
|
return this.buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import {
|
|||||||
} from "../shared/util.js";
|
} from "../shared/util.js";
|
||||||
import { ChunkedStreamManager } from "./chunked_stream.js";
|
import { ChunkedStreamManager } from "./chunked_stream.js";
|
||||||
import { ImageResizer } from "./image_resizer.js";
|
import { ImageResizer } from "./image_resizer.js";
|
||||||
import { JBig2WasmImage } from "./jbig2_wasm.js";
|
import { JBig2CCITTFaxWasmImage } from "./jbig2_ccittFax_wasm.js";
|
||||||
import { JpegStream } from "./jpeg_stream.js";
|
import { JpegStream } from "./jpeg_stream.js";
|
||||||
import { JpxImage } from "./jpx.js";
|
import { JpxImage } from "./jpx.js";
|
||||||
import { MissingDataException } from "./core_utils.js";
|
import { MissingDataException } from "./core_utils.js";
|
||||||
@ -82,7 +82,7 @@ class BasePdfManager {
|
|||||||
JpxImage.setOptions(options);
|
JpxImage.setOptions(options);
|
||||||
IccColorSpace.setOptions(options);
|
IccColorSpace.setOptions(options);
|
||||||
CmykICCBasedCS.setOptions(options);
|
CmykICCBasedCS.setOptions(options);
|
||||||
JBig2WasmImage.setOptions(options);
|
JBig2CCITTFaxWasmImage.setOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
get docId() {
|
get docId() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user