diff --git a/external/qcms/qcms.js b/external/qcms/qcms.js index 3995a18e3..b19a5da83 100644 --- a/external/qcms/qcms.js +++ b/external/qcms/qcms.js @@ -1,5 +1,5 @@ /* THIS FILE IS GENERATED - DO NOT EDIT */ -import { copy_result, copy_rgb } from './qcms_utils.js'; +import { copy_result, copy_rgb, make_cssRGB } from './qcms_utils.js'; let wasm; @@ -48,9 +48,10 @@ export function qcms_convert_array(transformer, src) { * This function is called directly from JavaScript. * @param {number} transformer * @param {number} src + * @param {boolean} css */ -export function qcms_convert_one(transformer, src) { - wasm.qcms_convert_one(transformer, src); +export function qcms_convert_one(transformer, src, css) { + wasm.qcms_convert_one(transformer, src, css); } /** @@ -61,9 +62,10 @@ export function qcms_convert_one(transformer, src) { * @param {number} src1 * @param {number} src2 * @param {number} src3 + * @param {boolean} css */ -export function qcms_convert_three(transformer, src1, src2, src3) { - wasm.qcms_convert_three(transformer, src1, src2, src3); +export function qcms_convert_three(transformer, src1, src2, src3, css) { + wasm.qcms_convert_three(transformer, src1, src2, src3, css); } /** @@ -75,9 +77,10 @@ export function qcms_convert_three(transformer, src1, src2, src3) { * @param {number} src2 * @param {number} src3 * @param {number} src4 + * @param {boolean} css */ -export function qcms_convert_four(transformer, src1, src2, src3, src4) { - wasm.qcms_convert_four(transformer, src1, src2, src3, src4); +export function qcms_convert_four(transformer, src1, src2, src3, src4, css) { + wasm.qcms_convert_four(transformer, src1, src2, src3, src4, css); } /** @@ -167,6 +170,9 @@ function __wbg_get_imports() { imports.wbg.__wbg_copyrgb_d60ce17bb05d9b67 = function(arg0) { copy_rgb(arg0 >>> 0); }; + imports.wbg.__wbg_makecssRGB_893bf0cd9fdb302d = function(arg0) { + make_cssRGB(arg0 >>> 0); + }; imports.wbg.__wbindgen_init_externref_table = function() { const table = wasm.__wbindgen_export_0; const offset = table.grow(4); diff --git a/external/qcms/qcms_bg.wasm b/external/qcms/qcms_bg.wasm index aa8be2c29..6ed10d710 100644 Binary files a/external/qcms/qcms_bg.wasm and b/external/qcms/qcms_bg.wasm differ diff --git a/external/qcms/qcms_utils.js b/external/qcms/qcms_utils.js index f0b6e679d..11d35351e 100644 --- a/external/qcms/qcms_utils.js +++ b/external/qcms/qcms_utils.js @@ -14,41 +14,71 @@ */ class QCMS { - static _module = null; + static #memoryArray = null; + + static _memory = null; static _mustAddAlpha = false; static _destBuffer = null; + + static _destOffset = 0; + + static _destLength = 0; + + static _cssColor = ""; + + static _makeHexColor = null; + + static get _memoryArray() { + const array = this.#memoryArray; + if (array?.byteLength) { + return array; + } + return (this.#memoryArray = new Uint8Array(this._memory.buffer)); + } } function copy_result(ptr, len) { // This function is called from the wasm module (it's an external // "C" function). Its goal is to copy the result from the wasm memory // to the destination buffer without any intermediate copies. - const { _module, _mustAddAlpha, _destBuffer } = QCMS; - const result = new Uint8Array(_module.memory.buffer, ptr, len); - if (result.length === _destBuffer.length) { - _destBuffer.set(result); + const { _mustAddAlpha, _destBuffer, _destOffset, _destLength, _memoryArray } = + QCMS; + if (len === _destLength) { + _destBuffer.set(_memoryArray.subarray(ptr, ptr + len), _destOffset); return; } if (_mustAddAlpha) { - for (let i = 0, j = 0, ii = result.length; i < ii; i += 3, j += 4) { - _destBuffer[j] = result[i]; - _destBuffer[j + 1] = result[i + 1]; - _destBuffer[j + 2] = result[i + 2]; + for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) { + _destBuffer[j] = _memoryArray[i]; + _destBuffer[j + 1] = _memoryArray[i + 1]; + _destBuffer[j + 2] = _memoryArray[i + 2]; _destBuffer[j + 3] = 255; } } else { - for (let i = 0, j = 0, ii = result.length; i < ii; i += 3, j += 4) { - _destBuffer[j] = result[i]; - _destBuffer[j + 1] = result[i + 1]; - _destBuffer[j + 2] = result[i + 2]; + for (let i = ptr, ii = ptr + len, j = _destOffset; i < ii; i += 3, j += 4) { + _destBuffer[j] = _memoryArray[i]; + _destBuffer[j + 1] = _memoryArray[i + 1]; + _destBuffer[j + 2] = _memoryArray[i + 2]; } } } function copy_rgb(ptr) { - QCMS._destBuffer.set(new Uint8Array(QCMS._module.memory.buffer, ptr, 3)); + const { _destBuffer, _destOffset, _memoryArray } = QCMS; + _destBuffer[_destOffset] = _memoryArray[ptr]; + _destBuffer[_destOffset + 1] = _memoryArray[ptr + 1]; + _destBuffer[_destOffset + 2] = _memoryArray[ptr + 2]; } -export { copy_result, copy_rgb, QCMS }; +function make_cssRGB(ptr) { + const { _memoryArray } = QCMS; + QCMS._cssColor = QCMS._makeHexColor( + _memoryArray[ptr], + _memoryArray[ptr + 1], + _memoryArray[ptr + 2] + ); +} + +export { copy_result, copy_rgb, make_cssRGB, QCMS }; diff --git a/src/core/icc_colorspace.js b/src/core/icc_colorspace.js index d955e3da0..b8ed91a6f 100644 --- a/src/core/icc_colorspace.js +++ b/src/core/icc_colorspace.js @@ -24,7 +24,7 @@ import { qcms_drop_transformer, qcms_transformer_from_memory, } from "../../external/qcms/qcms.js"; -import { shadow, warn } from "../shared/util.js"; +import { shadow, Util, warn } from "../shared/util.js"; import { ColorSpace } from "./colorspace.js"; import { QCMS } from "../../external/qcms/qcms_utils.js"; @@ -63,28 +63,30 @@ class IccColorSpace extends ColorSpace { switch (numComps) { case 1: inType = DataType.Gray8; - this.#convertPixel = (src, srcOffset) => - qcms_convert_one(this.#transformer, src[srcOffset] * 255); + this.#convertPixel = (src, srcOffset, css) => + qcms_convert_one(this.#transformer, src[srcOffset] * 255, css); break; case 3: inType = DataType.RGB8; - this.#convertPixel = (src, srcOffset) => + this.#convertPixel = (src, srcOffset, css) => qcms_convert_three( this.#transformer, src[srcOffset] * 255, src[srcOffset + 1] * 255, - src[srcOffset + 2] * 255 + src[srcOffset + 2] * 255, + css ); break; case 4: inType = DataType.CMYK; - this.#convertPixel = (src, srcOffset) => + this.#convertPixel = (src, srcOffset, css) => qcms_convert_four( this.#transformer, src[srcOffset] * 255, src[srcOffset + 1] * 255, src[srcOffset + 2] * 255, - src[srcOffset + 3] * 255 + src[srcOffset + 3] * 255, + css ); break; default: @@ -101,9 +103,16 @@ class IccColorSpace extends ColorSpace { IccColorSpace.#finalizer.register(this, this.#transformer); } + getRgbHex(src, srcOffset) { + this.#convertPixel(src, srcOffset, /* css */ true); + return QCMS._cssColor; + } + getRgbItem(src, srcOffset, dest, destOffset) { - QCMS._destBuffer = dest.subarray(destOffset, destOffset + 3); - this.#convertPixel(src, srcOffset); + QCMS._destBuffer = dest; + QCMS._destOffset = destOffset; + QCMS._destLength = 3; + this.#convertPixel(src, srcOffset, /* css */ false); QCMS._destBuffer = null; } @@ -116,10 +125,9 @@ class IccColorSpace extends ColorSpace { } } QCMS._mustAddAlpha = alpha01 && dest.buffer === src.buffer; - QCMS._destBuffer = dest.subarray( - destOffset, - destOffset + count * (3 + alpha01) - ); + QCMS._destBuffer = dest; + QCMS._destOffset = destOffset; + QCMS._destLength = count * (3 + alpha01); qcms_convert_array(this.#transformer, src); QCMS._mustAddAlpha = false; QCMS._destBuffer = null; @@ -143,10 +151,12 @@ class IccColorSpace extends ColorSpace { if (this.#useWasm) { if (this.#wasmUrl) { try { - this._module = QCMS._module = initSync({ + this._module = initSync({ module: fetchSync(`${this.#wasmUrl}qcms_bg.wasm`), }); isUsable = !!this._module; + QCMS._memory = this._module.memory; + QCMS._makeHexColor = Util.makeHexColor; } catch (e) { warn(`ICCBased color space: "${e}".`); }