1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-28 23:28:16 +02:00

[api-major] Add openjpeg.wasm to pdf.js (bug 1935076)

In order to fix bug 1935076, we'll have to add a pure js fallback in case wasm is disabled
or simd isn't supported. Unfortunately, this fallback will take some space.

So, the main goal of this patch is to reduce the overall size (by ~93k).
As a side effect, it should make easier to use an other wasm file (which must export
_jp2_decode, _malloc and _free).
This commit is contained in:
Calixte Denizet 2025-01-15 20:20:11 +01:00
parent 711bf2bd12
commit 94b4b54ef6
21 changed files with 274 additions and 19 deletions

View file

@ -24,20 +24,97 @@ class JpxError extends BaseException {
}
class JpxImage {
static #module = null;
static #buffer = null;
static decode(data, decoderOptions) {
decoderOptions ||= {};
this.#module ||= OpenJPEG({ warn });
const imageData = this.#module.decode(data, decoderOptions);
if (typeof imageData === "string") {
throw new JpxError(imageData);
static #handler = null;
static #instantiationFailed = false;
static #modulePromise = null;
static #wasmUrl = null;
static setOptions({ handler, wasmUrl }) {
if (!this.#buffer) {
this.#wasmUrl = wasmUrl || null;
if (wasmUrl === null) {
this.#handler = handler;
}
}
}
static async #instantiateWasm(imports, successCallback) {
try {
if (!this.#buffer) {
if (this.#wasmUrl !== null) {
const response = await fetch(`${this.#wasmUrl}openjpeg.wasm`);
this.#buffer = await response.arrayBuffer();
} else {
this.#buffer = await this.#handler.sendWithPromise("FetchWasm", {
filename: "openjpeg.wasm",
});
}
}
const results = await WebAssembly.instantiate(this.#buffer, imports);
return successCallback(results.instance);
} catch (e) {
this.#instantiationFailed = true;
warn(`Cannot load openjpeg.wasm: "${e}".`);
return false;
} finally {
this.#handler = null;
this.#wasmUrl = null;
}
}
static async decode(
bytes,
{ numComponents = 4, isIndexedColormap = false, smaskInData = false } = {}
) {
if (this.#instantiationFailed) {
throw new JpxError("OpenJPEG failed to instantiate.");
}
this.#modulePromise ||= OpenJPEG({
warn,
instantiateWasm: this.#instantiateWasm.bind(this),
});
const module = await this.#modulePromise;
let ptr;
try {
const size = bytes.length;
ptr = module._malloc(size);
module.HEAPU8.set(bytes, ptr);
const ret = module._jp2_decode(
ptr,
size,
numComponents > 0 ? numComponents : 0,
!!isIndexedColormap,
!!smaskInData
);
if (ret) {
const { errorMessages } = module;
if (errorMessages) {
delete module.errorMessages;
throw new JpxError(errorMessages);
}
throw new JpxError("Unknown error");
}
const { imageData } = module;
module.imageData = null;
return imageData;
} finally {
if (ptr) {
module._free(ptr);
}
}
return imageData;
}
static cleanup() {
this.#module = null;
this.#modulePromise = null;
}
static parseImageProperties(stream) {