Compare commits

..

No commits in common. "1c12b0772600da2e710d3b6a4406a67b6f4aedb8" and "bfd17b25868485c6e5024600cb43c766abda7fd3" have entirely different histories.

9 changed files with 51 additions and 142 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -465,33 +465,20 @@ const blackTable3 = [
* @param {Object} [options] - Decoding options. * @param {Object} [options] - Decoding options.
*/ */
class CCITTFaxDecoder { class CCITTFaxDecoder {
constructor( constructor(source, options = {}) {
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;
K: this.encoding, this.eoline = options.EndOfLine || false;
EndOfLine: this.eoline, this.byteAlign = options.EncodedByteAlign || false;
EncodedByteAlign: this.byteAlign, this.columns = options.Columns || 1728;
Columns: this.columns, this.rows = options.Rows || 0;
Rows: this.rows, this.eoblock = options.EndOfBlock ?? true;
EndOfBlock: this.eoblock, this.black = options.BlackIs1 || false;
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);

View File

@ -13,115 +13,52 @@
* 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;
} }
this.params = { const source = {
K: params.get("K") || 0, next() {
EndOfLine: !!params.get("EndOfLine"), return str.getByte();
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"),
get bytes() { EndOfLine: params.get("EndOfLine"),
// If `this.maybeLength` is null, we'll get the entire stream. EncodedByteAlign: params.get("EncodedByteAlign"),
return shadow(this, "bytes", this.stream.getBytes(this.maybeLength)); Columns: params.get("Columns"),
Rows: params.get("Rows"),
EndOfBlock: params.get("EndOfBlock"),
BlackIs1: params.get("BlackIs1"),
});
} }
readBlock() { readBlock() {
this.decodeImageFallback(); while (!this.eof) {
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 };

View File

@ -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, length, decoderOptions); return this.decodeImage(null, 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, length, decoderOptions); return this.decodeImage(data, decoderOptions);
} }
async asyncGetBytesFromDecompressionStream(name) { async asyncGetBytesFromDecompressionStream(name) {

View File

@ -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.decodeImageFallback(); this.decodeImage();
} }
get isAsyncDecoder() { get isAsyncDecoder() {
@ -56,7 +56,7 @@ class Jbig2Stream extends DecodeStream {
return true; return true;
} }
async decodeImage(bytes, length, _decoderOptions) { async decodeImage(bytes, _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 JBig2CCITTFaxWasmImage.decode( this.buffer = await JBig2WasmImage.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, length); return this.decodeImageFallback(bytes);
} }
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;
} }
decodeImageFallback(bytes, _length) { async decodeImageFallback(bytes) {
if (this.eof) { if (this.eof) {
return this.buffer; return this.buffer;
} }

View File

@ -23,7 +23,7 @@ class JBig2Error extends BaseException {
} }
} }
class JBig2CCITTFaxWasmImage { class JBig2WasmImage {
static #buffer = null; static #buffer = null;
static #handler = null; static #handler = null;
@ -69,7 +69,7 @@ class JBig2CCITTFaxWasmImage {
} }
} }
static async decode(bytes, width, height, globals, CCITTOptions) { static async decode(bytes, width, height, globals) {
if (!this.#modulePromise) { if (!this.#modulePromise) {
const { promise, resolve } = Promise.withResolvers(); const { promise, resolve } = Promise.withResolvers();
const promises = [promise]; const promises = [promise];
@ -95,28 +95,13 @@ class JBig2CCITTFaxWasmImage {
const size = bytes.length; const size = bytes.length;
ptr = module._malloc(size); ptr = module._malloc(size);
module.writeArrayToMemory(bytes, ptr); module.writeArrayToMemory(bytes, ptr);
const globalsSize = globals ? globals.length : 0;
if (CCITTOptions) { if (globalsSize > 0) {
module._ccitt_decode( globalsPtr = module._malloc(globalsSize);
ptr, module.writeArrayToMemory(globals, globalsPtr);
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;
if (globalsSize > 0) {
globalsPtr = module._malloc(globalsSize);
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");
} }
@ -139,4 +124,4 @@ class JBig2CCITTFaxWasmImage {
} }
} }
export { JBig2CCITTFaxWasmImage, JBig2Error }; export { JBig2Error, JBig2WasmImage };

View File

@ -49,7 +49,7 @@ class JpxStream extends DecodeStream {
return true; return true;
} }
async decodeImage(bytes, _length, decoderOptions) { async decodeImage(bytes, decoderOptions) {
if (this.eof) { if (this.eof) {
return this.buffer; return this.buffer;
} }

View File

@ -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 { JBig2CCITTFaxWasmImage } from "./jbig2_ccittFax_wasm.js"; import { JBig2WasmImage } from "./jbig2_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);
JBig2CCITTFaxWasmImage.setOptions(options); JBig2WasmImage.setOptions(options);
} }
get docId() { get docId() {