forked from external-repos/squoosh
Compare commits
9 Commits
visdif-err
...
urls-bug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
886d8d632b | ||
|
|
e2d1adf5e9 | ||
|
|
223da087b2 | ||
|
|
765402404a | ||
|
|
c260f3e280 | ||
|
|
45187c4932 | ||
|
|
9b8d3b1bd8 | ||
|
|
a811b6cf41 | ||
|
|
ba0df8e2ff |
@@ -10,9 +10,6 @@ export CODEC_DIR = node_modules/libavif
|
|||||||
export BUILD_DIR = node_modules/build
|
export BUILD_DIR = node_modules/build
|
||||||
export LIBAOM_DIR = node_modules/libaom
|
export LIBAOM_DIR = node_modules/libaom
|
||||||
|
|
||||||
override CFLAGS += "-Wno-unused-macros"
|
|
||||||
export
|
|
||||||
|
|
||||||
OUT_ENC_JS = enc/avif_enc.js
|
OUT_ENC_JS = enc/avif_enc.js
|
||||||
OUT_NODE_ENC_JS = enc/avif_node_enc.js
|
OUT_NODE_ENC_JS = enc/avif_node_enc.js
|
||||||
OUT_ENC_MT_JS = enc/avif_enc_mt.js
|
OUT_ENC_MT_JS = enc/avif_enc_mt.js
|
||||||
|
|||||||
43
codecs/avif/dec/avif_dec.js
generated
43
codecs/avif/dec/avif_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
43
codecs/avif/dec/avif_node_dec.js
generated
43
codecs/avif/dec/avif_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
49
codecs/avif/enc/avif_enc.js
generated
49
codecs/avif/enc/avif_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
82
codecs/avif/enc/avif_enc_mt.js
generated
82
codecs/avif/enc/avif_enc_mt.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/avif/enc/avif_enc_mt.worker.js
generated
2
codecs/avif/enc/avif_enc_mt.worker.js
generated
@@ -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,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}};
|
"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}};
|
||||||
|
|||||||
48
codecs/avif/enc/avif_node_enc.js
generated
48
codecs/avif/enc/avif_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1,13 +1,13 @@
|
|||||||
FROM emscripten/emsdk:2.0.23
|
FROM emscripten/emsdk:2.0.21
|
||||||
RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config
|
RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config
|
||||||
ENV CFLAGS "-O3 -flto"
|
ENV CFLAGS "-O3 -flto"
|
||||||
ENV CXXFLAGS "${CFLAGS} -std=c++17"
|
ENV CXXFLAGS "${CFLAGS} -std=c++17"
|
||||||
ENV LDFLAGS "${CFLAGS} \
|
ENV LDFLAGS "${CFLAGS} \
|
||||||
|
--closure 1 \
|
||||||
-s FILESYSTEM=0 \
|
-s FILESYSTEM=0 \
|
||||||
-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
|
-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
|
||||||
-s ALLOW_MEMORY_GROWTH=1 \
|
-s ALLOW_MEMORY_GROWTH=1 \
|
||||||
-s TEXTDECODER=2 \
|
-s TEXTDECODER=2 \
|
||||||
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \
|
|
||||||
"
|
"
|
||||||
# Build and cache standard libraries with these flags + Embind.
|
# Build and cache standard libraries with these flags + Embind.
|
||||||
RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -xc++ /dev/null -o /dev/null
|
RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -xc++ /dev/null -o /dev/null
|
||||||
|
|||||||
41
codecs/imagequant/imagequant.js
generated
41
codecs/imagequant/imagequant.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
41
codecs/imagequant/imagequant_node.js
generated
41
codecs/imagequant/imagequant_node.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
42
codecs/jxl/dec/jxl_dec.js
generated
42
codecs/jxl/dec/jxl_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
42
codecs/jxl/dec/jxl_node_dec.js
generated
42
codecs/jxl/dec/jxl_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
55
codecs/jxl/enc/jxl_enc.js
generated
55
codecs/jxl/enc/jxl_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
91
codecs/jxl/enc/jxl_enc_mt.js
generated
91
codecs/jxl/enc/jxl_enc_mt.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/jxl/enc/jxl_enc_mt.worker.js
generated
2
codecs/jxl/enc/jxl_enc_mt.worker.js
generated
@@ -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,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}};
|
"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}};
|
||||||
|
|||||||
91
codecs/jxl/enc/jxl_enc_mt_simd.js
generated
91
codecs/jxl/enc/jxl_enc_mt_simd.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/jxl/enc/jxl_enc_mt_simd.worker.js
generated
2
codecs/jxl/enc/jxl_enc_mt_simd.worker.js
generated
@@ -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,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}};
|
"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}};
|
||||||
|
|||||||
56
codecs/jxl/enc/jxl_node_enc.js
generated
56
codecs/jxl/enc/jxl_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
43
codecs/mozjpeg/dec/mozjpeg_node_dec.js
generated
43
codecs/mozjpeg/dec/mozjpeg_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
45
codecs/mozjpeg/enc/mozjpeg_enc.js
generated
45
codecs/mozjpeg/enc/mozjpeg_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
45
codecs/mozjpeg/enc/mozjpeg_node_enc.js
generated
45
codecs/mozjpeg/enc/mozjpeg_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
4
codecs/resize/pkg/squoosh_resize.d.ts
generated
vendored
4
codecs/resize/pkg/squoosh_resize.d.ts
generated
vendored
@@ -9,9 +9,9 @@
|
|||||||
* @param {number} typ_idx
|
* @param {number} typ_idx
|
||||||
* @param {boolean} premultiply
|
* @param {boolean} premultiply
|
||||||
* @param {boolean} color_space_conversion
|
* @param {boolean} color_space_conversion
|
||||||
* @returns {Uint8ClampedArray}
|
* @returns {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 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 type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
|||||||
16
codecs/resize/pkg/squoosh_resize.js
generated
16
codecs/resize/pkg/squoosh_resize.js
generated
@@ -26,16 +26,8 @@ function getInt32Memory0() {
|
|||||||
return cachegetInt32Memory0;
|
return cachegetInt32Memory0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachegetUint8ClampedMemory0 = null;
|
function getArrayU8FromWasm0(ptr, len) {
|
||||||
function getUint8ClampedMemory0() {
|
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
||||||
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
|
* @param {Uint8Array} input_image
|
||||||
@@ -46,7 +38,7 @@ function getClampedArrayU8FromWasm0(ptr, len) {
|
|||||||
* @param {number} typ_idx
|
* @param {number} typ_idx
|
||||||
* @param {boolean} premultiply
|
* @param {boolean} premultiply
|
||||||
* @param {boolean} color_space_conversion
|
* @param {boolean} color_space_conversion
|
||||||
* @returns {Uint8ClampedArray}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export function resize(input_image, input_width, input_height, output_width, output_height, typ_idx, premultiply, color_space_conversion) {
|
export function resize(input_image, input_width, input_height, output_width, output_height, typ_idx, premultiply, color_space_conversion) {
|
||||||
try {
|
try {
|
||||||
@@ -56,7 +48,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);
|
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 r0 = getInt32Memory0()[retptr / 4 + 0];
|
||||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
||||||
var v1 = getClampedArrayU8FromWasm0(r0, r1).slice();
|
var v1 = getArrayU8FromWasm0(r0, r1).slice();
|
||||||
wasm.__wbindgen_free(r0, r1 * 1);
|
wasm.__wbindgen_free(r0, r1 * 1);
|
||||||
return v1;
|
return v1;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Binary file not shown.
7
codecs/resize/pkg/squoosh_resize_bg.wasm.d.ts
generated
vendored
7
codecs/resize/pkg/squoosh_resize_bg.wasm.d.ts
generated
vendored
@@ -1,7 +0,0 @@
|
|||||||
/* 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;
|
|
||||||
@@ -8,7 +8,6 @@ use cfg_if::cfg_if;
|
|||||||
use resize::Pixel;
|
use resize::Pixel;
|
||||||
use resize::Type;
|
use resize::Type;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen::Clamped;
|
|
||||||
|
|
||||||
mod srgb;
|
mod srgb;
|
||||||
use srgb::{linear_to_srgb, Clamp};
|
use srgb::{linear_to_srgb, Clamp};
|
||||||
@@ -67,7 +66,7 @@ pub fn resize(
|
|||||||
typ_idx: usize,
|
typ_idx: usize,
|
||||||
premultiply: bool,
|
premultiply: bool,
|
||||||
color_space_conversion: bool,
|
color_space_conversion: bool,
|
||||||
) -> Clamped<Vec<u8>> {
|
) -> Vec<u8> {
|
||||||
let typ = match typ_idx {
|
let typ = match typ_idx {
|
||||||
0 => Type::Triangle,
|
0 => Type::Triangle,
|
||||||
1 => Type::Catrom,
|
1 => Type::Catrom,
|
||||||
@@ -92,7 +91,7 @@ pub fn resize(
|
|||||||
typ,
|
typ,
|
||||||
);
|
);
|
||||||
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
|
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
|
||||||
return Clamped(output_image);
|
return output_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we convert to f32 images to keep the
|
// Otherwise, we convert to f32 images to keep the
|
||||||
@@ -139,5 +138,5 @@ pub fn resize(
|
|||||||
.clamp(0.0, 255.0) as u8;
|
.clamp(0.0, 255.0) as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Clamped(output_image);
|
return output_image;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "avif",
|
"name": "avif",
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "../build-cpp.sh"
|
"build": "../build-cpp.sh"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
|
|
||||||
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});
|
|
||||||
55
codecs/visdif/visdif.js
generated
55
codecs/visdif/visdif.js
generated
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
|
|||||||
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.
41
codecs/webp/dec/webp_dec.js
generated
41
codecs/webp/dec/webp_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
41
codecs/webp/dec/webp_node_dec.js
generated
41
codecs/webp/dec/webp_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
45
codecs/webp/enc/webp_enc.js
generated
45
codecs/webp/enc/webp_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
45
codecs/webp/enc/webp_enc_simd.js
generated
45
codecs/webp/enc/webp_enc_simd.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
44
codecs/webp/enc/webp_node_enc.js
generated
44
codecs/webp/enc/webp_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
42
codecs/wp2/dec/wp2_dec.js
generated
42
codecs/wp2/dec/wp2_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
41
codecs/wp2/dec/wp2_node_dec.js
generated
41
codecs/wp2/dec/wp2_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
46
codecs/wp2/enc/wp2_enc.js
generated
46
codecs/wp2/enc/wp2_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
79
codecs/wp2/enc/wp2_enc_mt.js
generated
79
codecs/wp2/enc/wp2_enc_mt.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/wp2/enc/wp2_enc_mt.worker.js
generated
2
codecs/wp2/enc/wp2_enc_mt.worker.js
generated
@@ -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,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}};
|
"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}};
|
||||||
|
|||||||
79
codecs/wp2/enc/wp2_enc_mt_simd.js
generated
79
codecs/wp2/enc/wp2_enc_mt_simd.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
2
codecs/wp2/enc/wp2_enc_mt_simd.worker.js
generated
2
codecs/wp2/enc/wp2_enc_mt_simd.worker.js
generated
@@ -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,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}};
|
"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}};
|
||||||
|
|||||||
46
codecs/wp2/enc/wp2_node_enc.js
generated
46
codecs/wp2/enc/wp2_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -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:
|
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
|
```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: {
|
resize: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
@@ -50,7 +50,7 @@ const preprocessOptions = {
|
|||||||
}
|
}
|
||||||
await image.preprocess(preprocessOptions);
|
await image.preprocess(preprocessOptions);
|
||||||
|
|
||||||
const encodeOptions = {
|
const encodeOptions: {
|
||||||
mozjpeg: {}, //an empty object means 'use default settings'
|
mozjpeg: {}, //an empty object means 'use default settings'
|
||||||
jxl: {
|
jxl: {
|
||||||
quality: 90,
|
quality: 90,
|
||||||
@@ -81,7 +81,7 @@ When you have encoded an image, you normally want to write it to a file.
|
|||||||
This example takes an image that has been encoded as a `jpg` and writes it to a file:
|
This example takes an image that has been encoded as a `jpg` and writes it to a file:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const rawEncodedImage = (await image.encodedWith.mozjpeg).binary;
|
const rawEncodedImage = (await image.encodedWidth.mozjpeg).binary;
|
||||||
|
|
||||||
fs.writeFile('/path/to/new/image.jpg', rawEncodedImage);
|
fs.writeFile('/path/to/new/image.jpg', rawEncodedImage);
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,133 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2020 Google Inc. All Rights Reserved.
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
import { spawn } from 'child_process';
|
|
||||||
import { relative, join } from 'path';
|
|
||||||
import { promises as fsp } from 'fs';
|
|
||||||
import { promisify } from 'util';
|
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
|
||||||
import glob from 'glob';
|
|
||||||
import { sync as whichSync } from 'which';
|
|
||||||
|
|
||||||
const globP = promisify(glob);
|
|
||||||
|
|
||||||
const tscPath = whichSync('tsc');
|
|
||||||
|
|
||||||
const extRe = /\.tsx?$/;
|
|
||||||
|
|
||||||
function loadConfig(mainPath) {
|
|
||||||
const fileName = ts.findConfigFile(mainPath, ts.sys.fileExists);
|
|
||||||
if (!fileName) throw Error('tsconfig not found');
|
|
||||||
const text = ts.sys.readFile(fileName);
|
|
||||||
const loadedConfig = ts.parseConfigFileTextToJson(fileName, text).config;
|
|
||||||
const parsedTsConfig = ts.parseJsonConfigFileContent(
|
|
||||||
loadedConfig,
|
|
||||||
ts.sys,
|
|
||||||
process.cwd(),
|
|
||||||
undefined,
|
|
||||||
fileName,
|
|
||||||
);
|
|
||||||
return parsedTsConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function simpleTS(mainPath, { noBuild, watch } = {}) {
|
|
||||||
const config = loadConfig(mainPath);
|
|
||||||
const args = ['-b', mainPath];
|
|
||||||
|
|
||||||
let tsBuildDone;
|
|
||||||
|
|
||||||
async function watchBuiltFiles(rollupContext) {
|
|
||||||
const matches = await globP(config.options.outDir + '/**/*.js');
|
|
||||||
for (const match of matches) rollupContext.addWatchFile(match);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tsBuild(rollupContext) {
|
|
||||||
if (tsBuildDone) {
|
|
||||||
// Watch lists are cleared on each build, so we need to rewatch all the JS files.
|
|
||||||
await watchBuiltFiles(rollupContext);
|
|
||||||
return tsBuildDone;
|
|
||||||
}
|
|
||||||
if (noBuild) {
|
|
||||||
return (tsBuildDone = Promise.resolve());
|
|
||||||
}
|
|
||||||
tsBuildDone = Promise.resolve().then(async () => {
|
|
||||||
await new Promise((resolve) => {
|
|
||||||
const proc = spawn(tscPath, args, {
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
|
|
||||||
proc.on('exit', (code) => {
|
|
||||||
if (code !== 0) {
|
|
||||||
throw Error('TypeScript build failed');
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await watchBuiltFiles(rollupContext);
|
|
||||||
|
|
||||||
if (watch) {
|
|
||||||
tsBuildDone.then(() => {
|
|
||||||
spawn(tscPath, [...args, '--watch', '--preserveWatchOutput'], {
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return tsBuildDone;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: 'simple-ts',
|
|
||||||
resolveId(id, importer) {
|
|
||||||
// If there isn't an importer, it's an entry point, so we don't need to resolve it relative
|
|
||||||
// to something.
|
|
||||||
if (!importer) return null;
|
|
||||||
|
|
||||||
const tsResolve = ts.resolveModuleName(
|
|
||||||
id,
|
|
||||||
importer,
|
|
||||||
config.options,
|
|
||||||
ts.sys,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
// It didn't find anything
|
|
||||||
!tsResolve.resolvedModule ||
|
|
||||||
// Or if it's linking to a definition file, it's something in node_modules,
|
|
||||||
// or something local like css.d.ts
|
|
||||||
tsResolve.resolvedModule.extension === '.d.ts'
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return tsResolve.resolvedModule.resolvedFileName;
|
|
||||||
},
|
|
||||||
async load(id) {
|
|
||||||
if (!extRe.test(id)) return null;
|
|
||||||
|
|
||||||
// TypeScript building is deferred until the first TS file load.
|
|
||||||
// This allows prerequisites to happen first,
|
|
||||||
// such as css.d.ts generation in css-plugin.
|
|
||||||
await tsBuild(this);
|
|
||||||
|
|
||||||
// Look for the JS equivalent in the tmp folder
|
|
||||||
const newId = join(
|
|
||||||
config.options.outDir,
|
|
||||||
relative(config.options.rootDir, id),
|
|
||||||
).replace(extRe, '.js');
|
|
||||||
|
|
||||||
return fsp.readFile(newId, { encoding: 'utf8' });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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");
|
|
||||||
27
libsquoosh/package-lock.json
generated
27
libsquoosh/package-lock.json
generated
@@ -1125,9 +1125,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
"version": "15.6.1",
|
"version": "15.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-15.0.1.tgz",
|
||||||
"integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==",
|
"integrity": "sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/resolve": {
|
"@types/resolve": {
|
||||||
@@ -1492,12 +1492,6 @@
|
|||||||
"@types/estree": "*"
|
"@types/estree": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"isexe": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"jest-worker": {
|
"jest-worker": {
|
||||||
"version": "26.6.2",
|
"version": "26.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
||||||
@@ -1832,12 +1826,6 @@
|
|||||||
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
|
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"typescript": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"unicode-canonical-property-names-ecmascript": {
|
"unicode-canonical-property-names-ecmascript": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
|
||||||
@@ -1871,15 +1859,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz",
|
||||||
"integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA=="
|
"integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA=="
|
||||||
},
|
},
|
||||||
"which": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"isexe": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"version": "0.2.3",
|
"version": "0.2.3",
|
||||||
"description": "A Node library for Squoosh",
|
"description": "A Node library for Squoosh",
|
||||||
"public": true,
|
"public": true,
|
||||||
"main": "./build/index.js",
|
"main": "/build/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"/build/*"
|
"/build/*"
|
||||||
],
|
],
|
||||||
@@ -22,10 +22,7 @@
|
|||||||
"@rollup/plugin-babel": "^5.3.0",
|
"@rollup/plugin-babel": "^5.3.0",
|
||||||
"@rollup/plugin-commonjs": "^18.0.0",
|
"@rollup/plugin-commonjs": "^18.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^11.2.1",
|
"@rollup/plugin-node-resolve": "^11.2.1",
|
||||||
"@types/node": "^15.6.1",
|
|
||||||
"rollup": "^2.46.0",
|
"rollup": "^2.46.0",
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
"rollup-plugin-terser": "^7.0.2"
|
||||||
"typescript": "^4.1.3",
|
|
||||||
"which": "^2.0.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import resolve from '@rollup/plugin-node-resolve';
|
import resolve from '@rollup/plugin-node-resolve';
|
||||||
import cjs from '@rollup/plugin-commonjs';
|
import cjs from '@rollup/plugin-commonjs';
|
||||||
import simpleTS from './lib/simple-ts';
|
|
||||||
import asset from './lib/asset-plugin.js';
|
import asset from './lib/asset-plugin.js';
|
||||||
import json from './lib/json-plugin.js';
|
import json from './lib/json-plugin.js';
|
||||||
import autojson from './lib/autojson-plugin.js';
|
import autojson from './lib/autojson-plugin.js';
|
||||||
@@ -21,7 +20,6 @@ export default {
|
|||||||
asset(),
|
asset(),
|
||||||
autojson(),
|
autojson(),
|
||||||
json(),
|
json(),
|
||||||
simpleTS('.'),
|
|
||||||
getBabelOutputPlugin({
|
getBabelOutputPlugin({
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
configFile: false,
|
configFile: false,
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB |
132
libsquoosh/src/WebAssembly.d.ts
vendored
132
libsquoosh/src/WebAssembly.d.ts
vendored
@@ -1,132 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,7 @@ import visdifWasm from 'asset-url:../../codecs/visdif/visdif.wasm';
|
|||||||
export async function binarySearch(
|
export async function binarySearch(
|
||||||
measureGoal,
|
measureGoal,
|
||||||
measure,
|
measure,
|
||||||
{ min = 0, max = 100, epsilon = 0.1, maxRounds = 6 } = {},
|
{ min = 0, max = 100, epsilon = 0.1, maxRounds = 8 } = {},
|
||||||
) {
|
) {
|
||||||
let parameter = (max - min) / 2 + min;
|
let parameter = (max - min) / 2 + min;
|
||||||
let delta = (max - min) / 4;
|
let delta = (max - min) / 4;
|
||||||
|
|||||||
@@ -1,37 +1,6 @@
|
|||||||
import { promises as fsp } from 'fs';
|
import { promises as fsp } from 'fs';
|
||||||
import { instantiateEmscriptenWasm, pathify } from './emscripten-utils.js';
|
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
|
// MozJPEG
|
||||||
import mozEnc from '../../codecs/mozjpeg/enc/mozjpeg_node_enc.js';
|
import mozEnc from '../../codecs/mozjpeg/enc/mozjpeg_node_enc.js';
|
||||||
import mozEncWasm from 'asset-url:../../codecs/mozjpeg/enc/mozjpeg_node_enc.wasm';
|
import mozEncWasm from 'asset-url:../../codecs/mozjpeg/enc/mozjpeg_node_enc.wasm';
|
||||||
@@ -82,22 +51,16 @@ const resizePromise = resize.default(fsp.readFile(pathify(resizeWasm)));
|
|||||||
// rotate
|
// rotate
|
||||||
import rotateWasm from 'asset-url:../../codecs/rotate/rotate.wasm';
|
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
|
// ImageQuant
|
||||||
import imageQuant from '../../codecs/imagequant/imagequant_node.js';
|
import imageQuant from '../../codecs/imagequant/imagequant_node.js';
|
||||||
import imageQuantWasm from 'asset-url:../../codecs/imagequant/imagequant_node.wasm';
|
import imageQuantWasm from 'asset-url:../../codecs/imagequant/imagequant_node.wasm';
|
||||||
const imageQuantPromise: Promise<QuantizerModule> = instantiateEmscriptenWasm(
|
const imageQuantPromise = instantiateEmscriptenWasm(imageQuant, imageQuantWasm);
|
||||||
imageQuant,
|
|
||||||
imageQuantWasm,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Our decoders currently rely on a `ImageData` global.
|
// Our decoders currently rely on a `ImageData` global.
|
||||||
import ImageData from './image_data.js';
|
import ImageData from './image_data.js';
|
||||||
globalThis.ImageData = ImageData;
|
globalThis.ImageData = ImageData;
|
||||||
|
|
||||||
function resizeNameToIndex(name: string) {
|
function resizeNameToIndex(name) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'triangle':
|
case 'triangle':
|
||||||
return 0;
|
return 0;
|
||||||
@@ -117,26 +80,25 @@ function resizeWithAspect({
|
|||||||
input_height,
|
input_height,
|
||||||
target_width,
|
target_width,
|
||||||
target_height,
|
target_height,
|
||||||
}: ResizeWithAspectParams): { width: number; height: number } {
|
}) {
|
||||||
if (!target_width && !target_height) {
|
if (!target_width && !target_height) {
|
||||||
throw Error('Need to specify at least width or height when resizing');
|
throw Error('Need to specify at least width or height when resizing');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_width && target_height) {
|
if (target_width && target_height) {
|
||||||
return { width: target_width, height: target_height };
|
return { width: target_width, height: target_height };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target_width) {
|
if (!target_width) {
|
||||||
return {
|
return {
|
||||||
width: Math.round((input_width / input_height) * target_height),
|
width: Math.round((input_width / input_height) * target_height),
|
||||||
height: target_height,
|
height: target_height,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (!target_height) {
|
||||||
return {
|
return {
|
||||||
width: target_width,
|
width: target_width,
|
||||||
height: Math.round((input_height / input_width) * target_width),
|
height: Math.round((input_height / input_width) * target_width),
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const preprocessors = {
|
export const preprocessors = {
|
||||||
@@ -146,16 +108,10 @@ export const preprocessors = {
|
|||||||
instantiate: async () => {
|
instantiate: async () => {
|
||||||
await resizePromise;
|
await resizePromise;
|
||||||
return (
|
return (
|
||||||
buffer: Uint8Array,
|
buffer,
|
||||||
input_width: number,
|
input_width,
|
||||||
input_height: number,
|
input_height,
|
||||||
{
|
{ width, height, method, premultiply, linearRGB },
|
||||||
width,
|
|
||||||
height,
|
|
||||||
method,
|
|
||||||
premultiply,
|
|
||||||
linearRGB,
|
|
||||||
}: ResizeInstantiateOptions,
|
|
||||||
) => {
|
) => {
|
||||||
({ width, height } = resizeWithAspect({
|
({ width, height } = resizeWithAspect({
|
||||||
input_width,
|
input_width,
|
||||||
@@ -192,12 +148,7 @@ export const preprocessors = {
|
|||||||
description: 'Reduce the number of colors used (aka. paletting)',
|
description: 'Reduce the number of colors used (aka. paletting)',
|
||||||
instantiate: async () => {
|
instantiate: async () => {
|
||||||
const imageQuant = await imageQuantPromise;
|
const imageQuant = await imageQuantPromise;
|
||||||
return (
|
return (buffer, width, height, { numColors, dither }) =>
|
||||||
buffer: Uint8Array,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
{ numColors, dither }: { numColors: number; dither: number },
|
|
||||||
) =>
|
|
||||||
new ImageData(
|
new ImageData(
|
||||||
imageQuant.quantize(buffer, width, height, numColors, dither),
|
imageQuant.quantize(buffer, width, height, numColors, dither),
|
||||||
width,
|
width,
|
||||||
@@ -213,18 +164,13 @@ export const preprocessors = {
|
|||||||
name: 'Rotate',
|
name: 'Rotate',
|
||||||
description: 'Rotate image',
|
description: 'Rotate image',
|
||||||
instantiate: async () => {
|
instantiate: async () => {
|
||||||
return async (
|
return async (buffer, width, height, { numRotations }) => {
|
||||||
buffer: Uint8Array,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
{ numRotations }: { numRotations: number },
|
|
||||||
) => {
|
|
||||||
const degrees = (numRotations * 90) % 360;
|
const degrees = (numRotations * 90) % 360;
|
||||||
const sameDimensions = degrees == 0 || degrees == 180;
|
const sameDimensions = degrees == 0 || degrees == 180;
|
||||||
const size = width * height * 4;
|
const size = width * height * 4;
|
||||||
const instance = (
|
const { instance } = await WebAssembly.instantiate(
|
||||||
await WebAssembly.instantiate(await fsp.readFile(pathify(rotateWasm)))
|
await fsp.readFile(pathify(rotateWasm)),
|
||||||
).instance as RotateModuleInstance;
|
);
|
||||||
const { memory } = instance.exports;
|
const { memory } = instance.exports;
|
||||||
const additionalPagesNeeded = Math.ceil(
|
const additionalPagesNeeded = Math.ceil(
|
||||||
(size * 2 - memory.buffer.byteLength + 8) / (64 * 1024),
|
(size * 2 - memory.buffer.byteLength + 8) / (64 * 1024),
|
||||||
@@ -340,8 +286,8 @@ export const codecs = {
|
|||||||
},
|
},
|
||||||
autoOptimize: {
|
autoOptimize: {
|
||||||
option: 'cqLevel',
|
option: 'cqLevel',
|
||||||
min: 62,
|
min: 0,
|
||||||
max: 0,
|
max: 62,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
jxl: {
|
jxl: {
|
||||||
@@ -400,18 +346,13 @@ export const codecs = {
|
|||||||
await pngEncDecPromise;
|
await pngEncDecPromise;
|
||||||
await oxipngPromise;
|
await oxipngPromise;
|
||||||
return {
|
return {
|
||||||
encode: (
|
encode: (buffer, width, height, opts) => {
|
||||||
buffer: Uint8Array,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
opts: { level: number },
|
|
||||||
) => {
|
|
||||||
const simplePng = pngEncDec.encode(
|
const simplePng = pngEncDec.encode(
|
||||||
new Uint8Array(buffer),
|
new Uint8Array(buffer),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
);
|
);
|
||||||
return oxipng.optimise(simplePng, opts.level, false);
|
return oxipng.optimise(simplePng, opts.level);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
export function pathify(path: string): string {
|
export function pathify(path) {
|
||||||
if (path.startsWith('file://')) {
|
if (path.startsWith('file://')) {
|
||||||
path = fileURLToPath(path);
|
path = fileURLToPath(path);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function instantiateEmscriptenWasm<T extends EmscriptenWasm.Module>(
|
export function instantiateEmscriptenWasm(factory, path) {
|
||||||
factory: EmscriptenWasm.ModuleFactory<T>,
|
|
||||||
path: string,
|
|
||||||
): Promise<T> {
|
|
||||||
return factory({
|
return factory({
|
||||||
locateFile() {
|
locateFile() {
|
||||||
return pathify(path);
|
return pathify(path);
|
||||||
7
libsquoosh/src/image_data.js
Normal file
7
libsquoosh/src/image_data.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export default class ImageData {
|
||||||
|
constructor(data, width, height) {
|
||||||
|
this.data = data;
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
export default class ImageData {
|
|
||||||
readonly data: Uint8ClampedArray;
|
|
||||||
readonly width: number;
|
|
||||||
readonly height: number;
|
|
||||||
|
|
||||||
constructor(data: Uint8ClampedArray, width: number, height: number) {
|
|
||||||
this.data = data;
|
|
||||||
this.width = width;
|
|
||||||
this.height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -180,9 +180,9 @@ class Image {
|
|||||||
encName,
|
encName,
|
||||||
encConfig,
|
encConfig,
|
||||||
optimizerButteraugliTarget: Number(
|
optimizerButteraugliTarget: Number(
|
||||||
encodeOptions.optimizerButteraugliTarget ?? 1.4,
|
encodeOptions.optimizerButteraugliTarget,
|
||||||
),
|
),
|
||||||
maxOptimizerRounds: Number(encodeOptions.maxOptimizerRounds ?? 6),
|
maxOptimizerRounds: Number(encodeOptions.maxOptimizerRounds),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await Promise.all(Object.values(this.encodedWith));
|
await Promise.all(Object.values(this.encodedWith));
|
||||||
|
|||||||
38
libsquoosh/src/missing-types.d.ts
vendored
38
libsquoosh/src/missing-types.d.ts
vendored
@@ -1,38 +0,0 @@
|
|||||||
/// <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;
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../generic-tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"lib": ["esnext"],
|
|
||||||
"types": ["node"],
|
|
||||||
"allowJs": true
|
|
||||||
},
|
|
||||||
"include": ["src/**/*", "../codecs/**/*"]
|
|
||||||
}
|
|
||||||
8799
package-lock.json
generated
8799
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -33,23 +33,11 @@ import initialCssPlugin from './lib/initial-css-plugin';
|
|||||||
import serviceWorkerPlugin from './lib/sw-plugin';
|
import serviceWorkerPlugin from './lib/sw-plugin';
|
||||||
import dataURLPlugin from './lib/data-url-plugin';
|
import dataURLPlugin from './lib/data-url-plugin';
|
||||||
import entryDataPlugin, { fileNameToURL } from './lib/entry-data-plugin';
|
import entryDataPlugin, { fileNameToURL } from './lib/entry-data-plugin';
|
||||||
import dedent from 'dedent';
|
|
||||||
|
|
||||||
function resolveFileUrl({ fileName }) {
|
function resolveFileUrl({ fileName }) {
|
||||||
return JSON.stringify(fileNameToURL(fileName));
|
return JSON.stringify(fileNameToURL(fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveImportMetaUrlInStaticBuild(property, { moduleId }) {
|
|
||||||
if (property !== 'url') return;
|
|
||||||
throw new Error(dedent`
|
|
||||||
Attempted to use a \`new URL(..., import.meta.url)\` pattern in ${path.relative(
|
|
||||||
process.cwd(),
|
|
||||||
moduleId,
|
|
||||||
)} for URL that needs to end up in static HTML.
|
|
||||||
This is currently unsupported.
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dir = '.tmp/build';
|
const dir = '.tmp/build';
|
||||||
const staticPath = 'static/c/[name]-[hash][extname]';
|
const staticPath = 'static/c/[name]-[hash][extname]';
|
||||||
const jsPath = staticPath.replace('[extname]', '.js');
|
const jsPath = staticPath.replace('[extname]', '.js');
|
||||||
@@ -112,7 +100,7 @@ export default async function ({ watch }) {
|
|||||||
},
|
},
|
||||||
preserveModules: true,
|
preserveModules: true,
|
||||||
plugins: [
|
plugins: [
|
||||||
{ resolveFileUrl, resolveImportMeta: resolveImportMetaUrlInStaticBuild },
|
{ resolveFileUrl },
|
||||||
clientBundlePlugin(
|
clientBundlePlugin(
|
||||||
{
|
{
|
||||||
external: ['worker_threads'],
|
external: ['worker_threads'],
|
||||||
|
|||||||
@@ -34,8 +34,6 @@ export default class TwoUp extends HTMLElement {
|
|||||||
*/
|
*/
|
||||||
private _everConnected = false;
|
private _everConnected = false;
|
||||||
|
|
||||||
private _resizeObserver?: ResizeObserver;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._handle.className = styles.twoUpHandle;
|
this._handle.className = styles.twoUpHandle;
|
||||||
@@ -47,6 +45,13 @@ export default class TwoUp extends HTMLElement {
|
|||||||
childList: true,
|
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.
|
// Watch for pointers on the handle.
|
||||||
const pointerTracker: PointerTracker = new PointerTracker(this._handle, {
|
const pointerTracker: PointerTracker = new PointerTracker(this._handle, {
|
||||||
start: (_, event) => {
|
start: (_, event) => {
|
||||||
@@ -63,6 +68,8 @@ export default class TwoUp extends HTMLElement {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.addEventListener('keydown', (event) => this._onKeyDown(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
@@ -77,23 +84,12 @@ export default class TwoUp extends HTMLElement {
|
|||||||
}</svg>
|
}</svg>
|
||||||
`}</div>`;
|
`}</div>`;
|
||||||
|
|
||||||
// Watch for element size changes.
|
|
||||||
this._resizeObserver = new ResizeObserver(() => this._resetPosition());
|
|
||||||
this._resizeObserver.observe(this);
|
|
||||||
|
|
||||||
window.addEventListener('keydown', this._onKeyDown);
|
|
||||||
|
|
||||||
if (!this._everConnected) {
|
if (!this._everConnected) {
|
||||||
this._resetPosition();
|
this._resetPosition();
|
||||||
this._everConnected = true;
|
this._everConnected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
|
||||||
window.removeEventListener('keydown', this._onKeyDown);
|
|
||||||
if (this._resizeObserver) this._resizeObserver.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeChangedCallback(name: string) {
|
attributeChangedCallback(name: string) {
|
||||||
if (name === orientationAttr) {
|
if (name === orientationAttr) {
|
||||||
this._resetPosition();
|
this._resetPosition();
|
||||||
@@ -101,7 +97,7 @@ export default class TwoUp extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// KeyDown event handler
|
// KeyDown event handler
|
||||||
private _onKeyDown = (event: KeyboardEvent) => {
|
private _onKeyDown(event: KeyboardEvent) {
|
||||||
const target = event.target;
|
const target = event.target;
|
||||||
if (target instanceof HTMLElement && target.closest('input')) return;
|
if (target instanceof HTMLElement && target.closest('input')) return;
|
||||||
|
|
||||||
@@ -126,7 +122,7 @@ export default class TwoUp extends HTMLElement {
|
|||||||
this._relativePosition = this._position / bounds[dimensionAxis];
|
this._relativePosition = this._position / bounds[dimensionAxis];
|
||||||
this._setPosition();
|
this._setPosition();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
private _resetPosition() {
|
private _resetPosition() {
|
||||||
// Set the initial position of the handle.
|
// Set the initial position of the handle.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import './custom-els/PinchZoom';
|
|||||||
import './custom-els/TwoUp';
|
import './custom-els/TwoUp';
|
||||||
import * as style from './style.css';
|
import * as style from './style.css';
|
||||||
import 'add-css:./style.css';
|
import 'add-css:./style.css';
|
||||||
import { shallowEqual } from '../../util';
|
import { shallowEqual, drawDataToCanvas } from '../../util';
|
||||||
import {
|
import {
|
||||||
ToggleBackgroundIcon,
|
ToggleBackgroundIcon,
|
||||||
AddIcon,
|
AddIcon,
|
||||||
@@ -18,7 +18,6 @@ import type { PreprocessorState } from '../../feature-meta';
|
|||||||
import { cleanSet } from '../../util/clean-modify';
|
import { cleanSet } from '../../util/clean-modify';
|
||||||
import type { SourceImage } from '../../Compress';
|
import type { SourceImage } from '../../Compress';
|
||||||
import { linkRef } from 'shared/prerendered-app/util';
|
import { linkRef } from 'shared/prerendered-app/util';
|
||||||
import { drawDataToCanvas } from 'client/lazy-app/util/canvas';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
source?: SourceImage;
|
source?: SourceImage;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import * as style from './style.css';
|
|||||||
import 'add-css:./style.css';
|
import 'add-css:./style.css';
|
||||||
import {
|
import {
|
||||||
blobToImg,
|
blobToImg,
|
||||||
|
drawableToImageData,
|
||||||
blobToText,
|
blobToText,
|
||||||
builtinDecode,
|
builtinDecode,
|
||||||
sniffMimeType,
|
sniffMimeType,
|
||||||
@@ -32,7 +33,6 @@ import WorkerBridge from '../worker-bridge';
|
|||||||
import { resize } from 'features/processors/resize/client';
|
import { resize } from 'features/processors/resize/client';
|
||||||
import type SnackBarElement from 'shared/custom-els/snack-bar';
|
import type SnackBarElement from 'shared/custom-els/snack-bar';
|
||||||
import { generateCliInvocation } from '../util/cli';
|
import { generateCliInvocation } from '../util/cli';
|
||||||
import { drawableToImageData } from '../util/canvas';
|
|
||||||
|
|
||||||
export type OutputType = EncoderType | 'identity';
|
export type OutputType = EncoderType | 'identity';
|
||||||
|
|
||||||
@@ -377,7 +377,6 @@ export default class Compress extends Component<Props, State> {
|
|||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
updateDocumentTitle({ loading: false });
|
updateDocumentTitle({ loading: false });
|
||||||
this.widthQuery.removeListener(this.onMobileWidthChange);
|
|
||||||
this.mainAbortController.abort();
|
this.mainAbortController.abort();
|
||||||
for (const controller of this.sideAbortControllers) {
|
for (const controller of this.sideAbortControllers) {
|
||||||
controller.abort();
|
controller.abort();
|
||||||
|
|||||||
@@ -1,154 +0,0 @@
|
|||||||
/** Replace the contents of a canvas with the given data */
|
|
||||||
export function drawDataToCanvas(canvas: HTMLCanvasElement, data: ImageData) {
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
if (!ctx) throw Error('Canvas not initialized');
|
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
ctx.putImageData(data, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode some image data in a given format using the browser's encoders
|
|
||||||
*
|
|
||||||
* @param {ImageData} data
|
|
||||||
* @param {string} type A mime type, eg image/jpeg.
|
|
||||||
* @param {number} [quality] Between 0-1.
|
|
||||||
*/
|
|
||||||
export async function canvasEncode(
|
|
||||||
data: ImageData,
|
|
||||||
type: string,
|
|
||||||
quality?: number,
|
|
||||||
): Promise<Blob> {
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
canvas.width = data.width;
|
|
||||||
canvas.height = data.height;
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
if (!ctx) throw Error('Canvas not initialized');
|
|
||||||
ctx.putImageData(data, 0, 0);
|
|
||||||
|
|
||||||
let blob: Blob | null;
|
|
||||||
|
|
||||||
if ('toBlob' in canvas) {
|
|
||||||
blob = await new Promise<Blob | null>((r) =>
|
|
||||||
canvas.toBlob(r, type, quality),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Welcome to Edge.
|
|
||||||
// TypeScript thinks `canvas` is 'never', so it needs casting.
|
|
||||||
const dataUrl = (canvas as HTMLCanvasElement).toDataURL(type, quality);
|
|
||||||
const result = /data:([^;]+);base64,(.*)$/.exec(dataUrl);
|
|
||||||
|
|
||||||
if (!result) throw Error('Data URL reading failed');
|
|
||||||
|
|
||||||
const outputType = result[1];
|
|
||||||
const binaryStr = atob(result[2]);
|
|
||||||
const data = new Uint8Array(binaryStr.length);
|
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i += 1) {
|
|
||||||
data[i] = binaryStr.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
blob = new Blob([data], { type: outputType });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!blob) throw Error('Encoding failed');
|
|
||||||
return blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DrawableToImageDataOptions {
|
|
||||||
width?: number;
|
|
||||||
height?: number;
|
|
||||||
sx?: number;
|
|
||||||
sy?: number;
|
|
||||||
sw?: number;
|
|
||||||
sh?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWidth(
|
|
||||||
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
|
||||||
): number {
|
|
||||||
if ('displayWidth' in drawable) {
|
|
||||||
return drawable.displayWidth;
|
|
||||||
}
|
|
||||||
return drawable.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getHeight(
|
|
||||||
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
|
||||||
): number {
|
|
||||||
if ('displayHeight' in drawable) {
|
|
||||||
return drawable.displayHeight;
|
|
||||||
}
|
|
||||||
return drawable.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function drawableToImageData(
|
|
||||||
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
|
||||||
opts: DrawableToImageDataOptions = {},
|
|
||||||
): ImageData {
|
|
||||||
const {
|
|
||||||
width = getWidth(drawable),
|
|
||||||
height = getHeight(drawable),
|
|
||||||
sx = 0,
|
|
||||||
sy = 0,
|
|
||||||
sw = getWidth(drawable),
|
|
||||||
sh = getHeight(drawable),
|
|
||||||
} = opts;
|
|
||||||
|
|
||||||
// Make canvas same size as image
|
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
canvas.width = width;
|
|
||||||
canvas.height = height;
|
|
||||||
// Draw image onto canvas
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
if (!ctx) throw new Error('Could not create canvas context');
|
|
||||||
ctx.drawImage(drawable, sx, sy, sw, sh, 0, 0, width, height);
|
|
||||||
return ctx.getImageData(0, 0, width, height);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BuiltinResizeMethod = 'pixelated' | 'low' | 'medium' | 'high';
|
|
||||||
|
|
||||||
export function builtinResize(
|
|
||||||
data: ImageData,
|
|
||||||
sx: number,
|
|
||||||
sy: number,
|
|
||||||
sw: number,
|
|
||||||
sh: number,
|
|
||||||
dw: number,
|
|
||||||
dh: number,
|
|
||||||
method: BuiltinResizeMethod,
|
|
||||||
): ImageData {
|
|
||||||
const canvasSource = document.createElement('canvas');
|
|
||||||
canvasSource.width = data.width;
|
|
||||||
canvasSource.height = data.height;
|
|
||||||
drawDataToCanvas(canvasSource, data);
|
|
||||||
|
|
||||||
const canvasDest = document.createElement('canvas');
|
|
||||||
canvasDest.width = dw;
|
|
||||||
canvasDest.height = dh;
|
|
||||||
const ctx = canvasDest.getContext('2d');
|
|
||||||
if (!ctx) throw new Error('Could not create canvas context');
|
|
||||||
|
|
||||||
if (method === 'pixelated') {
|
|
||||||
ctx.imageSmoothingEnabled = false;
|
|
||||||
} else {
|
|
||||||
ctx.imageSmoothingQuality = method;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.drawImage(canvasSource, sx, sy, sw, sh, 0, 0, dw, dh);
|
|
||||||
return ctx.getImageData(0, 0, dw, dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether <canvas> can encode to a particular type.
|
|
||||||
*/
|
|
||||||
export async function canvasEncodeTest(mimeType: string): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
const blob = await canvasEncode(new ImageData(1, 1), mimeType);
|
|
||||||
// According to the spec, the blob should be null if the format isn't supported…
|
|
||||||
if (!blob) return false;
|
|
||||||
// …but Safari & Firefox fall back to PNG, so we need to check the mime type.
|
|
||||||
return blob.type === mimeType;
|
|
||||||
} catch (err) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import * as WebCodecs from '../util/web-codecs';
|
import * as WebCodecs from '../util/web-codecs';
|
||||||
import { drawableToImageData } from './canvas';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare two objects, returning a boolean indicating if
|
* Compare two objects, returning a boolean indicating if
|
||||||
@@ -24,6 +23,62 @@ export function shallowEqual(one: any, two: any) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Replace the contents of a canvas with the given data */
|
||||||
|
export function drawDataToCanvas(canvas: HTMLCanvasElement, data: ImageData) {
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (!ctx) throw Error('Canvas not initialized');
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.putImageData(data, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode some image data in a given format using the browser's encoders
|
||||||
|
*
|
||||||
|
* @param {ImageData} data
|
||||||
|
* @param {string} type A mime type, eg image/jpeg.
|
||||||
|
* @param {number} [quality] Between 0-1.
|
||||||
|
*/
|
||||||
|
export async function canvasEncode(
|
||||||
|
data: ImageData,
|
||||||
|
type: string,
|
||||||
|
quality?: number,
|
||||||
|
): Promise<Blob> {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = data.width;
|
||||||
|
canvas.height = data.height;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (!ctx) throw Error('Canvas not initialized');
|
||||||
|
ctx.putImageData(data, 0, 0);
|
||||||
|
|
||||||
|
let blob: Blob | null;
|
||||||
|
|
||||||
|
if ('toBlob' in canvas) {
|
||||||
|
blob = await new Promise<Blob | null>((r) =>
|
||||||
|
canvas.toBlob(r, type, quality),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Welcome to Edge.
|
||||||
|
// TypeScript thinks `canvas` is 'never', so it needs casting.
|
||||||
|
const dataUrl = (canvas as HTMLCanvasElement).toDataURL(type, quality);
|
||||||
|
const result = /data:([^;]+);base64,(.*)$/.exec(dataUrl);
|
||||||
|
|
||||||
|
if (!result) throw Error('Data URL reading failed');
|
||||||
|
|
||||||
|
const outputType = result[1];
|
||||||
|
const binaryStr = atob(result[2]);
|
||||||
|
const data = new Uint8Array(binaryStr.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i += 1) {
|
||||||
|
data[i] = binaryStr.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
blob = new Blob([data], { type: outputType });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blob) throw Error('Encoding failed');
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
async function decodeImage(url: string): Promise<HTMLImageElement> {
|
async function decodeImage(url: string): Promise<HTMLImageElement> {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.decoding = 'async';
|
img.decoding = 'async';
|
||||||
@@ -131,6 +186,57 @@ export async function blobToImg(blob: Blob): Promise<HTMLImageElement> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DrawableToImageDataOptions {
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
sx?: number;
|
||||||
|
sy?: number;
|
||||||
|
sw?: number;
|
||||||
|
sh?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWidth(
|
||||||
|
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
||||||
|
): number {
|
||||||
|
if ('displayWidth' in drawable) {
|
||||||
|
return drawable.displayWidth;
|
||||||
|
}
|
||||||
|
return drawable.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHeight(
|
||||||
|
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
||||||
|
): number {
|
||||||
|
if ('displayHeight' in drawable) {
|
||||||
|
return drawable.displayHeight;
|
||||||
|
}
|
||||||
|
return drawable.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function drawableToImageData(
|
||||||
|
drawable: ImageBitmap | HTMLImageElement | VideoFrame,
|
||||||
|
opts: DrawableToImageDataOptions = {},
|
||||||
|
): ImageData {
|
||||||
|
const {
|
||||||
|
width = getWidth(drawable),
|
||||||
|
height = getHeight(drawable),
|
||||||
|
sx = 0,
|
||||||
|
sy = 0,
|
||||||
|
sw = getWidth(drawable),
|
||||||
|
sh = getHeight(drawable),
|
||||||
|
} = opts;
|
||||||
|
|
||||||
|
// Make canvas same size as image
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
// Draw image onto canvas
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
if (!ctx) throw new Error('Could not create canvas context');
|
||||||
|
ctx.drawImage(drawable, sx, sy, sw, sh, 0, 0, width, height);
|
||||||
|
return ctx.getImageData(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
export async function builtinDecode(
|
export async function builtinDecode(
|
||||||
signal: AbortSignal,
|
signal: AbortSignal,
|
||||||
blob: Blob,
|
blob: Blob,
|
||||||
@@ -153,6 +259,39 @@ export async function builtinDecode(
|
|||||||
return drawableToImageData(drawable);
|
return drawableToImageData(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BuiltinResizeMethod = 'pixelated' | 'low' | 'medium' | 'high';
|
||||||
|
|
||||||
|
export function builtinResize(
|
||||||
|
data: ImageData,
|
||||||
|
sx: number,
|
||||||
|
sy: number,
|
||||||
|
sw: number,
|
||||||
|
sh: number,
|
||||||
|
dw: number,
|
||||||
|
dh: number,
|
||||||
|
method: BuiltinResizeMethod,
|
||||||
|
): ImageData {
|
||||||
|
const canvasSource = document.createElement('canvas');
|
||||||
|
canvasSource.width = data.width;
|
||||||
|
canvasSource.height = data.height;
|
||||||
|
drawDataToCanvas(canvasSource, data);
|
||||||
|
|
||||||
|
const canvasDest = document.createElement('canvas');
|
||||||
|
canvasDest.width = dw;
|
||||||
|
canvasDest.height = dh;
|
||||||
|
const ctx = canvasDest.getContext('2d');
|
||||||
|
if (!ctx) throw new Error('Could not create canvas context');
|
||||||
|
|
||||||
|
if (method === 'pixelated') {
|
||||||
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
} else {
|
||||||
|
ctx.imageSmoothingQuality = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(canvasSource, sx, sy, sw, sh, 0, 0, dw, dh);
|
||||||
|
return ctx.getImageData(0, 0, dw, dh);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param field An HTMLInputElement, but the casting is done here to tidy up onChange.
|
* @param field An HTMLInputElement, but the casting is done here to tidy up onChange.
|
||||||
* @param defaultVal Value to return if 'field' doesn't exist.
|
* @param defaultVal Value to return if 'field' doesn't exist.
|
||||||
@@ -295,3 +434,18 @@ export async function abortable<T>(
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether <canvas> can encode to a particular type.
|
||||||
|
*/
|
||||||
|
export async function canvasEncodeTest(mimeType: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const blob = await canvasEncode(new ImageData(1, 1), mimeType);
|
||||||
|
// According to the spec, the blob should be null if the format isn't supported…
|
||||||
|
if (!blob) return false;
|
||||||
|
// …but Safari & Firefox fall back to PNG, so we need to check the mime type.
|
||||||
|
return blob.type === mimeType;
|
||||||
|
} catch (err) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,19 +1,12 @@
|
|||||||
import { drawableToImageData } from '../canvas';
|
import { drawableToImageData } from 'client/lazy-app/util';
|
||||||
|
|
||||||
const hasImageDecoder = typeof ImageDecoder !== 'undefined';
|
const hasImageDecoder = typeof ImageDecoder !== 'undefined';
|
||||||
|
|
||||||
export async function isTypeSupported(mimeType: string): Promise<boolean> {
|
export async function isTypeSupported(mimeType: string): Promise<boolean> {
|
||||||
if (!hasImageDecoder) return false;
|
if (!hasImageDecoder) {
|
||||||
// Some old versions of this API threw here.
|
|
||||||
// It only impacted folks with experimental web platform flags enabled in Chrome 90.
|
|
||||||
// The API was updated in Chrome 91.
|
|
||||||
try {
|
|
||||||
return await ImageDecoder.isTypeSupported(mimeType);
|
|
||||||
} catch (err) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return ImageDecoder.isTypeSupported(mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function decode(
|
export async function decode(
|
||||||
blob: Blob | File,
|
blob: Blob | File,
|
||||||
mimeType: string,
|
mimeType: string,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { canvasEncodeTest, canvasEncode } from 'client/lazy-app/util/canvas';
|
import { canvasEncodeTest, canvasEncode } from 'client/lazy-app/util';
|
||||||
import WorkerBridge from 'client/lazy-app/worker-bridge';
|
import WorkerBridge from 'client/lazy-app/worker-bridge';
|
||||||
import { EncodeOptions, mimeType } from '../shared/meta';
|
import { EncodeOptions, mimeType } from '../shared/meta';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { canvasEncode } from 'client/lazy-app/util/canvas';
|
import { canvasEncode } from 'client/lazy-app/util';
|
||||||
import WorkerBridge from 'client/lazy-app/worker-bridge';
|
import WorkerBridge from 'client/lazy-app/worker-bridge';
|
||||||
import { qualityOption } from 'features/client-utils';
|
import { qualityOption } from 'features/client-utils';
|
||||||
import { mimeType, EncodeOptions } from '../shared/meta';
|
import { mimeType, EncodeOptions } from '../shared/meta';
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { canvasEncode } from 'client/lazy-app/util/canvas';
|
import { canvasEncode } from 'client/lazy-app/util';
|
||||||
import WorkerBridge from 'client/lazy-app/worker-bridge';
|
import WorkerBridge from 'client/lazy-app/worker-bridge';
|
||||||
import { EncodeOptions, mimeType } from '../shared/meta';
|
import { EncodeOptions, mimeType } from '../shared/meta';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { canvasEncode } from 'client/lazy-app/util/canvas';
|
|
||||||
import {
|
import {
|
||||||
|
canvasEncode,
|
||||||
abortable,
|
abortable,
|
||||||
blobToArrayBuffer,
|
blobToArrayBuffer,
|
||||||
inputFieldChecked,
|
inputFieldChecked,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
builtinResize,
|
builtinResize,
|
||||||
BuiltinResizeMethod,
|
BuiltinResizeMethod,
|
||||||
drawableToImageData,
|
drawableToImageData,
|
||||||
} from 'client/lazy-app/util/canvas';
|
} from 'client/lazy-app/util';
|
||||||
import {
|
import {
|
||||||
BrowserResizeOptions,
|
BrowserResizeOptions,
|
||||||
VectorResizeOptions,
|
VectorResizeOptions,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user