forked from external-repos/squoosh
Compare commits
52 Commits
rollup-bui
...
cli-invoc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8105633ca6 | ||
|
|
46764f3375 | ||
|
|
0371cfd292 | ||
|
|
3d1ecc1215 | ||
|
|
25fb1a9c80 | ||
|
|
3ae1cf86f5 | ||
|
|
a699a5c4dc | ||
|
|
613401c541 | ||
|
|
f450373e3f | ||
|
|
750872aca6 | ||
|
|
beaabe47dc | ||
|
|
8f7369068c | ||
|
|
10bfd60e20 | ||
|
|
7f08348509 | ||
|
|
f77ddac652 | ||
|
|
13631f1cfc | ||
|
|
f11e692d58 | ||
|
|
f0221b626d | ||
|
|
10c5ed0495 | ||
|
|
d945c79796 | ||
|
|
30b628c1b9 | ||
|
|
6ebf94d1b6 | ||
|
|
a229662bed | ||
|
|
e995b445ef | ||
|
|
6da590c7d0 | ||
|
|
56e10b3aa2 | ||
|
|
fd87ae7d2a | ||
|
|
5df7dd7590 | ||
|
|
013946b137 | ||
|
|
81c183b0d6 | ||
|
|
f523db6403 | ||
|
|
cc6ea9e11c | ||
|
|
bd4b67037b | ||
|
|
8c5c97e106 | ||
|
|
a9d3bd71b5 | ||
|
|
0d0a9b4cdf | ||
|
|
f583770696 | ||
|
|
bae243ccdb | ||
|
|
02c113a68f | ||
|
|
600eead007 | ||
|
|
05416768d5 | ||
|
|
35d31f2324 | ||
|
|
82fadac70e | ||
|
|
47f9d22dd8 | ||
|
|
9420dba3bc | ||
|
|
e462875807 | ||
|
|
0747d2c419 | ||
|
|
4c658b79ef | ||
|
|
685558847f | ||
|
|
63ac34a662 | ||
|
|
42f9e4aed2 | ||
|
|
e14790f0b9 |
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/codecs/**/*.js linguist-generated=true
|
||||||
|
/codecs/*/pkg*/*.d.ts linguist-generated=true
|
||||||
22
.github/workflows/node.js.yml
vendored
Normal file
22
.github/workflows/node.js.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Node.js CI
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- id: nvmrc
|
||||||
|
uses: browniebroke/read-nvmrc-action@v1
|
||||||
|
- uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '${{ steps.nvmrc.outputs.node_version }}'
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
12
.prettierignore
Normal file
12
.prettierignore
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
codecs
|
||||||
|
.tmp
|
||||||
|
node_modules
|
||||||
|
*.scss.d.ts
|
||||||
|
*.css.d.ts
|
||||||
|
build
|
||||||
|
*.o
|
||||||
|
|
||||||
|
# Auto-generated by lib/feature-plugin.js
|
||||||
|
src/features-worker/index.ts
|
||||||
|
src/client/lazy-app/worker-bridge/meta.ts
|
||||||
|
src/client/lazy-app/feature-meta/index.ts
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
cache: npm
|
|
||||||
script: npm run build
|
|
||||||
after_success: npm run sizereport
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- windows
|
|
||||||
0
codecs/avif/enc/avif_enc_mt.wasm
Executable file → Normal file
0
codecs/avif/enc/avif_enc_mt.wasm
Executable file → Normal file
@@ -14,12 +14,33 @@ thread_local const val ImageData = val::global("ImageData");
|
|||||||
// R, G, B, A
|
// R, G, B, A
|
||||||
#define COMPONENTS_PER_PIXEL 4
|
#define COMPONENTS_PER_PIXEL 4
|
||||||
|
|
||||||
|
#ifndef JXL_DEBUG_ON_ALL_ERROR
|
||||||
|
#define JXL_DEBUG_ON_ALL_ERROR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if JXL_DEBUG_ON_ALL_ERROR
|
||||||
|
#define EXPECT_TRUE(a) \
|
||||||
|
if (!(a)) { \
|
||||||
|
fprintf(stderr, "Assertion failure (%d): %s\n", __LINE__, #a); \
|
||||||
|
return val::null(); \
|
||||||
|
}
|
||||||
|
#define EXPECT_EQ(a, b) \
|
||||||
|
{ \
|
||||||
|
int a_ = a; \
|
||||||
|
int b_ = b; \
|
||||||
|
if (a_ != b_) { \
|
||||||
|
fprintf(stderr, "Assertion failure (%d): %s (%d) != %s (%d)\n", __LINE__, #a, a_, #b, b_); \
|
||||||
|
return val::null(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#else
|
||||||
#define EXPECT_TRUE(a) \
|
#define EXPECT_TRUE(a) \
|
||||||
if (!(a)) { \
|
if (!(a)) { \
|
||||||
return val::null(); \
|
return val::null(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXPECT_EQ(a, b) EXPECT_TRUE((a) == (b));
|
#define EXPECT_EQ(a, b) EXPECT_TRUE((a) == (b));
|
||||||
|
#endif
|
||||||
|
|
||||||
val decode(std::string data) {
|
val decode(std::string data) {
|
||||||
std::unique_ptr<JxlDecoder,
|
std::unique_ptr<JxlDecoder,
|
||||||
|
|||||||
Binary file not shown.
@@ -38,7 +38,14 @@ val encode(std::string image, int width, int height, JXLOptions options) {
|
|||||||
|
|
||||||
// Reduce memory usage of tree learning for lossless data.
|
// Reduce memory usage of tree learning for lossless data.
|
||||||
// TODO(veluca93): this is a mitigation for excessive memory usage in the JXL encoder.
|
// TODO(veluca93): this is a mitigation for excessive memory usage in the JXL encoder.
|
||||||
cparams.options.nb_repeats = 0.1;
|
float megapixels = width * height * 0.000001;
|
||||||
|
if (megapixels > 8) {
|
||||||
|
cparams.options.nb_repeats = 0.1;
|
||||||
|
} else if (megapixels > 4) {
|
||||||
|
cparams.options.nb_repeats = 0.3;
|
||||||
|
} else {
|
||||||
|
// default is OK.
|
||||||
|
}
|
||||||
|
|
||||||
float quality = options.quality;
|
float quality = options.quality;
|
||||||
|
|
||||||
@@ -59,8 +66,10 @@ val encode(std::string image, int width, int height, JXLOptions options) {
|
|||||||
|
|
||||||
if (options.progressive) {
|
if (options.progressive) {
|
||||||
cparams.qprogressive_mode = true;
|
cparams.qprogressive_mode = true;
|
||||||
cparams.progressive_dc = 1;
|
|
||||||
cparams.responsive = 1;
|
cparams.responsive = 1;
|
||||||
|
if (!cparams.modular_mode) {
|
||||||
|
cparams.progressive_dc = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cparams.modular_mode) {
|
if (cparams.modular_mode) {
|
||||||
|
|||||||
Binary file not shown.
12
codecs/oxipng/Cargo.lock
generated
12
codecs/oxipng/Cargo.lock
generated
@@ -247,18 +247,18 @@ checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libdeflate-sys"
|
name = "libdeflate-sys"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "21e39efa87b84db3e13ff4e2dfac1e57220abcbd7fe8ec44d238f7f4f787cc1f"
|
checksum = "2f5b1582a0ebf8c55a46166c04d7c66f6bb17add3a6cbf69a082ac2219f31671"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libdeflater"
|
name = "libdeflater"
|
||||||
version = "0.5.0"
|
version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4810980d791f26d470e2d7d91a3d4d22aa3a4b709fb7e9c5e43ee54f83a01f2"
|
checksum = "93edd93a53970951da84ef733a8b6e30189a8f8a9e19610f69e4cc5bb1f4d654"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libdeflate-sys",
|
"libdeflate-sys",
|
||||||
]
|
]
|
||||||
@@ -359,9 +359,9 @@ checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxipng"
|
name = "oxipng"
|
||||||
version = "4.0.0"
|
version = "4.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea40b366cecfce76ee3b082e7e6567b82cdef75644a22442ca8584bc666ff4eb"
|
checksum = "9fefb26bde273c3db896a313151301a69e698a7495ee577fe2168ed7065c29c4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-vec",
|
"bit-vec",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
|||||||
4
codecs/oxipng/build.sh
Executable file → Normal file
4
codecs/oxipng/build.sh
Executable file → Normal file
@@ -3,6 +3,8 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
rm -rf pkg,{-parallel}
|
rm -rf pkg,{-parallel}
|
||||||
wasm-pack build --target web
|
wasm-pack build -t web
|
||||||
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' wasm-pack build -t web -d pkg-parallel -- -Z build-std=panic_abort,std --features=parallel
|
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' wasm-pack build -t web -d pkg-parallel -- -Z build-std=panic_abort,std --features=parallel
|
||||||
|
# Workaround https://github.com/rustwasm/wasm-bindgen/issues/2133:
|
||||||
|
sed -i "s|maybe_memory:|maybe_memory?:|" pkg-parallel/squoosh_oxipng.d.ts
|
||||||
rm pkg{,-parallel}/.gitignore
|
rm pkg{,-parallel}/.gitignore
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "oxipng",
|
"name": "oxipng",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "RUST_IMG=rustlang/rust:8bb115b1090d ../build-rust.sh ./build.sh"
|
"build": "RUST_IMG=rustlang/rust@sha256:744aeea5a38f95aa7a96ec37269a65f0c6197a1cdd87d6534e12bb869141d807 ../build-rust.sh ./build.sh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
codecs/oxipng/pkg-parallel/squoosh_oxipng.d.ts
generated
vendored
47
codecs/oxipng/pkg-parallel/squoosh_oxipng.d.ts
generated
vendored
@@ -1,29 +1,24 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @param {number} level
|
* @param {number} level
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export function optimise(data: Uint8Array, level: number): Uint8Array;
|
export function optimise(data: Uint8Array, level: number): Uint8Array;
|
||||||
/**
|
/**
|
||||||
* @param {number} num
|
* @param {number} num
|
||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
export function worker_initializer(num: number): any;
|
export function worker_initializer(num: number): any;
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function start_main_thread(): void;
|
export function start_main_thread(): void;
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function start_worker_thread(): void;
|
export function start_worker_thread(): void;
|
||||||
|
|
||||||
export type InitInput =
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
| RequestInfo
|
|
||||||
| URL
|
|
||||||
| Response
|
|
||||||
| BufferSource
|
|
||||||
| WebAssembly.Module;
|
|
||||||
|
|
||||||
export interface InitOutput {
|
export interface InitOutput {
|
||||||
readonly optimise: (a: number, b: number, c: number, d: number) => void;
|
readonly optimise: (a: number, b: number, c: number, d: number) => void;
|
||||||
@@ -39,15 +34,13 @@ export interface InitOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||||
*
|
*
|
||||||
* @param {InitInput | Promise<InitInput>} module_or_path
|
* @param {InitInput | Promise<InitInput>} module_or_path
|
||||||
* @param {WebAssembly.Memory} maybe_memory
|
* @param {WebAssembly.Memory} maybe_memory
|
||||||
*
|
*
|
||||||
* @returns {Promise<InitOutput>}
|
* @returns {Promise<InitOutput>}
|
||||||
*/
|
*/
|
||||||
export default function init(
|
export default function init (module_or_path?: InitInput | Promise<InitInput>, maybe_memory?: WebAssembly.Memory): Promise<InitOutput>;
|
||||||
module_or_path?: InitInput | Promise<InitInput>,
|
|
||||||
maybe_memory?: WebAssembly.Memory,
|
|
||||||
): Promise<InitOutput>;
|
|
||||||
234
codecs/oxipng/pkg-parallel/squoosh_oxipng.js
generated
234
codecs/oxipng/pkg-parallel/squoosh_oxipng.js
generated
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
let wasm;
|
let wasm;
|
||||||
let memory;
|
let memory;
|
||||||
|
|
||||||
@@ -8,189 +9,172 @@ heap.push(undefined, null, true, false);
|
|||||||
let heap_next = heap.length;
|
let heap_next = heap.length;
|
||||||
|
|
||||||
function addHeapObject(obj) {
|
function addHeapObject(obj) {
|
||||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||||
const idx = heap_next;
|
const idx = heap_next;
|
||||||
heap_next = heap[idx];
|
heap_next = heap[idx];
|
||||||
|
|
||||||
heap[idx] = obj;
|
heap[idx] = obj;
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachedTextDecoder = new TextDecoder('utf-8', {
|
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||||
ignoreBOM: true,
|
|
||||||
fatal: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
cachedTextDecoder.decode();
|
cachedTextDecoder.decode();
|
||||||
|
|
||||||
let cachegetUint8Memory0 = null;
|
let cachegetUint8Memory0 = null;
|
||||||
function getUint8Memory0() {
|
function getUint8Memory0() {
|
||||||
if (
|
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.__wbindgen_export_0.buffer) {
|
||||||
cachegetUint8Memory0 === null ||
|
cachegetUint8Memory0 = new Uint8Array(wasm.__wbindgen_export_0.buffer);
|
||||||
cachegetUint8Memory0.buffer !== wasm.__wbindgen_export_0.buffer
|
}
|
||||||
) {
|
return cachegetUint8Memory0;
|
||||||
cachegetUint8Memory0 = new Uint8Array(wasm.__wbindgen_export_0.buffer);
|
|
||||||
}
|
|
||||||
return cachegetUint8Memory0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStringFromWasm0(ptr, len) {
|
function getStringFromWasm0(ptr, len) {
|
||||||
return cachedTextDecoder.decode(getUint8Memory0().slice(ptr, ptr + len));
|
return cachedTextDecoder.decode(getUint8Memory0().slice(ptr, ptr + len));
|
||||||
}
|
}
|
||||||
|
|
||||||
let WASM_VECTOR_LEN = 0;
|
let WASM_VECTOR_LEN = 0;
|
||||||
|
|
||||||
function passArray8ToWasm0(arg, malloc) {
|
function passArray8ToWasm0(arg, malloc) {
|
||||||
const ptr = malloc(arg.length * 1);
|
const ptr = malloc(arg.length * 1);
|
||||||
getUint8Memory0().set(arg, ptr / 1);
|
getUint8Memory0().set(arg, ptr / 1);
|
||||||
WASM_VECTOR_LEN = arg.length;
|
WASM_VECTOR_LEN = arg.length;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachegetInt32Memory0 = null;
|
let cachegetInt32Memory0 = null;
|
||||||
function getInt32Memory0() {
|
function getInt32Memory0() {
|
||||||
if (
|
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.__wbindgen_export_0.buffer) {
|
||||||
cachegetInt32Memory0 === null ||
|
cachegetInt32Memory0 = new Int32Array(wasm.__wbindgen_export_0.buffer);
|
||||||
cachegetInt32Memory0.buffer !== wasm.__wbindgen_export_0.buffer
|
}
|
||||||
) {
|
return cachegetInt32Memory0;
|
||||||
cachegetInt32Memory0 = new Int32Array(wasm.__wbindgen_export_0.buffer);
|
|
||||||
}
|
|
||||||
return cachegetInt32Memory0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getArrayU8FromWasm0(ptr, len) {
|
function getArrayU8FromWasm0(ptr, len) {
|
||||||
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @param {number} level
|
* @param {number} level
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export function optimise(data, level) {
|
export function optimise(data, level) {
|
||||||
try {
|
try {
|
||||||
const retptr = wasm.__wbindgen_export_1.value - 16;
|
const retptr = wasm.__wbindgen_export_1.value - 16;
|
||||||
wasm.__wbindgen_export_1.value = retptr;
|
wasm.__wbindgen_export_1.value = retptr;
|
||||||
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
||||||
var len0 = WASM_VECTOR_LEN;
|
var len0 = WASM_VECTOR_LEN;
|
||||||
wasm.optimise(retptr, ptr0, len0, level);
|
wasm.optimise(retptr, ptr0, len0, level);
|
||||||
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 = getArrayU8FromWasm0(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 {
|
||||||
wasm.__wbindgen_export_1.value += 16;
|
wasm.__wbindgen_export_1.value += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getObject(idx) {
|
function getObject(idx) { return heap[idx]; }
|
||||||
return heap[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
function dropObject(idx) {
|
function dropObject(idx) {
|
||||||
if (idx < 36) return;
|
if (idx < 36) return;
|
||||||
heap[idx] = heap_next;
|
heap[idx] = heap_next;
|
||||||
heap_next = idx;
|
heap_next = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
function takeObject(idx) {
|
function takeObject(idx) {
|
||||||
const ret = getObject(idx);
|
const ret = getObject(idx);
|
||||||
dropObject(idx);
|
dropObject(idx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {number} num
|
* @param {number} num
|
||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
export function worker_initializer(num) {
|
export function worker_initializer(num) {
|
||||||
var ret = wasm.worker_initializer(num);
|
var ret = wasm.worker_initializer(num);
|
||||||
return takeObject(ret);
|
return takeObject(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function start_main_thread() {
|
export function start_main_thread() {
|
||||||
wasm.start_main_thread();
|
wasm.start_main_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
export function start_worker_thread() {
|
export function start_worker_thread() {
|
||||||
wasm.start_worker_thread();
|
wasm.start_worker_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load(module, imports, maybe_memory) {
|
async function load(module, imports, maybe_memory) {
|
||||||
if (typeof Response === 'function' && module instanceof Response) {
|
if (typeof Response === 'function' && module instanceof Response) {
|
||||||
memory = imports.wbg.memory = new WebAssembly.Memory({
|
memory = imports.wbg.memory = new WebAssembly.Memory({initial:17,maximum:16384,shared:true});
|
||||||
initial: 17,
|
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
maximum: 16384,
|
try {
|
||||||
shared: true,
|
return await WebAssembly.instantiateStreaming(module, imports);
|
||||||
});
|
|
||||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
} catch (e) {
|
||||||
try {
|
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||||
return await WebAssembly.instantiateStreaming(module, imports);
|
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||||
} catch (e) {
|
|
||||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
} else {
|
||||||
console.warn(
|
throw e;
|
||||||
'`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n',
|
}
|
||||||
e,
|
}
|
||||||
);
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bytes = await module.arrayBuffer();
|
const bytes = await module.arrayBuffer();
|
||||||
return await WebAssembly.instantiate(bytes, imports);
|
return await WebAssembly.instantiate(bytes, imports);
|
||||||
} else {
|
|
||||||
memory = imports.wbg.memory = maybe_memory;
|
|
||||||
const instance = await WebAssembly.instantiate(module, imports);
|
|
||||||
|
|
||||||
if (instance instanceof WebAssembly.Instance) {
|
|
||||||
return { instance, module };
|
|
||||||
} else {
|
} else {
|
||||||
return instance;
|
memory = imports.wbg.memory = maybe_memory;
|
||||||
|
const instance = await WebAssembly.instantiate(module, imports);
|
||||||
|
|
||||||
|
if (instance instanceof WebAssembly.Instance) {
|
||||||
|
return { instance, module };
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function init(input, maybe_memory) {
|
async function init(input, maybe_memory) {
|
||||||
if (typeof input === 'undefined') {
|
if (typeof input === 'undefined') {
|
||||||
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|
||||||
}
|
}
|
||||||
const imports = {};
|
const imports = {};
|
||||||
imports.wbg = {};
|
imports.wbg = {};
|
||||||
imports.wbg.__wbindgen_module = function () {
|
imports.wbg.__wbindgen_module = function() {
|
||||||
var ret = init.__wbindgen_wasm_module;
|
var ret = init.__wbindgen_wasm_module;
|
||||||
return addHeapObject(ret);
|
return addHeapObject(ret);
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_memory = function () {
|
imports.wbg.__wbindgen_memory = function() {
|
||||||
var ret = wasm.__wbindgen_export_0;
|
var ret = wasm.__wbindgen_export_0;
|
||||||
return addHeapObject(ret);
|
return addHeapObject(ret);
|
||||||
};
|
};
|
||||||
imports.wbg.__wbg_of_6510501edc06d65e = function (arg0, arg1) {
|
imports.wbg.__wbg_of_6510501edc06d65e = function(arg0, arg1) {
|
||||||
var ret = Array.of(takeObject(arg0), takeObject(arg1));
|
var ret = Array.of(takeObject(arg0), takeObject(arg1));
|
||||||
return addHeapObject(ret);
|
return addHeapObject(ret);
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_throw = function (arg0, arg1) {
|
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||||
typeof input === 'string' ||
|
input = fetch(input);
|
||||||
(typeof Request === 'function' && input instanceof Request) ||
|
}
|
||||||
(typeof URL === 'function' && input instanceof URL)
|
|
||||||
) {
|
|
||||||
input = fetch(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { instance, module } = await load(await input, imports, maybe_memory);
|
const { instance, module } = await load(await input, imports, maybe_memory);
|
||||||
|
|
||||||
wasm = instance.exports;
|
wasm = instance.exports;
|
||||||
init.__wbindgen_wasm_module = module;
|
init.__wbindgen_wasm_module = module;
|
||||||
wasm.__wbindgen_start();
|
wasm.__wbindgen_start();
|
||||||
return wasm;
|
return wasm;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default init;
|
export default init;
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
34
codecs/oxipng/pkg/squoosh_oxipng.d.ts
generated
vendored
34
codecs/oxipng/pkg/squoosh_oxipng.d.ts
generated
vendored
@@ -1,18 +1,13 @@
|
|||||||
/* tslint:disable */
|
/* tslint:disable */
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
/**
|
/**
|
||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @param {number} level
|
* @param {number} level
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export function optimise(data: Uint8Array, level: number): Uint8Array;
|
export function optimise(data: Uint8Array, level: number): Uint8Array;
|
||||||
|
|
||||||
export type InitInput =
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
| RequestInfo
|
|
||||||
| URL
|
|
||||||
| Response
|
|
||||||
| BufferSource
|
|
||||||
| WebAssembly.Module;
|
|
||||||
|
|
||||||
export interface InitOutput {
|
export interface InitOutput {
|
||||||
readonly memory: WebAssembly.Memory;
|
readonly memory: WebAssembly.Memory;
|
||||||
@@ -24,13 +19,12 @@ export interface InitOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||||
*
|
*
|
||||||
* @param {InitInput | Promise<InitInput>} module_or_path
|
* @param {InitInput | Promise<InitInput>} module_or_path
|
||||||
*
|
*
|
||||||
* @returns {Promise<InitOutput>}
|
* @returns {Promise<InitOutput>}
|
||||||
*/
|
*/
|
||||||
export default function init(
|
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||||
module_or_path?: InitInput | Promise<InitInput>,
|
|
||||||
): Promise<InitOutput>;
|
|
||||||
158
codecs/oxipng/pkg/squoosh_oxipng.js
generated
158
codecs/oxipng/pkg/squoosh_oxipng.js
generated
@@ -1,126 +1,118 @@
|
|||||||
|
|
||||||
let wasm;
|
let wasm;
|
||||||
|
|
||||||
let cachedTextDecoder = new TextDecoder('utf-8', {
|
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||||
ignoreBOM: true,
|
|
||||||
fatal: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
cachedTextDecoder.decode();
|
cachedTextDecoder.decode();
|
||||||
|
|
||||||
let cachegetUint8Memory0 = null;
|
let cachegetUint8Memory0 = null;
|
||||||
function getUint8Memory0() {
|
function getUint8Memory0() {
|
||||||
if (
|
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
|
||||||
cachegetUint8Memory0 === null ||
|
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
||||||
cachegetUint8Memory0.buffer !== wasm.memory.buffer
|
}
|
||||||
) {
|
return cachegetUint8Memory0;
|
||||||
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
|
||||||
}
|
|
||||||
return cachegetUint8Memory0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStringFromWasm0(ptr, len) {
|
function getStringFromWasm0(ptr, len) {
|
||||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
||||||
}
|
}
|
||||||
|
|
||||||
let WASM_VECTOR_LEN = 0;
|
let WASM_VECTOR_LEN = 0;
|
||||||
|
|
||||||
function passArray8ToWasm0(arg, malloc) {
|
function passArray8ToWasm0(arg, malloc) {
|
||||||
const ptr = malloc(arg.length * 1);
|
const ptr = malloc(arg.length * 1);
|
||||||
getUint8Memory0().set(arg, ptr / 1);
|
getUint8Memory0().set(arg, ptr / 1);
|
||||||
WASM_VECTOR_LEN = arg.length;
|
WASM_VECTOR_LEN = arg.length;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachegetInt32Memory0 = null;
|
let cachegetInt32Memory0 = null;
|
||||||
function getInt32Memory0() {
|
function getInt32Memory0() {
|
||||||
if (
|
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
|
||||||
cachegetInt32Memory0 === null ||
|
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
||||||
cachegetInt32Memory0.buffer !== wasm.memory.buffer
|
}
|
||||||
) {
|
return cachegetInt32Memory0;
|
||||||
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
|
||||||
}
|
|
||||||
return cachegetInt32Memory0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getArrayU8FromWasm0(ptr, len) {
|
function getArrayU8FromWasm0(ptr, len) {
|
||||||
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @param {number} level
|
* @param {number} level
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export function optimise(data, level) {
|
export function optimise(data, level) {
|
||||||
try {
|
try {
|
||||||
const retptr = wasm.__wbindgen_export_0.value - 16;
|
const retptr = wasm.__wbindgen_export_0.value - 16;
|
||||||
wasm.__wbindgen_export_0.value = retptr;
|
wasm.__wbindgen_export_0.value = retptr;
|
||||||
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
||||||
var len0 = WASM_VECTOR_LEN;
|
var len0 = WASM_VECTOR_LEN;
|
||||||
wasm.optimise(retptr, ptr0, len0, level);
|
wasm.optimise(retptr, ptr0, len0, level);
|
||||||
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 = getArrayU8FromWasm0(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 {
|
||||||
wasm.__wbindgen_export_0.value += 16;
|
wasm.__wbindgen_export_0.value += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function load(module, imports) {
|
async function load(module, imports) {
|
||||||
if (typeof Response === 'function' && module instanceof Response) {
|
if (typeof Response === 'function' && module instanceof Response) {
|
||||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
||||||
try {
|
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
return await WebAssembly.instantiateStreaming(module, imports);
|
try {
|
||||||
} catch (e) {
|
return await WebAssembly.instantiateStreaming(module, imports);
|
||||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
|
||||||
console.warn(
|
} catch (e) {
|
||||||
'`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n',
|
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||||
e,
|
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bytes = await module.arrayBuffer();
|
const bytes = await module.arrayBuffer();
|
||||||
return await WebAssembly.instantiate(bytes, imports);
|
return await WebAssembly.instantiate(bytes, imports);
|
||||||
} else {
|
|
||||||
const instance = await WebAssembly.instantiate(module, imports);
|
|
||||||
|
|
||||||
if (instance instanceof WebAssembly.Instance) {
|
|
||||||
return { instance, module };
|
|
||||||
} else {
|
} else {
|
||||||
return instance;
|
|
||||||
|
const instance = await WebAssembly.instantiate(module, imports);
|
||||||
|
|
||||||
|
if (instance instanceof WebAssembly.Instance) {
|
||||||
|
return { instance, module };
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function init(input) {
|
async function init(input) {
|
||||||
if (typeof input === 'undefined') {
|
if (typeof input === 'undefined') {
|
||||||
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|
||||||
}
|
}
|
||||||
const imports = {};
|
const imports = {};
|
||||||
imports.wbg = {};
|
imports.wbg = {};
|
||||||
imports.wbg.__wbindgen_throw = function (arg0, arg1) {
|
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||||
typeof input === 'string' ||
|
input = fetch(input);
|
||||||
(typeof Request === 'function' && input instanceof Request) ||
|
}
|
||||||
(typeof URL === 'function' && input instanceof URL)
|
|
||||||
) {
|
|
||||||
input = fetch(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { instance, module } = await load(await input, imports);
|
const { instance, module } = await load(await input, imports);
|
||||||
|
|
||||||
wasm = instance.exports;
|
wasm = instance.exports;
|
||||||
init.__wbindgen_wasm_module = module;
|
init.__wbindgen_wasm_module = module;
|
||||||
|
|
||||||
return wasm;
|
return wasm;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default init;
|
export default init;
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,5 +1,5 @@
|
|||||||
use wasm_bindgen::prelude::*;
|
|
||||||
use oxipng::AlphaOptim;
|
use oxipng::AlphaOptim;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
mod malloc_shim;
|
mod malloc_shim;
|
||||||
|
|
||||||
@@ -8,14 +8,14 @@ pub mod parallel;
|
|||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn optimise(data: &[u8], level: u8) -> Vec<u8> {
|
pub fn optimise(data: &[u8], level: u8) -> Vec<u8> {
|
||||||
let mut options = oxipng::Options::from_preset(level);
|
let mut options = oxipng::Options::from_preset(level);
|
||||||
options.alphas.insert(AlphaOptim::Black);
|
options.alphas.insert(AlphaOptim::Black);
|
||||||
options.alphas.insert(AlphaOptim::White);
|
options.alphas.insert(AlphaOptim::White);
|
||||||
options.alphas.insert(AlphaOptim::Up);
|
options.alphas.insert(AlphaOptim::Up);
|
||||||
options.alphas.insert(AlphaOptim::Down);
|
options.alphas.insert(AlphaOptim::Down);
|
||||||
options.alphas.insert(AlphaOptim::Left);
|
options.alphas.insert(AlphaOptim::Left);
|
||||||
options.alphas.insert(AlphaOptim::Right);
|
options.alphas.insert(AlphaOptim::Right);
|
||||||
|
|
||||||
options.deflate = oxipng::Deflaters::Libdeflater;
|
options.deflate = oxipng::Deflaters::Libdeflater;
|
||||||
oxipng::optimize_from_memory(data, &options).unwrap_throw()
|
oxipng::optimize_from_memory(data, &options).unwrap_throw()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crossbeam_channel::{Sender, Receiver, bounded};
|
use crossbeam_channel::{bounded, Receiver, Sender};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
@@ -35,7 +35,8 @@ extern "C" {
|
|||||||
// shared memory and blocks the current thread until they're all grabbed.
|
// shared memory and blocks the current thread until they're all grabbed.
|
||||||
// 4) Provide a `worker_initializer` that is expected to be invoked from various workers,
|
// 4) Provide a `worker_initializer` that is expected to be invoked from various workers,
|
||||||
// reads one `threadPtr` from the shared channel and starts running it.
|
// reads one `threadPtr` from the shared channel and starts running it.
|
||||||
static CHANNEL: OnceCell<(Sender<rayon::ThreadBuilder>, Receiver<rayon::ThreadBuilder>)> = OnceCell::new();
|
static CHANNEL: OnceCell<(Sender<rayon::ThreadBuilder>, Receiver<rayon::ThreadBuilder>)> =
|
||||||
|
OnceCell::new();
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn worker_initializer(num: usize) -> JsValue {
|
pub fn worker_initializer(num: usize) -> JsValue {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ RUN wget -qO- https://github.com/rustwasm/wasm-pack/releases/download/v0.9.1/was
|
|||||||
FROM $RUST_IMG AS rust
|
FROM $RUST_IMG AS rust
|
||||||
ARG RUST_IMG
|
ARG RUST_IMG
|
||||||
RUN rustup target add wasm32-unknown-unknown
|
RUN rustup target add wasm32-unknown-unknown
|
||||||
RUN if [[ $RUST_IMG = rustlang/rust:* ]] ; then rustup component add rust-src ; fi
|
RUN case $RUST_IMG in rustlang/rust@*) rustup component add rust-src; esac
|
||||||
COPY --from=wasm-tools /emsdk/upstream/bin/wasm-opt /emsdk/upstream/bin/clang /usr/local/bin/
|
COPY --from=wasm-tools /emsdk/upstream/bin/wasm-opt /emsdk/upstream/bin/clang /usr/local/bin/
|
||||||
COPY --from=wasm-tools /emsdk/upstream/lib/ /usr/local/lib/
|
COPY --from=wasm-tools /emsdk/upstream/lib/ /usr/local/lib/
|
||||||
COPY --from=wasm-tools /emsdk/upstream/emscripten/system/include/libc/ /wasm32/include/
|
COPY --from=wasm-tools /emsdk/upstream/emscripten/system/include/libc/ /wasm32/include/
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ val decode(std::string buffer) {
|
|||||||
int width, height;
|
int width, height;
|
||||||
std::unique_ptr<uint8_t[]> rgba(
|
std::unique_ptr<uint8_t[]> rgba(
|
||||||
WebPDecodeRGBA((const uint8_t*)buffer.c_str(), buffer.size(), &width, &height));
|
WebPDecodeRGBA((const uint8_t*)buffer.c_str(), buffer.size(), &width, &height));
|
||||||
return rgba ? ImageData.new_(Uint8ClampedArray.new_(typed_memory_view(width * height * 4, rgba.get())), width, height) : val::null();
|
return rgba ? ImageData.new_(
|
||||||
|
Uint8ClampedArray.new_(typed_memory_view(width * height * 4, rgba.get())),
|
||||||
|
width, height)
|
||||||
|
: val::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_BINDINGS(my_module) {
|
EMSCRIPTEN_BINDINGS(my_module) {
|
||||||
|
|||||||
@@ -7,7 +7,31 @@ using namespace emscripten;
|
|||||||
|
|
||||||
thread_local const val Uint8Array = val::global("Uint8Array");
|
thread_local const val Uint8Array = val::global("Uint8Array");
|
||||||
|
|
||||||
val encode(std::string image_in, int image_width, int image_height, WP2::EncoderConfig config) {
|
struct WP2Options {
|
||||||
|
float quality;
|
||||||
|
float alpha_quality;
|
||||||
|
int speed;
|
||||||
|
int pass;
|
||||||
|
int uv_mode;
|
||||||
|
float sns;
|
||||||
|
int csp_type;
|
||||||
|
int error_diffusion;
|
||||||
|
bool use_random_matrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
val encode(std::string image_in, int image_width, int image_height, WP2Options options) {
|
||||||
|
WP2::EncoderConfig config = {};
|
||||||
|
|
||||||
|
config.quality = options.quality;
|
||||||
|
config.alpha_quality = options.alpha_quality;
|
||||||
|
config.speed = options.speed;
|
||||||
|
config.pass = options.pass;
|
||||||
|
config.uv_mode = static_cast<WP2::EncoderConfig::UVMode>(options.uv_mode);
|
||||||
|
config.csp_type = static_cast<WP2::Csp>(options.csp_type);
|
||||||
|
config.sns = options.sns;
|
||||||
|
config.error_diffusion = options.error_diffusion;
|
||||||
|
config.use_random_matrix = options.use_random_matrix;
|
||||||
|
|
||||||
uint8_t* image_buffer = (uint8_t*)image_in.c_str();
|
uint8_t* image_buffer = (uint8_t*)image_in.c_str();
|
||||||
WP2::ArgbBuffer src = WP2::ArgbBuffer();
|
WP2::ArgbBuffer src = WP2::ArgbBuffer();
|
||||||
WP2Status status =
|
WP2Status status =
|
||||||
@@ -27,12 +51,16 @@ val encode(std::string image_in, int image_width, int image_height, WP2::Encoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
EMSCRIPTEN_BINDINGS(my_module) {
|
EMSCRIPTEN_BINDINGS(my_module) {
|
||||||
value_object<WP2::EncoderConfig>("WP2EncoderConfig")
|
value_object<WP2Options>("WP2Options")
|
||||||
.field("quality", &WP2::EncoderConfig::quality)
|
.field("quality", &WP2Options::quality)
|
||||||
.field("alpha_quality", &WP2::EncoderConfig::alpha_quality)
|
.field("alpha_quality", &WP2Options::alpha_quality)
|
||||||
.field("speed", &WP2::EncoderConfig::speed)
|
.field("speed", &WP2Options::speed)
|
||||||
.field("pass", &WP2::EncoderConfig::pass)
|
.field("pass", &WP2Options::pass)
|
||||||
.field("sns", &WP2::EncoderConfig::sns);
|
.field("uv_mode", &WP2Options::uv_mode)
|
||||||
|
.field("csp_type", &WP2Options::csp_type)
|
||||||
|
.field("error_diffusion", &WP2Options::error_diffusion)
|
||||||
|
.field("use_random_matrix", &WP2Options::use_random_matrix)
|
||||||
|
.field("sns", &WP2Options::sns);
|
||||||
|
|
||||||
function("encode", &encode);
|
function("encode", &encode);
|
||||||
}
|
}
|
||||||
|
|||||||
18
codecs/wp2/enc/wp2_enc.d.ts
vendored
18
codecs/wp2/enc/wp2_enc.d.ts
vendored
@@ -4,6 +4,24 @@ export interface EncodeOptions {
|
|||||||
speed: number;
|
speed: number;
|
||||||
pass: number;
|
pass: number;
|
||||||
sns: number;
|
sns: number;
|
||||||
|
uv_mode: UVMode;
|
||||||
|
csp_type: Csp;
|
||||||
|
error_diffusion: number;
|
||||||
|
use_random_matrix: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum UVMode {
|
||||||
|
UVModeAdapt = 0, // Mix of 420 and 444 (per block)
|
||||||
|
UVMode420, // All blocks 420
|
||||||
|
UVMode444, // All blocks 444
|
||||||
|
UVModeAuto, // Choose any of the above automatically
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum Csp {
|
||||||
|
kYCoCg,
|
||||||
|
kYCbCr,
|
||||||
|
kCustom,
|
||||||
|
kYIQ,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WP2Module extends EmscriptenWasm.Module {
|
export interface WP2Module extends EmscriptenWasm.Module {
|
||||||
|
|||||||
12
codecs/wp2/enc/wp2_enc.js
generated
12
codecs/wp2/enc/wp2_enc.js
generated
@@ -576,7 +576,7 @@ var wp2_enc = (function () {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
var ob = {
|
var ob = {
|
||||||
p: function (a, b, c, d) {
|
t: function (a, b, c, d) {
|
||||||
A(
|
A(
|
||||||
'Assertion failed: ' +
|
'Assertion failed: ' +
|
||||||
C(a) +
|
C(a) +
|
||||||
@@ -807,7 +807,7 @@ var wp2_enc = (function () {
|
|||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
c: function (a, b, c, d, e) {
|
d: function (a, b, c, d, e) {
|
||||||
function g(l) {
|
function g(l) {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
@@ -1000,10 +1000,10 @@ var wp2_enc = (function () {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
q: function (a, b, c, d, e, g) {
|
p: function (a, b, c, d, e, g) {
|
||||||
Fa[a] = { name: U(b), da: Y(c, d), ea: Y(e, g), U: [] };
|
Fa[a] = { name: U(b), da: Y(c, d), ea: Y(e, g), U: [] };
|
||||||
},
|
},
|
||||||
e: function (a, b, c, d, e, g, m, h, k, l) {
|
c: function (a, b, c, d, e, g, m, h, k, l) {
|
||||||
Fa[a].U.push({
|
Fa[a].U.push({
|
||||||
X: U(b),
|
X: U(b),
|
||||||
aa: c,
|
aa: c,
|
||||||
@@ -1034,7 +1034,7 @@ var wp2_enc = (function () {
|
|||||||
m: function (a) {
|
m: function (a) {
|
||||||
4 < a && (X[a].T += 1);
|
4 < a && (X[a].T += 1);
|
||||||
},
|
},
|
||||||
t: function (a, b, c, d) {
|
q: function (a, b, c, d) {
|
||||||
a || W('Cannot use deleted val. handle = ' + a);
|
a || W('Cannot use deleted val. handle = ' + a);
|
||||||
a = X[a].value;
|
a = X[a].value;
|
||||||
var e = ib[b];
|
var e = ib[b];
|
||||||
@@ -1079,7 +1079,7 @@ var wp2_enc = (function () {
|
|||||||
u: function (a, b, c) {
|
u: function (a, b, c) {
|
||||||
D.copyWithin(a, b, b + c);
|
D.copyWithin(a, b, b + c);
|
||||||
},
|
},
|
||||||
d: function (a) {
|
e: function (a) {
|
||||||
a >>>= 0;
|
a >>>= 0;
|
||||||
var b = D.length;
|
var b = D.length;
|
||||||
if (2147483648 < a) return !1;
|
if (2147483648 < a) return !1;
|
||||||
|
|||||||
Binary file not shown.
@@ -11,6 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import rollup from 'rollup';
|
import rollup from 'rollup';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
const prefix = 'client-bundle:';
|
const prefix = 'client-bundle:';
|
||||||
const entryPathPlaceholder = 'CLIENT_BUNDLE_PLUGIN_ENTRY_PATH';
|
const entryPathPlaceholder = 'CLIENT_BUNDLE_PLUGIN_ENTRY_PATH';
|
||||||
@@ -119,9 +120,10 @@ export default function (inputOptions, outputOptions, resolveFileUrl) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = entryPointPlaceholderMap.get(num);
|
const id = path.normalize(entryPointPlaceholderMap.get(num));
|
||||||
const clientEntry = clientOutput.find(
|
const clientEntry = clientOutput.find(
|
||||||
(item) => item.facadeModuleId === id,
|
(item) =>
|
||||||
|
item.facadeModuleId && path.normalize(item.facadeModuleId) === id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (property.startsWith(entryPathPlaceholder)) {
|
if (property.startsWith(entryPathPlaceholder)) {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ import {
|
|||||||
resolve as resolvePath,
|
resolve as resolvePath,
|
||||||
dirname,
|
dirname,
|
||||||
normalize as nomalizePath,
|
normalize as nomalizePath,
|
||||||
|
sep as pathSep,
|
||||||
|
posix,
|
||||||
} from 'path';
|
} from 'path';
|
||||||
|
|
||||||
import postcss from 'postcss';
|
import postcss from 'postcss';
|
||||||
@@ -172,14 +174,15 @@ export default function (resolveFileUrl) {
|
|||||||
return `export default ${cssStr};`;
|
return `export default ${cssStr};`;
|
||||||
}
|
}
|
||||||
if (id.startsWith(addPrefix)) {
|
if (id.startsWith(addPrefix)) {
|
||||||
const path = id.slice(addPrefix.length);
|
const path = nomalizePath(id.slice(addPrefix.length));
|
||||||
return (
|
return (
|
||||||
`import css from 'css:${path}';\n` +
|
`import css from ${JSON.stringify('css:' + path)};\n` +
|
||||||
`import appendCss from '${appendCssModule}';\n` +
|
`import appendCss from '${appendCssModule}';\n` +
|
||||||
`appendCss(css);\n`
|
`appendCss(css);\n`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (id.endsWith(moduleSuffix)) {
|
if (id.endsWith(moduleSuffix)) {
|
||||||
|
const path = nomalizePath(id.slice(0, -moduleSuffix.length));
|
||||||
if (!pathToResult.has(id)) {
|
if (!pathToResult.has(id)) {
|
||||||
throw Error(`Cannot find ${id} in pathToResult`);
|
throw Error(`Cannot find ${id} in pathToResult`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,16 @@ import glob from 'glob';
|
|||||||
const globP = promisify(glob);
|
const globP = promisify(glob);
|
||||||
|
|
||||||
const moduleId = 'initial-css:';
|
const moduleId = 'initial-css:';
|
||||||
|
const initialCssModule = '\0initialCss';
|
||||||
|
|
||||||
export default function initialCssPlugin() {
|
export default function initialCssPlugin() {
|
||||||
return {
|
return {
|
||||||
name: 'initial-css-plugin',
|
name: 'initial-css-plugin',
|
||||||
resolveId(id) {
|
resolveId(id) {
|
||||||
if (id === moduleId) return moduleId;
|
if (id === moduleId) return initialCssModule;
|
||||||
},
|
},
|
||||||
async load(id) {
|
async load(id) {
|
||||||
if (id !== moduleId) return;
|
if (id !== initialCssModule) return;
|
||||||
|
|
||||||
const matches = await globP('shared/initial-app/**/*.css', {
|
const matches = await globP('shared/initial-app/**/*.css', {
|
||||||
nodir: true,
|
nodir: true,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import { posix as pathUtils } from 'path';
|
import { posix as pathUtils, isAbsolute } from 'path';
|
||||||
|
|
||||||
export default function resolveDirs(paths) {
|
export default function resolveDirs(paths) {
|
||||||
const pathBaseDir = paths.map((path) => [
|
const pathBaseDir = paths.map((path) => [
|
||||||
@@ -30,6 +30,7 @@ export default function resolveDirs(paths) {
|
|||||||
if (!resolveResult) {
|
if (!resolveResult) {
|
||||||
throw new Error(`Couldn't find ${'./' + id}`);
|
throw new Error(`Couldn't find ${'./' + id}`);
|
||||||
}
|
}
|
||||||
|
if (isAbsolute(resolveResult.id)) return resolveResult.id;
|
||||||
return pathUtils.resolve(resolveResult.id);
|
return pathUtils.resolve(resolveResult.id);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -127,15 +127,6 @@ export default function simpleTS(mainPath, { noBuild, watch } = {}) {
|
|||||||
relative(process.cwd(), id),
|
relative(process.cwd(), id),
|
||||||
).replace(extRe, '.js');
|
).replace(extRe, '.js');
|
||||||
|
|
||||||
console.log(
|
|
||||||
`simple-ts mapping`,
|
|
||||||
id,
|
|
||||||
'to',
|
|
||||||
newId,
|
|
||||||
'with outDir',
|
|
||||||
config.options.outDir,
|
|
||||||
);
|
|
||||||
|
|
||||||
return fsp.readFile(newId, { encoding: 'utf8' });
|
return fsp.readFile(newId, { encoding: 'utf8' });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
8538
package-lock.json
generated
8538
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@@ -6,8 +6,9 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c && node lib/move-output.js",
|
"build": "rollup -c && node lib/move-output.js",
|
||||||
"debug": "node --inspect-brk node_modules/.bin/rollup -c",
|
"debug": "node --inspect-brk node_modules/.bin/rollup -c",
|
||||||
"dev": "rollup -cw & npm run serve",
|
"dev": "run-p watch serve",
|
||||||
"serve": "serve --config server.json .tmp/build/static"
|
"watch": "rollup -cw",
|
||||||
|
"serve": "serve --config ../../../serve.json .tmp/build/static"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^15.1.0",
|
"@rollup/plugin-commonjs": "^15.1.0",
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
"lint-staged": "^10.5.1",
|
"lint-staged": "^10.5.1",
|
||||||
"lodash.camelcase": "^4.3.0",
|
"lodash.camelcase": "^4.3.0",
|
||||||
"mime-types": "^2.1.27",
|
"mime-types": "^2.1.27",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
"pointer-tracker": "^2.4.0",
|
"pointer-tracker": "^2.4.0",
|
||||||
"postcss": "^7.0.35",
|
"postcss": "^7.0.35",
|
||||||
"postcss-modules": "^3.2.2",
|
"postcss-modules": "^3.2.2",
|
||||||
@@ -47,9 +49,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*.{js,css,json,md,ts,tsx}": [
|
"*.{js,css,json,md,ts,tsx}": "prettier --write",
|
||||||
"prettier --write"
|
"*.{c,h,cpp,hpp}": "clang-format -i",
|
||||||
]
|
"*.rs": "rustfmt"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"wasm-feature-detect": "^1.2.9"
|
"wasm-feature-detect": "^1.2.9"
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ function jsFileName(chunkInfo) {
|
|||||||
const parsedPath = path.parse(chunkInfo.facadeModuleId);
|
const parsedPath = path.parse(chunkInfo.facadeModuleId);
|
||||||
if (parsedPath.name !== 'index') return jsPath;
|
if (parsedPath.name !== 'index') return jsPath;
|
||||||
// Come up with a better name than 'index'
|
// Come up with a better name than 'index'
|
||||||
const name = parsedPath.dir.split('/').slice(-1);
|
const name = parsedPath.dir.split(/\\|\//).slice(-1);
|
||||||
return jsPath.replace('[name]', name);
|
return jsPath.replace('[name]', name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,5 +9,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"redirects": [{ "source": "/editor", "destination": "/" }]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default class App extends Component<Props, State> {
|
|||||||
// really breaks things on Squoosh, as you can easily end up zooming the UI when you mean to
|
// really breaks things on Squoosh, as you can easily end up zooming the UI when you mean to
|
||||||
// zoom the image. Once you've done this, it's really difficult to undo. Anyway, this seems to
|
// zoom the image. Once you've done this, it's really difficult to undo. Anyway, this seems to
|
||||||
// prevent it.
|
// prevent it.
|
||||||
document.body.addEventListener('gesturestart', (event) => {
|
document.body.addEventListener('gesturestart', (event: any) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -115,11 +115,7 @@ export default class App extends Component<Props, State> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={style.app}>
|
<div class={style.app}>
|
||||||
<file-drop
|
<file-drop onfiledrop={this.onFileDrop} class={style.drop}>
|
||||||
accept="image/*"
|
|
||||||
onfiledrop={this.onFileDrop}
|
|
||||||
class={style.drop}
|
|
||||||
>
|
|
||||||
{showSpinner ? (
|
{showSpinner ? (
|
||||||
<loading-spinner class={style.appLoader} />
|
<loading-spinner class={style.appLoader} />
|
||||||
) : isEditorOpen ? (
|
) : isEditorOpen ? (
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'add-css:./style.css';
|
|||||||
import { cleanSet, cleanMerge } from '../../util/clean-modify';
|
import { cleanSet, cleanMerge } from '../../util/clean-modify';
|
||||||
|
|
||||||
import type { SourceImage, OutputType } from '..';
|
import type { SourceImage, OutputType } from '..';
|
||||||
|
import type SnackBarElement from 'shared/initial-app/custom-els/snack-bar';
|
||||||
import {
|
import {
|
||||||
EncoderOptions,
|
EncoderOptions,
|
||||||
EncoderState,
|
EncoderState,
|
||||||
@@ -18,7 +19,10 @@ import Select from './Select';
|
|||||||
import { Options as QuantOptionsComponent } from 'features/processors/quantize/client';
|
import { Options as QuantOptionsComponent } from 'features/processors/quantize/client';
|
||||||
import { Options as ResizeOptionsComponent } from 'features/processors/resize/client';
|
import { Options as ResizeOptionsComponent } from 'features/processors/resize/client';
|
||||||
|
|
||||||
|
import { generateCliInvocation } from '../../util/cli-invocation-generator';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
showSnack: SnackBarElement['showSnackbar'];
|
||||||
mobileView: boolean;
|
mobileView: boolean;
|
||||||
source?: SourceImage;
|
source?: SourceImage;
|
||||||
encoderState?: EncoderState;
|
encoderState?: EncoderState;
|
||||||
@@ -97,6 +101,22 @@ export default class Options extends Component<Props, State> {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onCreateCLIInvocation = () => {
|
||||||
|
if (!this.props.encoderState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cliInvocation = generateCliInvocation(
|
||||||
|
this.props.encoderState,
|
||||||
|
this.props.processorState,
|
||||||
|
);
|
||||||
|
navigator.clipboard.writeText(cliInvocation);
|
||||||
|
} catch (e) {
|
||||||
|
this.props.showSnack(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render(
|
render(
|
||||||
{ source, encoderState, processorState, onEncoderOptionsChange }: Props,
|
{ source, encoderState, processorState, onEncoderOptionsChange }: Props,
|
||||||
{ supportedEncoderMap }: State,
|
{ supportedEncoderMap }: State,
|
||||||
@@ -110,7 +130,9 @@ export default class Options extends Component<Props, State> {
|
|||||||
<Expander>
|
<Expander>
|
||||||
{!encoderState ? null : (
|
{!encoderState ? null : (
|
||||||
<div>
|
<div>
|
||||||
<h3 class={style.optionsTitle}>Edit</h3>
|
<h3 class={style.optionsTitle}>
|
||||||
|
<button onClick={this.onCreateCLIInvocation}>CLI</button>Edit
|
||||||
|
</h3>
|
||||||
<label class={style.sectionEnabler}>
|
<label class={style.sectionEnabler}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
name="resize.enable"
|
name="resize.enable"
|
||||||
|
|||||||
@@ -649,6 +649,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name === 'AbortError') return;
|
if (err.name === 'AbortError') return;
|
||||||
|
this.setState({ loading: false });
|
||||||
this.props.showSnack(`Preprocessing error: ${err}`);
|
this.props.showSnack(`Preprocessing error: ${err}`);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@@ -772,6 +773,12 @@ export default class Compress extends Component<Props, State> {
|
|||||||
this.activeSideJobs[sideIndex] = undefined;
|
this.activeSideJobs[sideIndex] = undefined;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name === 'AbortError') return;
|
if (err.name === 'AbortError') return;
|
||||||
|
this.setState((currentState) => {
|
||||||
|
const sides = cleanMerge(currentState.sides, sideIndex, {
|
||||||
|
loading: false,
|
||||||
|
});
|
||||||
|
return { sides };
|
||||||
|
});
|
||||||
this.props.showSnack(`Processing error: ${err}`);
|
this.props.showSnack(`Processing error: ${err}`);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@@ -779,7 +786,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(
|
render(
|
||||||
{ onBack }: Props,
|
{ onBack, showSnack }: Props,
|
||||||
{ loading, sides, source, mobileView, preprocessorState }: State,
|
{ loading, sides, source, mobileView, preprocessorState }: State,
|
||||||
) {
|
) {
|
||||||
const [leftSide, rightSide] = sides;
|
const [leftSide, rightSide] = sides;
|
||||||
@@ -787,6 +794,7 @@ export default class Compress extends Component<Props, State> {
|
|||||||
|
|
||||||
const options = sides.map((side, index) => (
|
const options = sides.map((side, index) => (
|
||||||
<Options
|
<Options
|
||||||
|
showSnack={showSnack}
|
||||||
source={source}
|
source={source}
|
||||||
mobileView={mobileView}
|
mobileView={mobileView}
|
||||||
processorState={side.latestSettings.processorState}
|
processorState={side.latestSettings.processorState}
|
||||||
|
|||||||
51
src/client/lazy-app/util/cli-invocation-generator.ts
Normal file
51
src/client/lazy-app/util/cli-invocation-generator.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* 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 { EncoderState, ProcessorState } from '../feature-meta';
|
||||||
|
|
||||||
|
// Maps our encoder.type values to CLI parameter names
|
||||||
|
const typeMap = new Map<string, string>([
|
||||||
|
['avif', '--avif'],
|
||||||
|
["jxl", "--jxl"],
|
||||||
|
['mozJPEG', '--mozjpeg'],
|
||||||
|
['oxiPNG', '--oxipng'],
|
||||||
|
['webP', '--webp'],
|
||||||
|
["wp2", "--wp2"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Same as JSON.stringify, but with single quotes around the entire value
|
||||||
|
// so that shells don’t do weird stuff.
|
||||||
|
function cliJson<T>(v: T): string {
|
||||||
|
return "'" + JSON.stringify(v) + "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateCliInvocation(
|
||||||
|
encoder: EncoderState,
|
||||||
|
processor: ProcessorState,
|
||||||
|
): string {
|
||||||
|
if (!typeMap.has(encoder.type)) {
|
||||||
|
throw Error(`Encoder ${encoder.type} is unsupported in the CLI`);
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
'npx',
|
||||||
|
'@squoosh/cli',
|
||||||
|
...(processor.resize.enabled
|
||||||
|
? ['--resize', cliJson(processor.resize)]
|
||||||
|
: []),
|
||||||
|
...(processor.quantize.enabled
|
||||||
|
? ['--quant', cliJson(processor.quantize)]
|
||||||
|
: []),
|
||||||
|
typeMap.get(encoder.type)!,
|
||||||
|
cliJson(encoder.options),
|
||||||
|
].join(' ');
|
||||||
|
}
|
||||||
@@ -315,9 +315,9 @@ export class Options extends Component<Props, State> {
|
|||||||
value={subsample}
|
value={subsample}
|
||||||
onChange={this._inputChange('subsample', 'number')}
|
onChange={this._inputChange('subsample', 'number')}
|
||||||
>
|
>
|
||||||
<option value="1">4:2:0</option>
|
<option value="1">Half</option>
|
||||||
{/*<option value="2">4:2:2</option>*/}
|
{/*<option value="2">4:2:2</option>*/}
|
||||||
<option value="3">4:4:4</option>
|
<option value="3">Off</option>
|
||||||
</Select>
|
</Select>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ interface State {
|
|||||||
edgePreservingFilter: number;
|
edgePreservingFilter: number;
|
||||||
lossless: boolean;
|
lossless: boolean;
|
||||||
slightLoss: boolean;
|
slightLoss: boolean;
|
||||||
|
autoEdgePreservingFilter: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxSpeed = 7;
|
const maxSpeed = 7;
|
||||||
@@ -48,9 +49,10 @@ export class Options extends Component<Props, State> {
|
|||||||
effort: maxSpeed - options.speed,
|
effort: maxSpeed - options.speed,
|
||||||
quality: options.quality,
|
quality: options.quality,
|
||||||
progressive: options.progressive,
|
progressive: options.progressive,
|
||||||
edgePreservingFilter: options.epf,
|
edgePreservingFilter: options.epf === -1 ? 2 : options.epf,
|
||||||
lossless: options.quality === 100,
|
lossless: options.quality === 100,
|
||||||
slightLoss: options.lossyPalette,
|
slightLoss: options.lossyPalette,
|
||||||
|
autoEdgePreservingFilter: options.epf === -1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +88,9 @@ export class Options extends Component<Props, State> {
|
|||||||
speed: maxSpeed - optionState.effort,
|
speed: maxSpeed - optionState.effort,
|
||||||
quality: optionState.lossless ? 100 : optionState.quality,
|
quality: optionState.lossless ? 100 : optionState.quality,
|
||||||
progressive: optionState.progressive,
|
progressive: optionState.progressive,
|
||||||
epf: optionState.edgePreservingFilter,
|
epf: optionState.autoEdgePreservingFilter
|
||||||
|
? -1
|
||||||
|
: optionState.edgePreservingFilter,
|
||||||
nearLossless: 0,
|
nearLossless: 0,
|
||||||
lossyPalette: optionState.lossless ? optionState.slightLoss : false,
|
lossyPalette: optionState.lossless ? optionState.slightLoss : false,
|
||||||
};
|
};
|
||||||
@@ -112,6 +116,7 @@ export class Options extends Component<Props, State> {
|
|||||||
edgePreservingFilter,
|
edgePreservingFilter,
|
||||||
lossless,
|
lossless,
|
||||||
slightLoss,
|
slightLoss,
|
||||||
|
autoEdgePreservingFilter,
|
||||||
}: State,
|
}: State,
|
||||||
) {
|
) {
|
||||||
// I'm rendering both lossy and lossless forms, as it becomes much easier when
|
// I'm rendering both lossy and lossless forms, as it becomes much easier when
|
||||||
@@ -152,16 +157,34 @@ export class Options extends Component<Props, State> {
|
|||||||
Quality:
|
Quality:
|
||||||
</Range>
|
</Range>
|
||||||
</div>
|
</div>
|
||||||
<div class={style.optionOneCell}>
|
<label class={style.optionInputFirst}>
|
||||||
<Range
|
<Checkbox
|
||||||
min="0"
|
name="autoEdgeFilter"
|
||||||
max="3"
|
checked={autoEdgePreservingFilter}
|
||||||
value={edgePreservingFilter}
|
onChange={this._inputChange(
|
||||||
onInput={this._inputChange('edgePreservingFilter', 'number')}
|
'autoEdgePreservingFilter',
|
||||||
>
|
'boolean',
|
||||||
Edge preserving filter:
|
)}
|
||||||
</Range>
|
/>
|
||||||
</div>
|
Auto edge filter
|
||||||
|
</label>
|
||||||
|
<Expander>
|
||||||
|
{!autoEdgePreservingFilter && (
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="0"
|
||||||
|
max="3"
|
||||||
|
value={edgePreservingFilter}
|
||||||
|
onInput={this._inputChange(
|
||||||
|
'edgePreservingFilter',
|
||||||
|
'number',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
Edge preserving filter:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Expander>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Expander>
|
</Expander>
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ export const label = 'JPEG XL (beta)';
|
|||||||
export const mimeType = 'image/jpegxl';
|
export const mimeType = 'image/jpegxl';
|
||||||
export const extension = 'jxl';
|
export const extension = 'jxl';
|
||||||
export const defaultOptions: EncodeOptions = {
|
export const defaultOptions: EncodeOptions = {
|
||||||
speed: 5,
|
speed: 4,
|
||||||
quality: 50,
|
quality: 75,
|
||||||
progressive: false,
|
progressive: false,
|
||||||
epf: 2,
|
epf: -1,
|
||||||
nearLossless: 0,
|
nearLossless: 0,
|
||||||
lossyPalette: false,
|
lossyPalette: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
import { EncodeOptions } from '../shared/meta';
|
import { EncodeOptions, UVMode, Csp } from '../shared/meta';
|
||||||
|
import { defaultOptions } from '../shared/meta';
|
||||||
import type WorkerBridge from 'client/lazy-app/worker-bridge';
|
import type WorkerBridge from 'client/lazy-app/worker-bridge';
|
||||||
import { h, Component } from 'preact';
|
import { h, Component } from 'preact';
|
||||||
import { inputFieldValueAsNumber, preventDefault } from 'client/lazy-app/util';
|
import { preventDefault, shallowEqual } from 'client/lazy-app/util';
|
||||||
import * as style from 'client/lazy-app/Compress/Options/style.css';
|
import * as style from 'client/lazy-app/Compress/Options/style.css';
|
||||||
import Range from 'client/lazy-app/Compress/Options/Range';
|
import Range from 'client/lazy-app/Compress/Options/Range';
|
||||||
|
import Select from 'client/lazy-app/Compress/Options/Select';
|
||||||
|
import Checkbox from 'client/lazy-app/Compress/Options/Checkbox';
|
||||||
|
import Expander from 'client/lazy-app/Compress/Options/Expander';
|
||||||
|
import linkState from 'linkstate';
|
||||||
|
|
||||||
export const encode = (
|
export const encode = (
|
||||||
signal: AbortSignal,
|
signal: AbortSignal,
|
||||||
@@ -18,93 +23,286 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
options: EncodeOptions;
|
||||||
|
effort: number;
|
||||||
|
quality: number;
|
||||||
|
alphaQuality: number;
|
||||||
|
passes: number;
|
||||||
|
sns: number;
|
||||||
|
uvMode: number;
|
||||||
|
lossless: boolean;
|
||||||
|
slightLoss: number;
|
||||||
|
colorSpace: number;
|
||||||
|
errorDiffusion: number;
|
||||||
|
useRandomMatrix: boolean;
|
||||||
showAdvanced: boolean;
|
showAdvanced: boolean;
|
||||||
|
separateAlpha: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Options extends Component<Props, State> {
|
export class Options extends Component<Props, State> {
|
||||||
state: State = {
|
static getDerivedStateFromProps(
|
||||||
showAdvanced: false,
|
props: Props,
|
||||||
};
|
state: State,
|
||||||
|
): Partial<State> | null {
|
||||||
|
if (state.options && shallowEqual(state.options, props.options)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private onChange = (event: Event) => {
|
const { options } = props;
|
||||||
const form = (event.currentTarget as HTMLInputElement).closest(
|
|
||||||
'form',
|
const modifyState: Partial<State> = {
|
||||||
) as HTMLFormElement;
|
options,
|
||||||
const { options } = this.props;
|
effort: options.speed,
|
||||||
const newOptions: EncodeOptions = {
|
alphaQuality: options.alpha_quality,
|
||||||
quality: inputFieldValueAsNumber(form.quality, options.quality),
|
passes: options.pass,
|
||||||
alpha_quality: inputFieldValueAsNumber(
|
sns: options.sns,
|
||||||
form.alpha_quality,
|
uvMode: options.uv_mode,
|
||||||
options.alpha_quality,
|
colorSpace: options.csp_type,
|
||||||
),
|
errorDiffusion: options.error_diffusion,
|
||||||
speed: inputFieldValueAsNumber(form.speed, options.speed),
|
useRandomMatrix: options.use_random_matrix,
|
||||||
pass: inputFieldValueAsNumber(form.pass, options.pass),
|
separateAlpha: options.quality !== options.alpha_quality,
|
||||||
sns: inputFieldValueAsNumber(form.sns, options.sns),
|
|
||||||
};
|
};
|
||||||
this.props.onChange(newOptions);
|
|
||||||
|
// If quality is > 95, it's lossless with slight loss
|
||||||
|
if (options.quality > 95) {
|
||||||
|
modifyState.lossless = true;
|
||||||
|
modifyState.slightLoss = 100 - options.quality;
|
||||||
|
} else {
|
||||||
|
modifyState.quality = options.quality;
|
||||||
|
modifyState.lossless = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return modifyState;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other state is set in getDerivedStateFromProps
|
||||||
|
state: State = {
|
||||||
|
lossless: false,
|
||||||
|
slightLoss: 0,
|
||||||
|
quality: defaultOptions.quality,
|
||||||
|
showAdvanced: false,
|
||||||
|
} as State;
|
||||||
|
|
||||||
|
private _inputChangeCallbacks = new Map<string, (event: Event) => void>();
|
||||||
|
|
||||||
|
private _inputChange = (prop: keyof State, type: 'number' | 'boolean') => {
|
||||||
|
// Cache the callback for performance
|
||||||
|
if (!this._inputChangeCallbacks.has(prop)) {
|
||||||
|
this._inputChangeCallbacks.set(prop, (event: Event) => {
|
||||||
|
const formEl = event.target as HTMLInputElement | HTMLSelectElement;
|
||||||
|
const newVal =
|
||||||
|
type === 'boolean'
|
||||||
|
? 'checked' in formEl
|
||||||
|
? formEl.checked
|
||||||
|
: !!formEl.value
|
||||||
|
: Number(formEl.value);
|
||||||
|
|
||||||
|
const newState: Partial<State> = {
|
||||||
|
[prop]: newVal,
|
||||||
|
};
|
||||||
|
|
||||||
|
const optionState = {
|
||||||
|
...this.state,
|
||||||
|
...newState,
|
||||||
|
};
|
||||||
|
|
||||||
|
const newOptions: EncodeOptions = {
|
||||||
|
speed: optionState.effort,
|
||||||
|
quality: optionState.lossless
|
||||||
|
? 100 - optionState.slightLoss
|
||||||
|
: optionState.quality,
|
||||||
|
alpha_quality: optionState.separateAlpha
|
||||||
|
? optionState.alphaQuality
|
||||||
|
: optionState.quality,
|
||||||
|
pass: optionState.passes,
|
||||||
|
sns: optionState.sns,
|
||||||
|
uv_mode: optionState.uvMode,
|
||||||
|
csp_type: optionState.colorSpace,
|
||||||
|
error_diffusion: optionState.errorDiffusion,
|
||||||
|
use_random_matrix: optionState.useRandomMatrix,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Updating options, so we don't recalculate in getDerivedStateFromProps.
|
||||||
|
newState.options = newOptions;
|
||||||
|
|
||||||
|
this.setState(newState);
|
||||||
|
|
||||||
|
this.props.onChange(newOptions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._inputChangeCallbacks.get(prop)!;
|
||||||
};
|
};
|
||||||
|
|
||||||
render({ options }: Props) {
|
render(
|
||||||
|
{}: Props,
|
||||||
|
{
|
||||||
|
effort,
|
||||||
|
alphaQuality,
|
||||||
|
passes,
|
||||||
|
quality,
|
||||||
|
sns,
|
||||||
|
uvMode,
|
||||||
|
lossless,
|
||||||
|
slightLoss,
|
||||||
|
colorSpace,
|
||||||
|
errorDiffusion,
|
||||||
|
useRandomMatrix,
|
||||||
|
separateAlpha,
|
||||||
|
showAdvanced,
|
||||||
|
}: State,
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<form class={style.optionsSection} onSubmit={preventDefault}>
|
<form class={style.optionsSection} onSubmit={preventDefault}>
|
||||||
|
<label class={style.optionInputFirst}>
|
||||||
|
<Checkbox
|
||||||
|
checked={lossless}
|
||||||
|
onChange={this._inputChange('lossless', 'boolean')}
|
||||||
|
/>
|
||||||
|
Lossless
|
||||||
|
</label>
|
||||||
|
<Expander>
|
||||||
|
{lossless && (
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="0"
|
||||||
|
max="5"
|
||||||
|
step="0.1"
|
||||||
|
value={slightLoss}
|
||||||
|
onInput={this._inputChange('slightLoss', 'number')}
|
||||||
|
>
|
||||||
|
Slight loss:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Expander>
|
||||||
|
<Expander>
|
||||||
|
{!lossless && (
|
||||||
|
<div>
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="0"
|
||||||
|
max="95"
|
||||||
|
step="0.1"
|
||||||
|
value={quality}
|
||||||
|
onInput={this._inputChange('quality', 'number')}
|
||||||
|
>
|
||||||
|
Quality:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
<label class={style.optionInputFirst}>
|
||||||
|
<Checkbox
|
||||||
|
checked={separateAlpha}
|
||||||
|
onChange={this._inputChange('separateAlpha', 'boolean')}
|
||||||
|
/>
|
||||||
|
Separate alpha quality
|
||||||
|
</label>
|
||||||
|
<Expander>
|
||||||
|
{separateAlpha && (
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
step="1"
|
||||||
|
value={alphaQuality}
|
||||||
|
onInput={this._inputChange('alphaQuality', 'number')}
|
||||||
|
>
|
||||||
|
Alpha Quality:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Expander>
|
||||||
|
<label class={style.optionInputFirst}>
|
||||||
|
<Checkbox
|
||||||
|
checked={showAdvanced}
|
||||||
|
onChange={linkState(this, 'showAdvanced')}
|
||||||
|
/>
|
||||||
|
Show advanced settings
|
||||||
|
</label>
|
||||||
|
<Expander>
|
||||||
|
{showAdvanced && (
|
||||||
|
<div>
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="1"
|
||||||
|
max="10"
|
||||||
|
step="1"
|
||||||
|
value={passes}
|
||||||
|
onInput={this._inputChange('passes', 'number')}
|
||||||
|
>
|
||||||
|
Passes:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
step="1"
|
||||||
|
value={sns}
|
||||||
|
onInput={this._inputChange('sns', 'number')}
|
||||||
|
>
|
||||||
|
Spatial noise shaping:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
<div class={style.optionOneCell}>
|
||||||
|
<Range
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
step="1"
|
||||||
|
value={errorDiffusion}
|
||||||
|
onInput={this._inputChange('errorDiffusion', 'number')}
|
||||||
|
>
|
||||||
|
Error diffusion:
|
||||||
|
</Range>
|
||||||
|
</div>
|
||||||
|
<label class={style.optionTextFirst}>
|
||||||
|
Subsample chroma:
|
||||||
|
<Select
|
||||||
|
value={uvMode}
|
||||||
|
onInput={this._inputChange('uvMode', 'number')}
|
||||||
|
>
|
||||||
|
<option value={UVMode.UVModeAuto}>Auto</option>
|
||||||
|
<option value={UVMode.UVModeAdapt}>Vary</option>
|
||||||
|
<option value={UVMode.UVMode420}>Half</option>
|
||||||
|
<option value={UVMode.UVMode444}>Off</option>
|
||||||
|
</Select>
|
||||||
|
</label>
|
||||||
|
<label class={style.optionTextFirst}>
|
||||||
|
Color space:
|
||||||
|
<Select
|
||||||
|
value={colorSpace}
|
||||||
|
onInput={this._inputChange('colorSpace', 'number')}
|
||||||
|
>
|
||||||
|
<option value={Csp.kYCoCg}>YCoCg</option>
|
||||||
|
<option value={Csp.kYCbCr}>YCbCr</option>
|
||||||
|
<option value={Csp.kYIQ}>YIQ</option>
|
||||||
|
</Select>
|
||||||
|
</label>
|
||||||
|
<label class={style.optionInputFirst}>
|
||||||
|
<Checkbox
|
||||||
|
checked={useRandomMatrix}
|
||||||
|
onChange={this._inputChange(
|
||||||
|
'useRandomMatrix',
|
||||||
|
'boolean',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
Random matrix
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Expander>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Expander>
|
||||||
<div class={style.optionOneCell}>
|
<div class={style.optionOneCell}>
|
||||||
<Range
|
<Range
|
||||||
name="quality"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
step="1"
|
|
||||||
value={options.quality}
|
|
||||||
onInput={this.onChange}
|
|
||||||
>
|
|
||||||
Quality:
|
|
||||||
</Range>
|
|
||||||
</div>
|
|
||||||
<div class={style.optionOneCell}>
|
|
||||||
<Range
|
|
||||||
name="alpha_quality"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
step="1"
|
|
||||||
value={options.alpha_quality}
|
|
||||||
onInput={this.onChange}
|
|
||||||
>
|
|
||||||
Alpha Quality:
|
|
||||||
</Range>
|
|
||||||
</div>
|
|
||||||
<div class={style.optionOneCell}>
|
|
||||||
<Range
|
|
||||||
name="speed"
|
|
||||||
min="0"
|
min="0"
|
||||||
max="9"
|
max="9"
|
||||||
step="1"
|
step="1"
|
||||||
value={options.speed}
|
value={effort}
|
||||||
onInput={this.onChange}
|
onInput={this._inputChange('effort', 'number')}
|
||||||
>
|
>
|
||||||
Speed:
|
Effort:
|
||||||
</Range>
|
|
||||||
</div>
|
|
||||||
<div class={style.optionOneCell}>
|
|
||||||
<Range
|
|
||||||
name="pass"
|
|
||||||
min="1"
|
|
||||||
max="10"
|
|
||||||
step="1"
|
|
||||||
value={options.pass}
|
|
||||||
onInput={this.onChange}
|
|
||||||
>
|
|
||||||
Pass:
|
|
||||||
</Range>
|
|
||||||
</div>
|
|
||||||
<div class={style.optionOneCell}>
|
|
||||||
<Range
|
|
||||||
name="sns"
|
|
||||||
min="0"
|
|
||||||
max="100"
|
|
||||||
step="1"
|
|
||||||
value={options.sns}
|
|
||||||
onInput={this.onChange}
|
|
||||||
>
|
|
||||||
Spatial noise shaping:
|
|
||||||
</Range>
|
</Range>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -11,16 +11,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import type { EncodeOptions } from 'codecs/wp2/enc/wp2_enc';
|
import type { EncodeOptions } from 'codecs/wp2/enc/wp2_enc';
|
||||||
|
import { UVMode, Csp } from 'codecs/wp2/enc/wp2_enc';
|
||||||
|
|
||||||
export { EncodeOptions };
|
export { EncodeOptions, UVMode, Csp };
|
||||||
|
|
||||||
export const label = 'WebP v2 (unstable)';
|
export const label = 'WebP v2 (unstable)';
|
||||||
export const mimeType = 'image/webp2';
|
export const mimeType = 'image/webp2';
|
||||||
export const extension = 'wp2';
|
export const extension = 'wp2';
|
||||||
export const defaultOptions: EncodeOptions = {
|
export const defaultOptions: EncodeOptions = {
|
||||||
quality: 75,
|
quality: 75,
|
||||||
alpha_quality: 100,
|
alpha_quality: 75,
|
||||||
speed: 5,
|
speed: 5,
|
||||||
pass: 1,
|
pass: 1,
|
||||||
sns: 50,
|
sns: 50,
|
||||||
|
uv_mode: UVMode.UVModeAuto,
|
||||||
|
csp_type: Csp.kYCoCg,
|
||||||
|
error_diffusion: 0,
|
||||||
|
use_random_matrix: false,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user