Compare commits

...

34 Commits

Author SHA1 Message Date
Surma
5bc80e66ec Merge remote-tracking branch 'origin/dev' into visdif-error 2021-06-16 13:54:49 +01:00
Surma
b1f50cd27c Fix AVIF auto optimizer options 2021-06-16 13:54:17 +01:00
Surma
3d136016e2 Provide optimizer default value 2021-06-16 13:44:24 +01:00
Surma
14a715e952 Add test files for now 2021-06-16 12:56:37 +01:00
Surma
324b04d398 Merge pull request #1044 from ergunsh/libsquoosh-codecs-to-ts
Typescriptify libsquoosh's codecs.js and emscripten-utils.js
2021-06-16 11:47:21 +01:00
Surma
eb76fbc4bc Merge branch 'dev' into libsquoosh-codecs-to-ts 2021-06-16 11:43:35 +01:00
Jake Archibald
1d292468b0 Everything supports ResizeObserver now 2021-06-16 10:13:46 +01:00
Jake Archibald
828f9a5eeb Fix memory leaks (#1054) 2021-06-15 10:45:53 +01:00
Surma
5595525c8a Merge pull request #1053 from alex-drocks/patch-1
Update README.md @libSquoosh code example
2021-06-11 16:25:23 +01:00
Alexandre Desroches
5e14444b13 Update README.md
To close typo in example code as reported in issue #1051
2021-06-11 09:36:30 -04:00
Ergün Erdoğmuş
3d58c616af Merge branch 'dev' into libsquoosh-codecs-to-ts 2021-06-10 18:31:02 +02:00
Surma
d7090042a6 Fix alignment issue 2021-06-10 12:25:58 -04:00
Surma
be3249bf2f Add test case 2021-06-10 11:31:59 -04:00
ergunsh
1b59c3f47a Keep js extension while importing module & types 2021-06-09 18:11:30 +02:00
Surma
9a37cc7959 Merge pull request #1042 from GoogleChromeLabs/issue-1022 2021-06-09 12:17:00 +01:00
Surma
ffb9135a7a Merge remote-tracking branch 'origin/dev' into issue-1022 2021-06-09 06:35:00 -04:00
ergunsh
5707eeff41 Return Uint8ClampedArray in resize operation 2021-06-08 20:28:22 +02:00
ergunsh
a18ed360eb Address review comments
* Updated import to contain file extension `js`
* Separated WebAssembly definitions from missing-types
* Converted resizer.resize result to Uint8ClampedArray
* Moved ResizeInstantiateOptions to an interface
2021-06-08 20:09:37 +02:00
Surma
011d0c2099 Update AVIF 2021-06-08 16:51:08 +01:00
Surma
89105bbb22 Update wp2 2021-06-08 11:07:32 -04:00
Surma
5f7c619413 Update webp 2021-06-08 11:02:43 -04:00
Surma
3ec7d4db16 Update visdif 2021-06-08 10:59:47 -04:00
Surma
8ef8cef522 Update MozJPEG 2021-06-08 10:58:10 -04:00
Surma
f6431d8147 Update JXL 2021-06-08 10:54:16 -04:00
Surma
be037754ce Update imagequant 2021-06-08 10:43:33 -04:00
Surma
32107124e6 Update Emscripten version 2021-06-08 10:43:11 -04:00
ergunsh
1af5d1fa7b Typescriptify libsquoosh's codecs and emscripten-utils 2021-06-04 19:12:31 +02:00
Surma
5df04f6419 Update wp2 2021-06-04 09:51:10 -04:00
Surma
cf570a4d3f Update webp 2021-06-04 09:29:16 -04:00
Surma
2aa691339c Update visdif 2021-06-04 09:25:57 -04:00
Surma
9fcb4a4c55 Update mozjpeg 2021-06-04 09:23:23 -04:00
Surma
18e3d77aef Update jxl 2021-06-04 09:18:27 -04:00
Surma
6a4982bf4c Update imagequant 2021-06-04 08:52:46 -04:00
Surma
c7b998a877 Add flags 2021-06-04 08:33:57 -04:00
84 changed files with 9204 additions and 1493 deletions

View File

@@ -10,6 +10,9 @@ export CODEC_DIR = node_modules/libavif
export BUILD_DIR = node_modules/build
export LIBAOM_DIR = node_modules/libaom
override CFLAGS += "-Wno-unused-macros"
export
OUT_ENC_JS = enc/avif_enc.js
OUT_NODE_ENC_JS = enc/avif_node_enc.js
OUT_ENC_MT_JS = enc/avif_enc_mt.js

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./avif_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./avif_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1,13 +1,13 @@
FROM emscripten/emsdk:2.0.21
FROM emscripten/emsdk:2.0.23
RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config
ENV CFLAGS "-O3 -flto"
ENV CXXFLAGS "${CFLAGS} -std=c++17"
ENV LDFLAGS "${CFLAGS} \
--closure 1 \
-s FILESYSTEM=0 \
-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
-s ALLOW_MEMORY_GROWTH=1 \
-s TEXTDECODER=2 \
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \
"
# Build and cache standard libraries with these flags + Embind.
RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -xc++ /dev/null -o /dev/null

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt_simd.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt_simd.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -9,9 +9,9 @@
* @param {number} typ_idx
* @param {boolean} premultiply
* @param {boolean} color_space_conversion
* @returns {Uint8Array}
* @returns {Uint8ClampedArray}
*/
export function resize(input_image: Uint8Array, input_width: number, input_height: number, output_width: number, output_height: number, typ_idx: number, premultiply: boolean, color_space_conversion: boolean): Uint8Array;
export function resize(input_image: Uint8Array, input_width: number, input_height: number, output_width: number, output_height: number, typ_idx: number, premultiply: boolean, color_space_conversion: boolean): Uint8ClampedArray;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;

View File

@@ -26,8 +26,16 @@ function getInt32Memory0() {
return cachegetInt32Memory0;
}
function getArrayU8FromWasm0(ptr, len) {
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
let cachegetUint8ClampedMemory0 = null;
function getUint8ClampedMemory0() {
if (cachegetUint8ClampedMemory0 === null || cachegetUint8ClampedMemory0.buffer !== wasm.memory.buffer) {
cachegetUint8ClampedMemory0 = new Uint8ClampedArray(wasm.memory.buffer);
}
return cachegetUint8ClampedMemory0;
}
function getClampedArrayU8FromWasm0(ptr, len) {
return getUint8ClampedMemory0().subarray(ptr / 1, ptr / 1 + len);
}
/**
* @param {Uint8Array} input_image
@@ -38,7 +46,7 @@ function getArrayU8FromWasm0(ptr, len) {
* @param {number} typ_idx
* @param {boolean} premultiply
* @param {boolean} color_space_conversion
* @returns {Uint8Array}
* @returns {Uint8ClampedArray}
*/
export function resize(input_image, input_width, input_height, output_width, output_height, typ_idx, premultiply, color_space_conversion) {
try {
@@ -48,7 +56,7 @@ export function resize(input_image, input_width, input_height, output_width, out
wasm.resize(retptr, ptr0, len0, input_width, input_height, output_width, output_height, typ_idx, premultiply, color_space_conversion);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice();
var v1 = getClampedArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v1;
} finally {

7
codecs/resize/pkg/squoosh_resize_bg.wasm.d.ts generated vendored Normal file
View File

@@ -0,0 +1,7 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function resize(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number): void;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function __wbindgen_malloc(a: number): number;
export function __wbindgen_free(a: number, b: number): void;

View File

@@ -8,6 +8,7 @@ use cfg_if::cfg_if;
use resize::Pixel;
use resize::Type;
use wasm_bindgen::prelude::*;
use wasm_bindgen::Clamped;
mod srgb;
use srgb::{linear_to_srgb, Clamp};
@@ -66,7 +67,7 @@ pub fn resize(
typ_idx: usize,
premultiply: bool,
color_space_conversion: bool,
) -> Vec<u8> {
) -> Clamped<Vec<u8>> {
let typ = match typ_idx {
0 => Type::Triangle,
1 => Type::Catrom,
@@ -91,7 +92,7 @@ pub fn resize(
typ,
);
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
return output_image;
return Clamped(output_image);
}
// Otherwise, we convert to f32 images to keep the
@@ -138,5 +139,5 @@ pub fn resize(
.clamp(0.0, 255.0) as u8;
}
return output_image;
return Clamped(output_image);
}

View File

@@ -1,5 +1,6 @@
{
"name": "avif",
"type": "module",
"scripts": {
"build": "../build-cpp.sh"
}

22
codecs/visdif/test.mjs Normal file
View File

@@ -0,0 +1,22 @@
import {dirname} from "path";
globalThis.__dirname = dirname(import.meta.url);
import { createRequire } from 'module';
globalThis.require = createRequire(import.meta.url);
import visdif from './visdif.js';
const {VisDiff} = await visdif({
locateFile() {
return new URL("./visdif.wasm", import.meta.url).pathname;
}
});
const comparator = new VisDiff(
new Uint8ClampedArray([0, 0, 0, 255]),
1,
1
);
const distance = comparator.distance(new Uint8ClampedArray([1,1,1,255]));
console.log({distance});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,21 @@
import {dirname} from "path";
globalThis.__dirname = dirname(import.meta.url);
import { createRequire } from 'module';
globalThis.require = createRequire(import.meta.url);
import visdif from './visdif.js';
const {VisDiff} = await visdif({
locateFile() {
return new URL("./visdif.wasm", import.meta.url).pathname;
}
});
const comparator = new VisDiff(
new Uint8ClampedArray([0, 0, 0, 255]),
1,
1
);
const distance = comparator.distance(new Uint8ClampedArray([1,1,1,255]));
console.log({distance});

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./wp2_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./wp2_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./wp2_enc_mt_simd.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,/*isMainBrowserThread=*/0,/*isMainRuntimeThread=*/0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./wp2_enc_mt_simd.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -39,9 +39,9 @@ The returned `image` object is a representation of the original image, that you
When an image has been ingested, you can start preprocessing it and encoding it to other formats. This example will resize the image and then encode it to a `.jpg` and `.jxl` image:
```js
await image.decoded; //Wait until the image is decoded before running preprocessors
await image.decoded; //Wait until the image is decoded before running preprocessors.
const preprocessOptions: {
const preprocessOptions = {
resize: {
enabled: true,
width: 100,
@@ -50,7 +50,7 @@ const preprocessOptions: {
}
await image.preprocess(preprocessOptions);
const encodeOptions: {
const encodeOptions = {
mozjpeg: {}, //an empty object means 'use default settings'
jxl: {
quality: 90,

View File

@@ -0,0 +1,18 @@
import { ImagePool } from './build/index.js';
console.log("Starting");
const imagePool = new ImagePool();
// const imagePath = '/Users/surma/Downloads/happy_dog.png';
const imagePath = './squoosh.png';
console.log("INgesting");
const image = imagePool.ingestImage(imagePath);
console.log("Decoding");
await image.decoded;
const encodeOptions = {
mozjpeg: 'auto',
};
console.log("Encoding");
await image.encode(encodeOptions);
console.log("Closing");
await imagePool.close();
console.log("Done");

BIN
libsquoosh/squoosh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

132
libsquoosh/src/WebAssembly.d.ts vendored Normal file
View File

@@ -0,0 +1,132 @@
/**
* WebAssembly definitions are not available in `@types/node` yet,
* so these are copied from `lib.dom.d.ts`
*/
declare namespace WebAssembly {
interface CompileError {}
var CompileError: {
prototype: CompileError;
new (): CompileError;
};
interface Global {
value: any;
valueOf(): any;
}
var Global: {
prototype: Global;
new (descriptor: GlobalDescriptor, v?: any): Global;
};
interface Instance {
readonly exports: Exports;
}
var Instance: {
prototype: Instance;
new (module: Module, importObject?: Imports): Instance;
};
interface LinkError {}
var LinkError: {
prototype: LinkError;
new (): LinkError;
};
interface Memory {
readonly buffer: ArrayBuffer;
grow(delta: number): number;
}
var Memory: {
prototype: Memory;
new (descriptor: MemoryDescriptor): Memory;
};
interface Module {}
var Module: {
prototype: Module;
new (bytes: BufferSource): Module;
customSections(moduleObject: Module, sectionName: string): ArrayBuffer[];
exports(moduleObject: Module): ModuleExportDescriptor[];
imports(moduleObject: Module): ModuleImportDescriptor[];
};
interface RuntimeError {}
var RuntimeError: {
prototype: RuntimeError;
new (): RuntimeError;
};
interface Table {
readonly length: number;
get(index: number): Function | null;
grow(delta: number): number;
set(index: number, value: Function | null): void;
}
var Table: {
prototype: Table;
new (descriptor: TableDescriptor): Table;
};
interface GlobalDescriptor {
mutable?: boolean;
value: ValueType;
}
interface MemoryDescriptor {
initial: number;
maximum?: number;
}
interface ModuleExportDescriptor {
kind: ImportExportKind;
name: string;
}
interface ModuleImportDescriptor {
kind: ImportExportKind;
module: string;
name: string;
}
interface TableDescriptor {
element: TableKind;
initial: number;
maximum?: number;
}
interface WebAssemblyInstantiatedSource {
instance: Instance;
module: Module;
}
type ImportExportKind = 'function' | 'global' | 'memory' | 'table';
type TableKind = 'anyfunc';
type ValueType = 'f32' | 'f64' | 'i32' | 'i64';
type ExportValue = Function | Global | Memory | Table;
type Exports = Record<string, ExportValue>;
type ImportValue = ExportValue | number;
type ModuleImports = Record<string, ImportValue>;
type Imports = Record<string, ModuleImports>;
function compile(bytes: BufferSource): Promise<Module>;
// `compileStreaming` does not exist in NodeJS
// function compileStreaming(source: Response | Promise<Response>): Promise<Module>;
function instantiate(
bytes: BufferSource,
importObject?: Imports,
): Promise<WebAssemblyInstantiatedSource>;
function instantiate(
moduleObject: Module,
importObject?: Imports,
): Promise<Instance>;
// `instantiateStreaming` does not exist in NodeJS
// function instantiateStreaming(response: Response | PromiseLike<Response>, importObject?: Imports): Promise<WebAssemblyInstantiatedSource>;
function validate(bytes: BufferSource): boolean;
}

View File

@@ -11,7 +11,7 @@ import visdifWasm from 'asset-url:../../codecs/visdif/visdif.wasm';
export async function binarySearch(
measureGoal,
measure,
{ min = 0, max = 100, epsilon = 0.1, maxRounds = 8 } = {},
{ min = 0, max = 100, epsilon = 0.1, maxRounds = 6 } = {},
) {
let parameter = (max - min) / 2 + min;
let delta = (max - min) / 4;

View File

@@ -1,6 +1,37 @@
import { promises as fsp } from 'fs';
import { instantiateEmscriptenWasm, pathify } from './emscripten-utils.js';
interface RotateModuleInstance {
exports: {
memory: WebAssembly.Memory;
rotate(width: number, height: number, rotate: number): void;
};
}
interface ResizeWithAspectParams {
input_width: number;
input_height: number;
target_width: number;
target_height: number;
}
interface ResizeInstantiateOptions {
width: number;
height: number;
method: string;
premultiply: boolean;
linearRGB: boolean;
}
declare global {
// Needed for being able to use ImageData as type in codec types
type ImageData = typeof import('./image_data.js');
// Needed for being able to assign to `globalThis.ImageData`
var ImageData: ImageData['constructor'];
}
import type { QuantizerModule } from '../../codecs/imagequant/imagequant.js';
// MozJPEG
import mozEnc from '../../codecs/mozjpeg/enc/mozjpeg_node_enc.js';
import mozEncWasm from 'asset-url:../../codecs/mozjpeg/enc/mozjpeg_node_enc.wasm';
@@ -51,16 +82,22 @@ const resizePromise = resize.default(fsp.readFile(pathify(resizeWasm)));
// rotate
import rotateWasm from 'asset-url:../../codecs/rotate/rotate.wasm';
// TODO(ergunsh): Type definitions of some modules do not exist
// Figure out creating type definitions for them and remove `allowJs` rule
// We shouldn't need to use Promise<QuantizerModule> below after getting type definitions for imageQuant
// ImageQuant
import imageQuant from '../../codecs/imagequant/imagequant_node.js';
import imageQuantWasm from 'asset-url:../../codecs/imagequant/imagequant_node.wasm';
const imageQuantPromise = instantiateEmscriptenWasm(imageQuant, imageQuantWasm);
const imageQuantPromise: Promise<QuantizerModule> = instantiateEmscriptenWasm(
imageQuant,
imageQuantWasm,
);
// Our decoders currently rely on a `ImageData` global.
import ImageData from './image_data.js';
globalThis.ImageData = ImageData;
function resizeNameToIndex(name) {
function resizeNameToIndex(name: string) {
switch (name) {
case 'triangle':
return 0;
@@ -80,25 +117,26 @@ function resizeWithAspect({
input_height,
target_width,
target_height,
}) {
}: ResizeWithAspectParams): { width: number; height: number } {
if (!target_width && !target_height) {
throw Error('Need to specify at least width or height when resizing');
}
if (target_width && target_height) {
return { width: target_width, height: target_height };
}
if (!target_width) {
return {
width: Math.round((input_width / input_height) * target_height),
height: target_height,
};
}
if (!target_height) {
return {
width: target_width,
height: Math.round((input_height / input_width) * target_width),
};
}
return {
width: target_width,
height: Math.round((input_height / input_width) * target_width),
};
}
export const preprocessors = {
@@ -108,10 +146,16 @@ export const preprocessors = {
instantiate: async () => {
await resizePromise;
return (
buffer,
input_width,
input_height,
{ width, height, method, premultiply, linearRGB },
buffer: Uint8Array,
input_width: number,
input_height: number,
{
width,
height,
method,
premultiply,
linearRGB,
}: ResizeInstantiateOptions,
) => {
({ width, height } = resizeWithAspect({
input_width,
@@ -148,7 +192,12 @@ export const preprocessors = {
description: 'Reduce the number of colors used (aka. paletting)',
instantiate: async () => {
const imageQuant = await imageQuantPromise;
return (buffer, width, height, { numColors, dither }) =>
return (
buffer: Uint8Array,
width: number,
height: number,
{ numColors, dither }: { numColors: number; dither: number },
) =>
new ImageData(
imageQuant.quantize(buffer, width, height, numColors, dither),
width,
@@ -164,13 +213,18 @@ export const preprocessors = {
name: 'Rotate',
description: 'Rotate image',
instantiate: async () => {
return async (buffer, width, height, { numRotations }) => {
return async (
buffer: Uint8Array,
width: number,
height: number,
{ numRotations }: { numRotations: number },
) => {
const degrees = (numRotations * 90) % 360;
const sameDimensions = degrees == 0 || degrees == 180;
const size = width * height * 4;
const { instance } = await WebAssembly.instantiate(
await fsp.readFile(pathify(rotateWasm)),
);
const instance = (
await WebAssembly.instantiate(await fsp.readFile(pathify(rotateWasm)))
).instance as RotateModuleInstance;
const { memory } = instance.exports;
const additionalPagesNeeded = Math.ceil(
(size * 2 - memory.buffer.byteLength + 8) / (64 * 1024),
@@ -286,8 +340,8 @@ export const codecs = {
},
autoOptimize: {
option: 'cqLevel',
min: 0,
max: 62,
min: 62,
max: 0,
},
},
jxl: {
@@ -346,13 +400,18 @@ export const codecs = {
await pngEncDecPromise;
await oxipngPromise;
return {
encode: (buffer, width, height, opts) => {
encode: (
buffer: Uint8Array,
width: number,
height: number,
opts: { level: number },
) => {
const simplePng = pngEncDec.encode(
new Uint8Array(buffer),
width,
height,
);
return oxipng.optimise(simplePng, opts.level);
return oxipng.optimise(simplePng, opts.level, false);
},
};
},

View File

@@ -1,13 +1,16 @@
import { fileURLToPath } from 'url';
export function pathify(path) {
export function pathify(path: string): string {
if (path.startsWith('file://')) {
path = fileURLToPath(path);
}
return path;
}
export function instantiateEmscriptenWasm(factory, path) {
export function instantiateEmscriptenWasm<T extends EmscriptenWasm.Module>(
factory: EmscriptenWasm.ModuleFactory<T>,
path: string,
): Promise<T> {
return factory({
locateFile() {
return pathify(path);

View File

@@ -180,9 +180,9 @@ class Image {
encName,
encConfig,
optimizerButteraugliTarget: Number(
encodeOptions.optimizerButteraugliTarget,
encodeOptions.optimizerButteraugliTarget ?? 1.4,
),
maxOptimizerRounds: Number(encodeOptions.maxOptimizerRounds),
maxOptimizerRounds: Number(encodeOptions.maxOptimizerRounds ?? 6),
});
}
await Promise.all(Object.values(this.encodedWith));

38
libsquoosh/src/missing-types.d.ts vendored Normal file
View File

@@ -0,0 +1,38 @@
/// <reference path="../../missing-types.d.ts" />
declare module 'asset-url:*' {
const value: string;
export default value;
}
// Somehow TS picks up definitions from the module itself
// instead of using `asset-url:*`. It is probably related to
// specifity of the module declaration and these declarations below fix it
declare module 'asset-url:../../codecs/png/pkg/squoosh_png_bg.wasm' {
const value: string;
export default value;
}
declare module 'asset-url:../../codecs/oxipng/pkg/squoosh_oxipng_bg.wasm' {
const value: string;
export default value;
}
declare module 'asset-url:../../codecs/resize/pkg/squoosh_resize_bg.wasm' {
const value: string;
export default value;
}
// These don't exist in NodeJS types so we're not able to use them but they are referenced in some emscripten and codec types
// Thus, we need to explicitly assign them to be `never`
// We're also not able to use the APIs that use these types
// So, if we want to use those APIs we need to supply its dependencies ourselves
// However, probably those APIs are more suited to be used in web (i.e. there can be other
// dependencies to web APIs that might not work in Node)
type RequestInfo = never;
type Response = never;
type WebGLRenderingContext = never;
type MessageEvent = never;
type BufferSource = ArrayBufferView | ArrayBuffer;
type URL = import('url').URL;

View File

@@ -2,7 +2,8 @@
"extends": "../generic-tsconfig.json",
"compilerOptions": {
"lib": ["esnext"],
"types": ["node"]
"types": ["node"],
"allowJs": true
},
"include": ["src/**/*"]
"include": ["src/**/*", "../codecs/**/*"]
}

8799
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,8 @@ export default class TwoUp extends HTMLElement {
*/
private _everConnected = false;
private _resizeObserver?: ResizeObserver;
constructor() {
super();
this._handle.className = styles.twoUpHandle;
@@ -45,13 +47,6 @@ export default class TwoUp extends HTMLElement {
childList: true,
});
// Watch for element size changes.
if ('ResizeObserver' in window) {
new ResizeObserver(() => this._resetPosition()).observe(this);
} else {
window.addEventListener('resize', () => this._resetPosition());
}
// Watch for pointers on the handle.
const pointerTracker: PointerTracker = new PointerTracker(this._handle, {
start: (_, event) => {
@@ -68,8 +63,6 @@ export default class TwoUp extends HTMLElement {
);
},
});
window.addEventListener('keydown', (event) => this._onKeyDown(event));
}
connectedCallback() {
@@ -84,12 +77,23 @@ export default class TwoUp extends HTMLElement {
}</svg>
`}</div>`;
// Watch for element size changes.
this._resizeObserver = new ResizeObserver(() => this._resetPosition());
this._resizeObserver.observe(this);
window.addEventListener('keydown', this._onKeyDown);
if (!this._everConnected) {
this._resetPosition();
this._everConnected = true;
}
}
disconnectedCallback() {
window.removeEventListener('keydown', this._onKeyDown);
if (this._resizeObserver) this._resizeObserver.disconnect();
}
attributeChangedCallback(name: string) {
if (name === orientationAttr) {
this._resetPosition();
@@ -97,7 +101,7 @@ export default class TwoUp extends HTMLElement {
}
// KeyDown event handler
private _onKeyDown(event: KeyboardEvent) {
private _onKeyDown = (event: KeyboardEvent) => {
const target = event.target;
if (target instanceof HTMLElement && target.closest('input')) return;
@@ -122,7 +126,7 @@ export default class TwoUp extends HTMLElement {
this._relativePosition = this._position / bounds[dimensionAxis];
this._setPosition();
}
}
};
private _resetPosition() {
// Set the initial position of the handle.

View File

@@ -377,6 +377,7 @@ export default class Compress extends Component<Props, State> {
componentWillUnmount(): void {
updateDocumentTitle({ loading: false });
this.widthQuery.removeListener(this.onMobileWidthChange);
this.mainAbortController.abort();
for (const controller of this.sideAbortControllers) {
controller.abort();