diff --git a/cli/src/codecs.js b/cli/src/codecs.js index 854668f2..2be8cac0 100644 --- a/cli/src/codecs.js +++ b/cli/src/codecs.js @@ -20,12 +20,15 @@ import avifDec from "../../codecs/avif/dec/avif_dec.js"; import avifDecWasm from "asset-url:../../codecs/avif/dec/avif_dec.wasm"; // PNG -import pngEncDecInit, { - encode as pngEncode, - decode as pngDecode -} from "../../codecs/png/pkg/squoosh_png.js"; +import * as pngEncDec from "../../codecs/png/pkg/squoosh_png.js"; import pngEncDecWasm from "asset-url:../../codecs/png/pkg/squoosh_png_bg.wasm"; -const pngEncDecPromise = pngEncDecInit(fsp.readFile(pathify(pngEncDecWasm))); +const pngEncDecPromise = pngEncDec.default( + fsp.readFile(pathify(pngEncDecWasm)) +); + +import * as oxipng from "../../codecs/oxipng/pkg/squoosh_oxipng.js"; +import oxipngWasm from "asset-url:../../codecs/oxipng/pkg/squoosh_oxipng_bg.wasm"; +const oxipngPromise = oxipng.default(fsp.readFile(pathify(oxipngWasm))); // Our decoders currently rely on a `ImageData` global. import ImageData from "./image_data.js"; @@ -123,21 +126,28 @@ export default { max: 62 } }, - png: { - name: "PNG", + oxipng: { + name: "OxiPNG", extension: "png", detectors: [/^\x89PNG\x0D\x0A\x1A\x0A/], dec: async () => { await pngEncDecPromise; - return { decode: (...args) => pngDecode(...args) }; + return { decode: pngEncDec.decode }; }, enc: async () => { await pngEncDecPromise; + await oxipngPromise; return { - encode: (buffer, ...args) => - new Uint8Array(pngEncode(new Uint8Array(buffer), ...args)) + encode: (buffer, width, height, opts) => { + const simplePng = new Uint8Array( + pngEncDec.encode(new Uint8Array(buffer), width, height) + ); + return new Uint8Array(oxipng.optimise(simplePng, opts.level)); + } }; }, - defaultEncoderOptions: {} + defaultEncoderOptions: { + level: 2 + } } }; diff --git a/codecs/oxipng/package.json b/codecs/oxipng/package.json index 552448fd..adce0fe0 100644 --- a/codecs/oxipng/package.json +++ b/codecs/oxipng/package.json @@ -1,6 +1,6 @@ { "name": "oxipng", "scripts": { - "build": "../build-rust.sh" + "build": "../build-rust.sh rm -rf pkg && wasm-pack build --debug --target web -- --verbose --locked && rm pkg/.gitignore" } } diff --git a/codecs/oxipng/pkg/squoosh_oxipng.d.ts b/codecs/oxipng/pkg/squoosh_oxipng.d.ts index 1c95bae4..196593fb 100644 --- a/codecs/oxipng/pkg/squoosh_oxipng.d.ts +++ b/codecs/oxipng/pkg/squoosh_oxipng.d.ts @@ -6,3 +6,25 @@ * @returns {Uint8Array} */ export function optimise(data: Uint8Array, level: number): Uint8Array; + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly optimise: (a: number, b: number, c: number, d: number) => void; + readonly malloc: (a: number) => number; + readonly free: (a: number) => void; + readonly __wbindgen_malloc: (a: number) => number; + readonly __wbindgen_free: (a: number, b: number) => void; +} + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {InitInput | Promise} module_or_path +* +* @returns {Promise} +*/ +export default function init (module_or_path?: InitInput | Promise): Promise; + \ No newline at end of file diff --git a/codecs/oxipng/pkg/squoosh_oxipng.js b/codecs/oxipng/pkg/squoosh_oxipng.js index 24abe864..62519eb6 100644 --- a/codecs/oxipng/pkg/squoosh_oxipng.js +++ b/codecs/oxipng/pkg/squoosh_oxipng.js @@ -1,2 +1,117 @@ -import * as wasm from "./squoosh_oxipng_bg.wasm"; -export * from "./squoosh_oxipng_bg.js"; \ No newline at end of file + +let wasm; + +let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + +cachedTextDecoder.decode(); + +let cachegetUint8Memory0 = null; +function getUint8Memory0() { + if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) { + cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachegetUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +let WASM_VECTOR_LEN = 0; + +function passArray8ToWasm0(arg, malloc) { + const ptr = malloc(arg.length * 1); + getUint8Memory0().set(arg, ptr / 1); + WASM_VECTOR_LEN = arg.length; + return ptr; +} + +function _assertNum(n) { + if (typeof(n) !== 'number') throw new Error('expected a number argument'); +} + +let cachegetInt32Memory0 = null; +function getInt32Memory0() { + if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) { + cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachegetInt32Memory0; +} + +function getArrayU8FromWasm0(ptr, len) { + return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); +} +/** +* @param {Uint8Array} data +* @param {number} level +* @returns {Uint8Array} +*/ +export function optimise(data, level) { + var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); + var len0 = WASM_VECTOR_LEN; + _assertNum(level); + wasm.optimise(8, ptr0, len0, level); + var r0 = getInt32Memory0()[8 / 4 + 0]; + var r1 = getInt32Memory0()[8 / 4 + 1]; + var v1 = getArrayU8FromWasm0(r0, r1).slice(); + wasm.__wbindgen_free(r0, r1 * 1); + return v1; +} + +async function load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +async function init(input) { + if (typeof input === 'undefined') { + input = import.meta.url.replace(/\.js$/, '_bg.wasm'); + } + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + const { instance, module } = await load(await input, imports); + + wasm = instance.exports; + init.__wbindgen_wasm_module = module; + + return wasm; +} + +export default init; + diff --git a/codecs/oxipng/pkg/squoosh_oxipng_bg.js b/codecs/oxipng/pkg/squoosh_oxipng_bg.js deleted file mode 100644 index 87154f54..00000000 --- a/codecs/oxipng/pkg/squoosh_oxipng_bg.js +++ /dev/null @@ -1,60 +0,0 @@ -import * as wasm from './squoosh_oxipng_bg.wasm'; - -const lTextDecoder = typeof TextDecoder === 'undefined' ? (0, module.require)('util').TextDecoder : TextDecoder; - -let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true }); - -cachedTextDecoder.decode(); - -let cachegetUint8Memory0 = null; -function getUint8Memory0() { - if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) { - cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer); - } - return cachegetUint8Memory0; -} - -function getStringFromWasm0(ptr, len) { - return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); -} - -let WASM_VECTOR_LEN = 0; - -function passArray8ToWasm0(arg, malloc) { - const ptr = malloc(arg.length * 1); - getUint8Memory0().set(arg, ptr / 1); - WASM_VECTOR_LEN = arg.length; - return ptr; -} - -let cachegetInt32Memory0 = null; -function getInt32Memory0() { - if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) { - cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer); - } - return cachegetInt32Memory0; -} - -function getArrayU8FromWasm0(ptr, len) { - return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); -} -/** -* @param {Uint8Array} data -* @param {number} level -* @returns {Uint8Array} -*/ -export function optimise(data, level) { - var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); - var len0 = WASM_VECTOR_LEN; - wasm.optimise(8, ptr0, len0, level); - var r0 = getInt32Memory0()[8 / 4 + 0]; - var r1 = getInt32Memory0()[8 / 4 + 1]; - var v1 = getArrayU8FromWasm0(r0, r1).slice(); - wasm.__wbindgen_free(r0, r1 * 1); - return v1; -} - -export const __wbindgen_throw = function(arg0, arg1) { - throw new Error(getStringFromWasm0(arg0, arg1)); -}; - diff --git a/codecs/oxipng/pkg/squoosh_oxipng_bg.wasm b/codecs/oxipng/pkg/squoosh_oxipng_bg.wasm index 7b1309eb..437bb3b1 100644 Binary files a/codecs/oxipng/pkg/squoosh_oxipng_bg.wasm and b/codecs/oxipng/pkg/squoosh_oxipng_bg.wasm differ