Compare commits

..

6 Commits

Author SHA1 Message Date
416e865adf Strip via wasm-opt 2021-05-04 19:05:33 +01:00
aa0ba8509e REmove reactor 2021-05-04 18:53:56 +01:00
6820412ffd Make it smaller 2021-05-04 18:52:26 +01:00
be3688c8d3 Integrate WASI module with Squoosh UI 2021-05-04 13:00:33 +01:00
deee258820 Add setter functions 2021-05-04 12:38:22 +01:00
f5c9d6a209 Make it build with WASI SDK 2021-05-04 12:06:25 +01:00
92 changed files with 2964 additions and 3781 deletions

View File

@ -3,9 +3,9 @@
[Squoosh] is an image compression web app that allows you to dive into the advanced options provided
by various image compressors.
# API & CLI
# CLI
Squoosh now has [an API](https://github.com/GoogleChromeLabs/squoosh/tree/dev/libsquoosh) and [a CLI](https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli) that allows you to compress many images at once.
[Squoosh now has a CLI](https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli) that allows you to compress many images at once.
# Privacy

View File

@ -55,5 +55,5 @@ $ npx @squoosh/cli --wp2 auto test.png
```
[squoosh]: https://squoosh.app
[codecs.js]: https://github.com/GoogleChromeLabs/squoosh/blob/dev/libsquoosh/src/codecs.js
[codecs.js]: https://github.com/GoogleChromeLabs/squoosh/blob/dev/cli/src/codecs.js
[butteraugli]: https://github.com/google/butteraugli

View File

@ -10,11 +10,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { promises as fs } from 'fs';
import { basename } from 'path';
import { promises as fs } from "fs";
import { basename } from "path";
const defaultOpts = {
prefix: 'asset-url',
prefix: "asset-url"
};
export default function assetPlugin(opts) {
@ -23,16 +23,16 @@ export default function assetPlugin(opts) {
/** @type {Map<string, Buffer>} */
let assetIdToSourceBuffer;
const prefix = opts.prefix + ':';
const prefix = opts.prefix + ":";
return {
name: 'asset-plugin',
name: "asset-plugin",
buildStart() {
assetIdToSourceBuffer = new Map();
},
augmentChunkHash(info) {
// Get the sources for all assets imported by this chunk.
const buffers = Object.keys(info.modules)
.map((moduleId) => assetIdToSourceBuffer.get(moduleId))
.map(moduleId => assetIdToSourceBuffer.get(moduleId))
.filter(Boolean);
if (buffers.length === 0) return;
@ -56,20 +56,20 @@ export default function assetPlugin(opts) {
throw Error(`Cannot find ${realId}`);
}
// Add an additional .js to the end so it ends up with .js at the end in the _virtual folder.
return prefix + resolveResult.id + '.js';
return prefix + resolveResult.id + ".js";
},
async load(id) {
if (!id.startsWith(prefix)) return;
const realId = id.slice(prefix.length, -'.js'.length);
const realId = id.slice(prefix.length, -".js".length);
const source = await fs.readFile(realId);
assetIdToSourceBuffer.set(id, source);
this.addWatchFile(realId);
return `export default import.meta.ROLLUP_FILE_URL_${this.emitFile({
type: 'asset',
type: "asset",
source,
name: basename(realId),
name: basename(realId)
})}`;
},
}
};
}

View File

@ -5,8 +5,8 @@ export default function autojsonPlugin() {
name: 'autojson-plugin',
async load(id) {
if (id.endsWith('.json') && !id.startsWith('json:')) {
return 'export default ' + (await fsp.readFile(id, 'utf8'));
return 'export default ' + await fsp.readFile(id, 'utf8');
}
},
}
};
}
};

2461
cli/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,32 @@
{
"name": "@squoosh/cli",
"version": "0.7.0",
"version": "0.6.0",
"description": "A CLI for Squoosh",
"public": true,
"type": "module",
"bin": {
"squoosh-cli": "src/index.js",
"@squoosh/cli": "src/index.js"
"squoosh-cli": "build/index.js",
"@squoosh/cli": "build/index.js"
},
"scripts": {
"build": "rollup -c"
},
"files": [
"/src/index.js"
],
"keywords": [],
"author": "Google Chrome Developers <chromium-dev@google.com>",
"license": "Apache-2.0",
"dependencies": {
"@squoosh/lib": "^0.2.0",
"commander": "^7.2.0",
"json5": "^2.2.0",
"kleur": "^4.1.4",
"ora": "^5.4.0"
"web-streams-polyfill": "^3.0.0"
},
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/preset-env": "^7.11.5",
"@rollup/plugin-babel": "^5.2.1",
"@rollup/plugin-commonjs": "^15.0.0",
"@rollup/plugin-node-resolve": "^9.0.0",
"commander": "^6.0.0",
"json5": "^2.1.3",
"kleur": "^4.1.3",
"ora": "^5.1.0",
"rollup": "^2.26.11",
"rollup-plugin-terser": "^7.0.2"
}
}

View File

@ -13,6 +13,9 @@ export default {
dir: 'build',
format: 'cjs',
assetFileNames: '[name]-[hash][extname]',
// This is needed so the resulting `index.js` can be
// executed by `npx`.
banner: '#!/usr/bin/env node',
},
plugins: [
resolve(),
@ -24,7 +27,7 @@ export default {
babelrc: false,
configFile: false,
minified: process.env.DEBUG != '',
comments: true,
comments: false,
presets: [
[
'@babel/preset-env',
@ -38,5 +41,5 @@ export default {
],
}),
],
external: [...builtinModules, 'web-streams-polyfill'],
external: builtinModules,
};

View File

@ -1,7 +1,7 @@
import { instantiateEmscriptenWasm } from './emscripten-utils.js';
import { instantiateEmscriptenWasm } from "./emscripten-utils.js";
import visdif from '../../codecs/visdif/visdif.js';
import visdifWasm from 'asset-url:../../codecs/visdif/visdif.wasm';
import visdif from "../../codecs/visdif/visdif.js";
import visdifWasm from "asset-url:../../codecs/visdif/visdif.wasm";
// `measure` is a (async) function that takes exactly one numeric parameter and
// returns a value. The function is assumed to be monotonic (an increase in `parameter`
@ -11,7 +11,7 @@ import visdifWasm from 'asset-url:../../codecs/visdif/visdif.wasm';
export async function binarySearch(
measureGoal,
measure,
{ min = 0, max = 100, epsilon = 0.1, maxRounds = 8 } = {},
{ min = 0, max = 100, epsilon = 0.1, maxRounds = 8 } = {}
) {
let parameter = (max - min) / 2 + min;
let delta = (max - min) / 4;
@ -36,14 +36,14 @@ export async function autoOptimize(
bitmapIn,
encode,
decode,
{ butteraugliDistanceGoal = 1.4, ...otherOpts } = {},
{ butteraugliDistanceGoal = 1.4, ...otherOpts } = {}
) {
const { VisDiff } = await instantiateEmscriptenWasm(visdif, visdifWasm);
const comparator = new VisDiff(
bitmapIn.data,
bitmapIn.width,
bitmapIn.height,
bitmapIn.height
);
let bitmapOut;
@ -53,18 +53,18 @@ export async function autoOptimize(
// increase the metric value. So multipliy Butteraugli values by -1.
const { parameter } = await binarySearch(
-1 * butteraugliDistanceGoal,
async (quality) => {
async quality => {
binaryOut = await encode(bitmapIn, quality);
bitmapOut = await decode(binaryOut);
return -1 * comparator.distance(bitmapOut.data);
},
otherOpts,
otherOpts
);
comparator.delete();
return {
bitmap: bitmapOut,
binary: binaryOut,
quality: parameter,
quality: parameter
};
}

View File

@ -344,11 +344,7 @@ export const codecs = {
await oxipngPromise;
return {
encode: (buffer, width, height, opts) => {
const simplePng = pngEncDec.encode(
new Uint8Array(buffer),
width,
height,
);
const simplePng = pngEncDec.encode(new Uint8Array(buffer), width, height);
return oxipng.optimise(simplePng, opts.level);
},
};

326
cli/src/index.js Executable file → Normal file
View File

@ -1,13 +1,17 @@
#!/usr/bin/env node
import { program } from 'commander/esm.mjs';
import { program } from 'commander';
import JSON5 from 'json5';
import path from 'path';
import { isMainThread } from 'worker_threads';
import { cpus } from 'os';
import { extname, join, basename } from 'path';
import { promises as fsp } from 'fs';
import { resolve as resolvePath } from 'path';
import { version } from 'json:../package.json';
import ora from 'ora';
import kleur from 'kleur';
import { ImagePool, preprocessors, encoders } from '@squoosh/lib';
import { codecs as supportedFormats, preprocessors } from './codecs.js';
import WorkerPool from './worker_pool.js';
import { autoOptimize } from './auto-optimizer.js';
function clamp(v, min, max) {
if (v < min) return min;
@ -22,6 +26,114 @@ function prettyPrintSize(size) {
return (size / 2 ** (10 * index)).toFixed(2) + suffix[index];
}
async function decodeFile(file) {
const buffer = await fsp.readFile(file);
const firstChunk = buffer.slice(0, 16);
const firstChunkString = Array.from(firstChunk)
.map((v) => String.fromCodePoint(v))
.join('');
const key = Object.entries(supportedFormats).find(([name, { detectors }]) =>
detectors.some((detector) => detector.exec(firstChunkString)),
)?.[0];
if (!key) {
throw Error(`${file} has an unsupported format`);
}
const rgba = (await supportedFormats[key].dec()).decode(
new Uint8Array(buffer),
);
return {
file,
bitmap: rgba,
size: buffer.length,
};
}
async function preprocessImage({ preprocessorName, options, file }) {
const preprocessor = await preprocessors[preprocessorName].instantiate();
file.bitmap = await preprocessor(
file.bitmap.data,
file.bitmap.width,
file.bitmap.height,
options,
);
return file;
}
async function encodeFile({
file,
size,
bitmap: bitmapIn,
outputFile,
encName,
encConfig,
optimizerButteraugliTarget,
maxOptimizerRounds,
}) {
let out, infoText;
const encoder = await supportedFormats[encName].enc();
if (encConfig === 'auto') {
const optionToOptimize = supportedFormats[encName].autoOptimize.option;
const decoder = await supportedFormats[encName].dec();
const encode = (bitmapIn, quality) =>
encoder.encode(
bitmapIn.data,
bitmapIn.width,
bitmapIn.height,
Object.assign({}, supportedFormats[encName].defaultEncoderOptions, {
[optionToOptimize]: quality,
}),
);
const decode = (binary) => decoder.decode(binary);
const { bitmap, binary, quality } = await autoOptimize(
bitmapIn,
encode,
decode,
{
min: supportedFormats[encName].autoOptimize.min,
max: supportedFormats[encName].autoOptimize.max,
butteraugliDistanceGoal: optimizerButteraugliTarget,
maxRounds: maxOptimizerRounds,
},
);
out = binary;
const opts = {
// 5 significant digits is enough
[optionToOptimize]: Math.round(quality * 10000) / 10000,
};
infoText = ` using --${encName} '${JSON5.stringify(opts)}'`;
} else {
out = encoder.encode(
bitmapIn.data.buffer,
bitmapIn.width,
bitmapIn.height,
encConfig,
);
}
await fsp.writeFile(outputFile, out);
return {
infoText,
inputSize: size,
inputFile: file,
outputFile,
outputSize: out.length,
};
}
// both decoding and encoding go through the worker pool
function handleJob(params) {
const { operation } = params;
switch (operation) {
case 'encode':
return encodeFile(params);
case 'decode':
return decodeFile(params.file);
case 'preprocess':
return preprocessImage(params);
default:
throw Error(`Invalid job "${operation}"`);
}
}
function progressTracker(results) {
const spinner = ora();
const tracker = {};
@ -51,12 +163,13 @@ function progressTracker(results) {
};
function getResultsText() {
let out = '';
for (const result of results.values()) {
out += `\n ${kleur.cyan(result.file)}: ${prettyPrintSize(result.size)}`;
for (const { outputFile, size: outputSize, infoText } of result.outputs) {
out += `\n ${kleur.dim('└')} ${kleur.cyan(
outputFile.padEnd(5),
)}${prettyPrintSize(outputSize)}`;
for (const [filename, result] of results.entries()) {
out += `\n ${kleur.cyan(filename)}: ${prettyPrintSize(result.size)}`;
for (const { outputFile, outputSize, infoText } of result.outputs) {
const name = (program.suffix + extname(outputFile)).padEnd(5);
out += `\n ${kleur.dim('└')} ${kleur.cyan(name)}${prettyPrintSize(
outputSize,
)}`;
const percent = ((outputSize / result.size) * 100).toPrecision(3);
out += ` (${kleur[outputSize > result.size ? 'red' : 'green'](
percent + '%',
@ -73,17 +186,17 @@ function progressTracker(results) {
async function getInputFiles(paths) {
const validFiles = [];
for (const inputPath of paths) {
const files = (await fsp.lstat(inputPath)).isDirectory()
? (await fsp.readdir(inputPath, {withFileTypes: true})).filter(dirent => dirent.isFile()).map(dirent => path.join(inputPath, dirent.name))
: [inputPath];
for (const path of paths) {
const files = (await fsp.lstat(path)).isDirectory()
? (await fsp.readdir(path)).map(file => join(path, file))
: [path];
for (const file of files) {
try {
await fsp.stat(file);
} catch (err) {
if (err.code === 'ENOENT') {
console.warn(
`Warning: Input file does not exist: ${path.resolve(file)}`,
`Warning: Input file does not exist: ${resolvePath(file)}`,
);
continue;
} else {
@ -101,7 +214,7 @@ async function getInputFiles(paths) {
async function processFiles(files) {
files = await getInputFiles(files);
const imagePool = new ImagePool();
const parallelism = cpus().length;
const results = new Map();
const progress = progressTracker(results);
@ -110,123 +223,140 @@ async function processFiles(files) {
progress.totalOffset = files.length;
progress.setProgress(0, files.length);
const workerPool = new WorkerPool(parallelism, __filename);
// Create output directory
await fsp.mkdir(program.opts().outputDir, { recursive: true });
await fsp.mkdir(program.outputDir, { recursive: true });
let decoded = 0;
let decodedFiles = await Promise.all(
files.map(async (file) => {
const image = imagePool.ingestImage(file);
await image.decoded;
results.set(image, {
const result = await workerPool.dispatchJob({
operation: 'decode',
file,
size: (await image.decoded).size,
});
results.set(file, {
file: result.file,
size: result.size,
outputs: [],
});
progress.setProgress(++decoded, files.length);
return image;
return result;
}),
);
const preprocessOptions = {};
for (const preprocessorName of Object.keys(preprocessors)) {
if (!program.opts()[preprocessorName]) {
for (const [preprocessorName, value] of Object.entries(preprocessors)) {
if (!program[preprocessorName]) {
continue;
}
preprocessOptions[preprocessorName] = JSON5.parse(
program.opts()[preprocessorName],
const preprocessorParam = program[preprocessorName];
const preprocessorOptions = Object.assign(
{},
value.defaultOptions,
JSON5.parse(preprocessorParam),
);
decodedFiles = await Promise.all(
decodedFiles.map(async (file) => {
return workerPool.dispatchJob({
file,
operation: 'preprocess',
preprocessorName,
options: preprocessorOptions,
});
}),
);
}
for (const image of decodedFiles) {
image.preprocess(preprocessOptions);
}
await Promise.all(decodedFiles.map((image) => image.decoded));
progress.progressOffset = decoded;
progress.setStatus(
'Encoding ' + kleur.dim(`(${imagePool.workerPool.numWorkers} threads)`),
);
progress.setStatus('Encoding ' + kleur.dim(`(${parallelism} threads)`));
progress.setProgress(0, files.length);
const jobs = [];
let jobsStarted = 0;
let jobsFinished = 0;
for (const image of decodedFiles) {
const originalFile = results.get(image).file;
for (const { file, bitmap, size } of decodedFiles) {
const ext = extname(file);
const base = basename(file, ext) + program.suffix;
const encodeOptions = {
optimizerButteraugliTarget: Number(
program.opts().optimizerButteraugliTarget,
),
maxOptimizerRounds: Number(program.opts().maxOptimizerRounds),
};
for (const encName of Object.keys(encoders)) {
if (!program.opts()[encName]) {
for (const [encName, value] of Object.entries(supportedFormats)) {
if (!program[encName]) {
continue;
}
const encParam = program.opts()[encName];
const encParam =
typeof program[encName] === 'string' ? program[encName] : '{}';
const encConfig =
encParam.toLowerCase() === 'auto' ? 'auto' : JSON5.parse(encParam);
encodeOptions[encName] = encConfig;
encParam.toLowerCase() === 'auto'
? 'auto'
: Object.assign(
{},
value.defaultEncoderOptions,
JSON5.parse(encParam),
);
const outputFile = join(program.outputDir, `${base}.${value.extension}`);
jobsStarted++;
const p = workerPool
.dispatchJob({
operation: 'encode',
file,
size,
bitmap,
outputFile,
encName,
encConfig,
optimizerButteraugliTarget: Number(
program.optimizerButteraugliTarget,
),
maxOptimizerRounds: Number(program.maxOptimizerRounds),
})
.then((output) => {
jobsFinished++;
results.get(file).outputs.push(output);
progress.setProgress(jobsFinished, jobsStarted);
});
jobs.push(p);
}
jobsStarted++;
const job = image.encode(encodeOptions).then(async () => {
jobsFinished++;
const outputPath = path.join(
program.opts().outputDir,
program.opts().suffix +
path.basename(originalFile, path.extname(originalFile)),
);
for (const output of Object.values(image.encodedWith)) {
const outputFile = `${outputPath}.${(await output).extension}`;
await fsp.writeFile(outputFile, (await output).binary);
results
.get(image)
.outputs.push(Object.assign(await output, { outputFile }));
}
progress.setProgress(jobsFinished, jobsStarted);
});
jobs.push(job);
}
// update the progress to account for multi-format
progress.setProgress(jobsFinished, jobsStarted);
// Wait for all jobs to finish
await workerPool.join();
await Promise.all(jobs);
await imagePool.close();
progress.finish('Squoosh results:');
}
program
.name('squoosh-cli')
.arguments('<files...>')
.option('-d, --output-dir <dir>', 'Output directory', '.')
.option('-s, --suffix <suffix>', 'Append suffix to output files', '')
.option(
'--max-optimizer-rounds <rounds>',
'Maximum number of compressions to use for auto optimizations',
'6',
)
.option(
'--optimizer-butteraugli-target <butteraugli distance>',
'Target Butteraugli distance for auto optimizer',
'1.4',
)
.action(processFiles);
if (isMainThread) {
program
.name('squoosh-cli')
.version(version)
.arguments('<files...>')
.option('-d, --output-dir <dir>', 'Output directory', '.')
.option('-s, --suffix <suffix>', 'Append suffix to output files', '')
.option(
'--max-optimizer-rounds <rounds>',
'Maximum number of compressions to use for auto optimizations',
'6',
)
.option(
'--optimizer-butteraugli-target <butteraugli distance>',
'Target Butteraugli distance for auto optimizer',
'1.4',
)
.action(processFiles);
// Create a CLI option for each supported preprocessor
for (const [key, value] of Object.entries(preprocessors)) {
program.option(`--${key} [config]`, value.description);
}
// Create a CLI option for each supported encoder
for (const [key, value] of Object.entries(encoders)) {
program.option(
`--${key} [config]`,
`Use ${value.name} to generate a .${value.extension} file with the given configuration`,
);
}
// Create a CLI option for each supported preprocessor
for (const [key, value] of Object.entries(preprocessors)) {
program.option(`--${key} [config]`, value.description);
}
// Create a CLI option for each supported encoder
for (const [key, value] of Object.entries(supportedFormats)) {
program.option(
`--${key} [config]`,
`Use ${value.name} to generate a .${value.extension} file with the given configuration`,
);
}
program.parse(process.argv);
program.parse(process.argv);
} else {
WorkerPool.useThisThreadAsWorker(handleJob);
}

View File

@ -1,9 +1,9 @@
# libavif and libaom versions are from
# https://docs.google.com/document/d/1wEEA5rRU7wT54k41u3qyZIZHDCJArIMzLuzsrLAwaK8/edit
CODEC_URL = https://github.com/AOMediaCodec/libavif/archive/1c39e772c2c0d687691dd4b589a12c323f5f767d.tar.gz
CODEC_URL = https://github.com/AOMediaCodec/libavif/archive/d37ef74127986184500e571bf1f9793cc0bdef50.tar.gz
CODEC_PACKAGE = node_modules/libavif.tar.gz
LIBAOM_URL = https://aomedia.googlesource.com/aom/+archive/v3.1.0.tar.gz
LIBAOM_URL = https://aomedia.googlesource.com/aom/+archive/0a5da45c7f942908974f5ab8e107c9fa82048ae7.tar.gz
LIBAOM_PACKAGE = node_modules/libaom.tar.gz
export CODEC_DIR = node_modules/libavif

View File

@ -29,10 +29,8 @@ struct AvifOptions {
bool chromaDeltaQ;
// 0-7
int sharpness;
// 0 = auto
// 1 = PSNR
// 2 = SSIM
int tune;
// Target ssim rather than psnr
bool targetSsim;
// 0-50
int denoiseLevel;
};
@ -100,7 +98,7 @@ val encode(std::string buffer, int width, int height, AvifOptions options) {
std::to_string(options.cqAlphaLevel).c_str());
}
if (options.tune == 2 || (options.tune == 0 && options.cqLevel <= 32)) {
if (options.targetSsim) {
avifEncoderSetCodecSpecificOption(encoder, "tune", "ssim");
}
@ -138,7 +136,7 @@ EMSCRIPTEN_BINDINGS(my_module) {
.field("speed", &AvifOptions::speed)
.field("chromaDeltaQ", &AvifOptions::chromaDeltaQ)
.field("sharpness", &AvifOptions::sharpness)
.field("tune", &AvifOptions::tune)
.field("targetSsim", &AvifOptions::targetSsim)
.field("denoiseLevel", &AvifOptions::denoiseLevel)
.field("subsample", &AvifOptions::subsample);

View File

@ -1,9 +1,3 @@
export const enum AVIFTune {
auto,
psnr,
ssim,
}
export interface EncodeOptions {
cqLevel: number;
denoiseLevel: number;
@ -14,7 +8,7 @@ export interface EncodeOptions {
subsample: number;
chromaDeltaQ: boolean;
sharpness: number;
tune: AVIFTune;
targetSsim: boolean;
}
export interface AVIFModule extends EmscriptenWasm.Module {

Binary file not shown.

View File

@ -18,7 +18,7 @@ function Ia(a){for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&5
if(B)e=z.wasmMemory,l=z.buffer;else if(z.wasmMemory)e=z.wasmMemory;else if(e=new WebAssembly.Memory({initial:Ja/65536,maximum:32768,shared:!0}),!(e.buffer instanceof SharedArrayBuffer))throw D("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag"),Error("bad memory");e&&(l=e.buffer);Ja=l.byteLength;n(l);var H,Ka=[],La=[],Ma=[],Na=[];
function Oa(){var a=z.preRun.shift();Ka.unshift(a)}var I=0,Pa=null,Qa=null;z.preloadedImages={};z.preloadedAudios={};function E(a){if(z.onAbort)z.onAbort(a);B&&console.error("Pthread aborting at "+Error().stack);D(a);ya=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");pa(a);throw a;}function Ra(){var a=K;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var K="avif_enc_mt.wasm";
Ra()||(K=sa(K));function Sa(){try{if(wa)return new Uint8Array(wa);if(ta)return ta(K);throw"both async and sync fetching of the wasm failed";}catch(a){E(a)}}function Ta(){return wa||"function"!==typeof fetch?Promise.resolve().then(Sa):fetch(K,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+K+"'";return a.arrayBuffer()}).catch(function(){return Sa()})}
var Va={597253:function(a,b){setTimeout(function(){Ua(a,b)},0)},597331:function(){throw"Canceled!";}};function Wa(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(z);else{var c=b.Eb;"number"===typeof c?void 0===b.eb?H.get(c)():H.get(c)(b.eb):c(void 0===b.eb?null:b.eb)}}}function Xa(a,b,c){var d;-1!=a.indexOf("j")?d=c&&c.length?z["dynCall_"+a].apply(null,[b].concat(c)):z["dynCall_"+a].call(null,b):d=H.get(b).apply(null,c);return d}z.dynCall=Xa;var L=0,Ya=0,Za=0;
var Va={597269:function(a,b){setTimeout(function(){Ua(a,b)},0)},597347:function(){throw"Canceled!";}};function Wa(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(z);else{var c=b.Eb;"number"===typeof c?void 0===b.eb?H.get(c)():H.get(c)(b.eb):c(void 0===b.eb?null:b.eb)}}}function Xa(a,b,c){var d;-1!=a.indexOf("j")?d=c&&c.length?z["dynCall_"+a].apply(null,[b].concat(c)):z["dynCall_"+a].call(null,b):d=H.get(b).apply(null,c);return d}z.dynCall=Xa;var L=0,Ya=0,Za=0;
function $a(a,b,c){L=a|0;Za=b|0;Ya=c|0}z.registerPthreadPtr=$a;function ab(a,b){if(0>=a||a>aa().length||a&1||0>b)return-28;if(0==b)return 0;2147483647<=b&&(b=Infinity);var c=Atomics.load(w(),M.vb>>2),d=0;if(c==a&&Atomics.compareExchange(w(),M.vb>>2,c,0)==c&&(--b,d=1,0>=b))return 1;a=Atomics.notify(w(),a>>2,b);if(0<=a)return a+d;throw"Atomics.notify returned an unexpected value "+a;}z._emscripten_futex_wake=ab;
function bb(a){if(B)throw"Internal Error! cleanupThread() can only ever be called from main application thread!";if(!a)throw"Internal Error! Null pthread_ptr in cleanupThread!";w()[a+12>>2]=0;(a=M.Ya[a])&&M.jb(a.worker)}
var M={ac:1,kc:{yb:0,zb:0},Wa:[],$a:[],Lb:function(){for(var a=navigator.hardwareConcurrency,b=0;b<a;++b)M.pb()},Mb:function(){M.Ua=N(232);for(var a=0;58>a;++a)y()[M.Ua/4+a]=0;w()[M.Ua+12>>2]=M.Ua;a=M.Ua+156;w()[a>>2]=a;var b=N(512);for(a=0;128>a;++a)y()[b/4+a]=0;Atomics.store(y(),M.Ua+104>>2,b);Atomics.store(y(),M.Ua+40>>2,M.Ua);Atomics.store(y(),M.Ua+44>>2,42);M.tb();$a(M.Ua,!1,1);cb(M.Ua)},Nb:function(){M.tb();oa(z);M.receiveObjectTransfer=M.Sb;M.setThreadStatus=M.Tb;M.threadCancel=M.Yb;M.threadExit=
@ -86,7 +86,7 @@ z._emscripten_sync_run_in_main_thread_1=function(){return(z._emscripten_sync_run
z._emscripten_sync_run_in_main_thread_3=function(){return(z._emscripten_sync_run_in_main_thread_3=z.asm.Ga).apply(null,arguments)};var Cc=z._emscripten_sync_run_in_main_thread_4=function(){return(Cc=z._emscripten_sync_run_in_main_thread_4=z.asm.Ha).apply(null,arguments)};z._emscripten_sync_run_in_main_thread_5=function(){return(z._emscripten_sync_run_in_main_thread_5=z.asm.Ia).apply(null,arguments)};
z._emscripten_sync_run_in_main_thread_6=function(){return(z._emscripten_sync_run_in_main_thread_6=z.asm.Ja).apply(null,arguments)};z._emscripten_sync_run_in_main_thread_7=function(){return(z._emscripten_sync_run_in_main_thread_7=z.asm.Ka).apply(null,arguments)};
var Wb=z._emscripten_run_in_main_runtime_thread_js=function(){return(Wb=z._emscripten_run_in_main_runtime_thread_js=z.asm.La).apply(null,arguments)},bc=z.__emscripten_call_on_thread=function(){return(bc=z.__emscripten_call_on_thread=z.asm.Ma).apply(null,arguments)};z._emscripten_tls_init=function(){return(z._emscripten_tls_init=z.asm.Na).apply(null,arguments)};z.dynCall_jiiiiiiiii=function(){return(z.dynCall_jiiiiiiiii=z.asm.Oa).apply(null,arguments)};
z.dynCall_jiji=function(){return(z.dynCall_jiji=z.asm.Pa).apply(null,arguments)};z.dynCall_jiiiiiiii=function(){return(z.dynCall_jiiiiiiii=z.asm.Qa).apply(null,arguments)};z.dynCall_jiiiiii=function(){return(z.dynCall_jiiiiii=z.asm.Ra).apply(null,arguments)};z.dynCall_jiiiii=function(){return(z.dynCall_jiiiii=z.asm.Sa).apply(null,arguments)};z.dynCall_iiijii=function(){return(z.dynCall_iiijii=z.asm.Ta).apply(null,arguments)};var db=z._main_thread_futex=899108;
z.dynCall_jiji=function(){return(z.dynCall_jiji=z.asm.Pa).apply(null,arguments)};z.dynCall_jiiiiiiii=function(){return(z.dynCall_jiiiiiiii=z.asm.Qa).apply(null,arguments)};z.dynCall_jiiiiii=function(){return(z.dynCall_jiiiiii=z.asm.Ra).apply(null,arguments)};z.dynCall_jiiiii=function(){return(z.dynCall_jiiiii=z.asm.Sa).apply(null,arguments)};z.dynCall_iiijii=function(){return(z.dynCall_iiijii=z.asm.Ta).apply(null,arguments)};var db=z._main_thread_futex=899124;
function zc(a,b){var c=Y();try{H.get(a)(b)}catch(d){P(c);if(d!==d+0&&"longjmp"!==d)throw d;Z(1,0)}}function Bc(a,b,c,d,f){var g=Y();try{H.get(a)(b,c,d,f)}catch(h){P(g);if(h!==h+0&&"longjmp"!==h)throw h;Z(1,0)}}function Ac(a,b,c){var d=Y();try{H.get(a)(b,c)}catch(f){P(d);if(f!==f+0&&"longjmp"!==f)throw f;Z(1,0)}}function yc(a,b,c,d,f,g,h,k,m,q){var p=Y();try{return H.get(a)(b,c,d,f,g,h,k,m,q)}catch(v){P(p);if(v!==v+0&&"longjmp"!==v)throw v;Z(1,0)}}
function vc(a,b,c){var d=Y();try{return H.get(a)(b,c)}catch(f){P(d);if(f!==f+0&&"longjmp"!==f)throw f;Z(1,0)}}function wc(a,b,c,d,f){var g=Y();try{return H.get(a)(b,c,d,f)}catch(h){P(g);if(h!==h+0&&"longjmp"!==h)throw h;Z(1,0)}}function uc(a,b){var c=Y();try{return H.get(a)(b)}catch(d){P(c);if(d!==d+0&&"longjmp"!==d)throw d;Z(1,0)}}function xc(a,b,c,d,f,g,h,k,m){var q=Y();try{return H.get(a)(b,c,d,f,g,h,k,m)}catch(p){P(q);if(p!==p+0&&"longjmp"!==p)throw p;Z(1,0)}}z.PThread=M;z.PThread=M;
z._pthread_self=oc;z.wasmMemory=e;z.ExitStatus=Fc;var Gc;function Fc(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}Qa=function Hc(){Gc||Ic();Gc||(Qa=Hc)};

Binary file not shown.

Binary file not shown.

3
codecs/build-wasi-sdk.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh -e
docker build -t squoosh-wasi-sdk - < ../wasi-sdk.Dockerfile
docker run -it --rm -v $PWD:/src squoosh-wasi-sdk "$@"

View File

@ -1,5 +1,5 @@
CODEC_URL = https://gitlab.com/wg1/jpeg-xl.git
CODEC_VERSION = ab7c5e9b6795134377aa4846ceaae2c5bc504f76
CODEC_VERSION = v0.3.3
CODEC_DIR = node_modules/jxl
CODEC_BUILD_ROOT := $(CODEC_DIR)/build
CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt

Binary file not shown.

Binary file not shown.

View File

@ -18,7 +18,6 @@ struct JXLOptions {
int epf;
int nearLossless;
bool lossyPalette;
size_t decodingSpeedTier;
};
val encode(std::string image, int width, int height, JXLOptions options) {
@ -36,7 +35,6 @@ val encode(std::string image, int width, int height, JXLOptions options) {
cparams.epf = options.epf;
cparams.speed_tier = static_cast<jxl::SpeedTier>(options.speed);
cparams.near_lossless = options.nearLossless;
cparams.decoding_speed_tier = options.decodingSpeedTier;
if (options.lossyPalette) {
cparams.lossy_palette = true;
@ -115,7 +113,6 @@ EMSCRIPTEN_BINDINGS(my_module) {
.field("progressive", &JXLOptions::progressive)
.field("nearLossless", &JXLOptions::nearLossless)
.field("lossyPalette", &JXLOptions::lossyPalette)
.field("decodingSpeedTier", &JXLOptions::decodingSpeedTier)
.field("epf", &JXLOptions::epf);
function("encode", &encode);

View File

@ -5,7 +5,6 @@ export interface EncodeOptions {
epf: number;
nearLossless: number;
lossyPalette: boolean;
decodingSpeedTier: number;
}
export interface JXLModule extends EmscriptenWasm.Module {

View File

@ -50,9 +50,9 @@ v.push(p+"}\n");k=Ya(v).apply(null,q);l=b-1;if(!f.hasOwnProperty(n))throw new Oa
readValueFromPointer:d},{ja:!0})},k:function(a,b){b=U(b);var c="std::string"===b;T(a,{name:b,fromWireType:function(d){var g=K[d>>2];if(c)for(var h=d+4,m=0;m<=g;++m){var k=d+4+m;if(m==g||0==E[k]){h=ia(h,k-h);if(void 0===n)var n=h;else n+=String.fromCharCode(0),n+=h;h=k+1}}else{n=Array(g);for(m=0;m<g;++m)n[m]=String.fromCharCode(E[d+4+m]);n=n.join("")}Z(d);return n},toWireType:function(d,g){g instanceof ArrayBuffer&&(g=new Uint8Array(g));var h="string"===typeof g;h||g instanceof Uint8Array||g instanceof
Uint8ClampedArray||g instanceof Int8Array||V("Cannot pass non-string to std::string");var m=(c&&h?function(){return ka(g)}:function(){return g.length})(),k=zb(4+m+1);K[k>>2]=m;if(c&&h)ja(g,E,k+4,m+1);else if(h)for(h=0;h<m;++h){var n=g.charCodeAt(h);255<n&&(Z(k),V("String has UTF-16 code units that do not fit in 8 bits"));E[k+4+h]=n}else for(h=0;h<m;++h)E[k+4+h]=g[h];null!==d&&d.push(Z,k);return k},argPackAdvance:8,readValueFromPointer:Ja,T:function(d){Z(d)}})},h:function(a,b,c){c=U(c);if(2===b){var d=
ma;var g=na;var h=oa;var m=function(){return F};var k=1}else 4===b&&(d=pa,g=qa,h=ra,m=function(){return K},k=2);T(a,{name:c,fromWireType:function(n){for(var p=K[n>>2],q=m(),r,x=n+4,e=0;e<=p;++e){var l=n+4+e*b;if(e==p||0==q[l>>k])x=d(x,l-x),void 0===r?r=x:(r+=String.fromCharCode(0),r+=x),x=l+b}Z(n);return r},toWireType:function(n,p){"string"!==typeof p&&V("Cannot pass non-string to C++ string type "+c);var q=h(p),r=zb(4+q+b);K[r>>2]=q>>k;g(p,r+4,q+b);null!==n&&n.push(Z,r);return r},argPackAdvance:8,
readValueFromPointer:Ja,T:function(n){Z(n)}})},n:function(a,b,c,d,g,h){Ha[a]={name:U(b),la:Y(c,d),ma:Y(g,h),ba:[]}},e:function(a,b,c,d,g,h,m,k,n,p){Ha[a].ba.push({ea:U(b),ia:c,ga:Y(d,g),ha:h,ta:m,sa:Y(k,n),ua:p})},A:function(a,b){b=U(b);T(a,{za:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},g:Ua,C:function(a){if(0===a)return Va(ib());var b=hb[a];a=void 0===b?U(a):b;return Va(ib()[a])},B:function(a){4<a&&(X[a].aa+=1)},o:function(a,b,c,d){a||V("Cannot use deleted val. handle = "+
readValueFromPointer:Ja,T:function(n){Z(n)}})},n:function(a,b,c,d,g,h){Ha[a]={name:U(b),la:Y(c,d),ma:Y(g,h),ba:[]}},f:function(a,b,c,d,g,h,m,k,n,p){Ha[a].ba.push({ea:U(b),ia:c,ga:Y(d,g),ha:h,ta:m,sa:Y(k,n),ua:p})},A:function(a,b){b=U(b);T(a,{za:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},g:Ua,C:function(a){if(0===a)return Va(ib());var b=hb[a];a=void 0===b?U(a):b;return Va(ib()[a])},B:function(a){4<a&&(X[a].aa+=1)},o:function(a,b,c,d){a||V("Cannot use deleted val. handle = "+
a);a=X[a].value;var g=kb[b];if(!g){g="";for(var h=0;h<b;++h)g+=(0!==h?", ":"")+"arg"+h;var m="return function emval_allocator_"+b+"(constructor, argTypes, args) {\n";for(h=0;h<b;++h)m+="var argType"+h+" = requireRegisteredType(Module['HEAP32'][(argTypes >>> 2) + "+h+'], "parameter '+h+'");\nvar arg'+h+" = argType"+h+".readValueFromPointer(args);\nargs += argType"+h+"['argPackAdvance'];\n";g=(new Function("requireRegisteredType","Module","__emval_register",m+("var obj = new constructor("+g+");\nreturn __emval_register(obj);\n}\n")))(jb,
f,Va);kb[b]=g}return g(a,c,d)},b:function(){C()},t:function(a,b,c){E.copyWithin(a,b,b+c)},f:function(a){a>>>=0;var b=E.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{D.grow(Math.min(2147483648,d)-I.byteLength+65535>>>16);ua(D.buffer);var g=1;break a}catch(h){}g=void 0}if(g)return!0}return!1},v:function(a,b){var c=0;mb().forEach(function(d,g){var h=b+c;g=H[a+4*g>>2]=h;for(h=0;h<d.length;++h)J[g++>>
f,Va);kb[b]=g}return g(a,c,d)},b:function(){C()},t:function(a,b,c){E.copyWithin(a,b,b+c)},e:function(a){a>>>=0;var b=E.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{D.grow(Math.min(2147483648,d)-I.byteLength+65535>>>16);ua(D.buffer);var g=1;break a}catch(h){}g=void 0}if(g)return!0}return!1},v:function(a,b){var c=0;mb().forEach(function(d,g){var h=b+c;g=H[a+4*g>>2]=h;for(h=0;h<d.length;++h)J[g++>>
0]=d.charCodeAt(h);J[g>>0]=0;c+=d.length+1});return 0},w:function(a,b){var c=mb();H[a>>2]=c.length;var d=0;c.forEach(function(g){d+=g.length+1});H[b>>2]=d;return 0},x:function(){return 0},r:function(){},i:function(a,b,c,d){for(var g=0,h=0;h<c;h++){for(var m=H[b+8*h>>2],k=H[b+(8*h+4)>>2],n=0;n<k;n++){var p=E[m+n],q=ob[a];if(0===p||10===p){for(p=0;q[p]&&!(NaN<=p);)++p;p=ha.decode(q.subarray?q.subarray(0,p):new Uint8Array(q.slice(0,p)));(1===a?ea:z)(p);q.length=0}else q.push(p)}g+=k}H[d>>2]=g;return 0},
a:D,s:function(){},u:function(a,b,c,d){return ub(a,b,c,d)}};
(function(){function a(g){f.asm=g.exports;L=f.asm.E;M--;f.monitorRunDependencies&&f.monitorRunDependencies(M);0==M&&(null!==Ba&&(clearInterval(Ba),Ba=null),N&&(g=N,N=null,g()))}function b(g){a(g.instance)}function c(g){return Fa().then(function(h){return WebAssembly.instantiate(h,d)}).then(g,function(h){z("failed to asynchronously prepare wasm: "+h);C(h)})}var d={a:Ab};M++;f.monitorRunDependencies&&f.monitorRunDependencies(M);if(f.instantiateWasm)try{return f.instantiateWasm(d,a)}catch(g){return z("Module.instantiateWasm callback failed with error: "+

Binary file not shown.

View File

@ -17,7 +17,7 @@ function Da(a){return 2*a.length}function Ea(a,b){for(var c=0,d="";!(c>=b/4);){v
function Ga(a){for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&57343>=d&&++c;b+=4}return b}function Ha(a,b){e().set(a,b)}var n,aa,ba,ca,fa,ha,ia,ka,ma;function u(a){n=a;D.HEAP8=aa=new Int8Array(a);D.HEAP16=ca=new Int16Array(a);D.HEAP32=ha=new Int32Array(a);D.HEAPU8=ba=new Uint8Array(a);D.HEAPU16=fa=new Uint16Array(a);D.HEAPU32=ia=new Uint32Array(a);D.HEAPF32=ka=new Float32Array(a);D.HEAPF64=ma=new Float64Array(a)}var Ia=D.INITIAL_MEMORY||16777216;
if(G)m=D.wasmMemory,n=D.buffer;else if(D.wasmMemory)m=D.wasmMemory;else if(m=new WebAssembly.Memory({initial:Ia/65536,maximum:32768,shared:!0}),!(m.buffer instanceof SharedArrayBuffer))throw J("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag"),Error("bad memory");m&&(n=m.buffer);Ia=n.byteLength;u(n);var M,Ja=[],Ka=[],La=[],Ma=[];
function Na(){var a=D.preRun.shift();Ja.unshift(a)}var N=0,Oa=null,Pa=null;D.preloadedImages={};D.preloadedAudios={};function K(a){if(D.onAbort)D.onAbort(a);G&&console.error("Pthread aborting at "+Error().stack);J(a);va=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");oa(a);throw a;}function Qa(){var a=O;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var O="jxl_enc_mt.wasm";
Qa()||(O=qa(O));function Ra(){try{if(ta)return new Uint8Array(ta);if(ra)return ra(O);throw"both async and sync fetching of the wasm failed";}catch(a){K(a)}}function Sa(){return ta||"function"!==typeof fetch?Promise.resolve().then(Ra):fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return Ra()})}var Ua={60485:function(a,b){setTimeout(function(){Ta(a,b)},0)},60563:function(){throw"Canceled!";}};
Qa()||(O=qa(O));function Ra(){try{if(ta)return new Uint8Array(ta);if(ra)return ra(O);throw"both async and sync fetching of the wasm failed";}catch(a){K(a)}}function Sa(){return ta||"function"!==typeof fetch?Promise.resolve().then(Ra):fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return Ra()})}var Ua={60053:function(a,b){setTimeout(function(){Ta(a,b)},0)},60131:function(){throw"Canceled!";}};
function Va(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(D);else{var c=b.Bb;"number"===typeof c?void 0===b.Va?M.get(c)():M.get(c)(b.Va):c(void 0===b.Va?null:b.Va)}}}function Wa(a,b,c){var d;-1!=a.indexOf("j")?d=c&&c.length?D["dynCall_"+a].apply(null,[b].concat(c)):D["dynCall_"+a].call(null,b):d=M.get(b).apply(null,c);return d}D.dynCall=Wa;var P=0,Xa=0,Ya=0;function Za(a,b,c){P=a|0;Ya=b|0;Xa=c|0}D.registerPthreadPtr=Za;
function $a(a,b){if(0>=a||a>e().length||a&1||0>b)return-28;if(0==b)return 0;2147483647<=b&&(b=Infinity);var c=Atomics.load(A(),Q.rb>>2),d=0;if(c==a&&Atomics.compareExchange(A(),Q.rb>>2,c,0)==c&&(--b,d=1,0>=b))return 1;a=Atomics.notify(A(),a>>2,b);if(0<=a)return a+d;throw"Atomics.notify returned an unexpected value "+a;}D._emscripten_futex_wake=$a;
function ab(a){if(G)throw"Internal Error! cleanupThread() can only ever be called from main application thread!";if(!a)throw"Internal Error! Null pthread_ptr in cleanupThread!";A()[a+12>>2]=0;(a=Q.Oa[a])&&Q.bb(a.worker)}
@ -77,10 +77,10 @@ r){if("number"!==typeof r&&"boolean"!==typeof r)throw new TypeError('Cannot conv
Uint32Array,Float32Array,Float64Array][b];c=W(c);V(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{Gb:!0})},u:function(a,b){b=W(b);var c="std::string"===b;V(a,{name:b,fromWireType:function(d){var f=C()[d>>2];if(c)for(var g=d+4,l=0;l<=f;++l){var k=d+4+l;if(l==f||0==v()[k]){g=L(g,k-g);if(void 0===q)var q=g;else q+=String.fromCharCode(0),q+=g;g=k+1}}else{q=Array(f);for(l=0;l<f;++l)q[l]=String.fromCharCode(v()[d+4+l]);q=q.join("")}S(d);return q},toWireType:function(d,f){f instanceof
ArrayBuffer&&(f=new Uint8Array(f));var g="string"===typeof f;g||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array||X("Cannot pass non-string to std::string");var l=(c&&g?function(){return Aa(f)}:function(){return f.length})(),k=R(4+l+1);C()[k>>2]=l;if(c&&g)za(f,k+4,l+1);else if(g)for(g=0;g<l;++g){var q=f.charCodeAt(g);255<q&&(S(k),X("String has UTF-16 code units that do not fit in 8 bits"));v()[k+4+g]=q}else for(g=0;g<l;++g)v()[k+4+g]=f[g];null!==d&&d.push(S,k);return k},
argPackAdvance:8,readValueFromPointer:nb,Pa:function(d){S(d)}})},q:function(a,b,c){c=W(c);if(2===b){var d=Ba;var f=Ca;var g=Da;var l=function(){return ea()};var k=1}else 4===b&&(d=Ea,f=Fa,g=Ga,l=function(){return C()},k=2);V(a,{name:c,fromWireType:function(q){for(var t=C()[q>>2],r=l(),w,z=q+4,h=0;h<=t;++h){var p=q+4+h*b;if(h==t||0==r[p>>k])z=d(z,p-z),void 0===w?w=z:(w+=String.fromCharCode(0),w+=z),z=p+b}S(q);return w},toWireType:function(q,t){"string"!==typeof t&&X("Cannot pass non-string to C++ string type "+
c);var r=g(t),w=R(4+r+b);C()[w>>2]=r>>k;f(t,w+4,r+b);null!==q&&q.push(S,w);return w},argPackAdvance:8,readValueFromPointer:nb,Pa:function(q){S(q)}})},x:function(a,b,c,d,f,g){lb[a]={name:W(b),Ob:Hb(c,d),Pb:Hb(f,g),ob:[]}},k:function(a,b,c,d,f,g,l,k,q,t){lb[a].ob.push({Ab:W(b),Fb:c,Db:Hb(d,f),Eb:g,Yb:l,Xb:Hb(k,q),Zb:t})},T:function(a,b){b=W(b);V(a,{oc:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},H:function(a,b){if(a==b)postMessage({cmd:"processQueuedMainThreadWork"});
c);var r=g(t),w=R(4+r+b);C()[w>>2]=r>>k;f(t,w+4,r+b);null!==q&&q.push(S,w);return w},argPackAdvance:8,readValueFromPointer:nb,Pa:function(q){S(q)}})},x:function(a,b,c,d,f,g){lb[a]={name:W(b),Ob:Hb(c,d),Pb:Hb(f,g),ob:[]}},l:function(a,b,c,d,f,g,l,k,q,t){lb[a].ob.push({Ab:W(b),Fb:c,Db:Hb(d,f),Eb:g,Yb:l,Xb:Hb(k,q),Zb:t})},T:function(a,b){b=W(b);V(a,{oc:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},H:function(a,b){if(a==b)postMessage({cmd:"processQueuedMainThreadWork"});
else if(G)postMessage({targetThread:a,cmd:"processThreadQueue"});else{a=(a=Q.Oa[a])&&a.worker;if(!a)return;a.postMessage({cmd:"processThreadQueue"})}return 1},m:yb,W:function(a){if(0===a)return zb(Ob());var b=Nb[a];a=void 0===b?W(a):b;return zb(Ob()[a])},V:function(a){4<a&&(Y[a].jb+=1)},y:function(a,b,c,d){a||X("Cannot use deleted val. handle = "+a);a=Y[a].value;var f=Qb[b];if(!f){f="";for(var g=0;g<b;++g)f+=(0!==g?", ":"")+"arg"+g;var l="return function emval_allocator_"+b+"(constructor, argTypes, args) {\n";
for(g=0;g<b;++g)l+="var argType"+g+" = requireRegisteredType(Module['HEAP32'][(argTypes >>> 2) + "+g+'], "parameter '+g+'");\nvar arg'+g+" = argType"+g+".readValueFromPointer(args);\nargs += argType"+g+"['argPackAdvance'];\n";f=(new Function("requireRegisteredType","Module","__emval_register",l+("var obj = new constructor("+f+");\nreturn __emval_register(obj);\n}\n")))(Pb,D,zb);Qb[b]=f}return f(a,c,d)},b:function(){K()},n:function(a,b,c){Wb.length=0;var d;for(c>>=2;d=v()[b++];)(d=105>d)&&c&1&&c++,
Wb.push(d?la()[c++>>1]:A()[c]),++c;return Ua[a].apply(null,Wb)},J:function(){},r:function(){},f:Rb,g:$a,d:hb,p:function(){return Ya|0},o:function(){return Xa|0},C:function(a,b,c){v().copyWithin(a,b,b+c)},E:function(a,b,c){Vb.length=b;c>>=3;for(var d=0;d<b;d++)Vb[d]=la()[c+d];return(0>a?Ua[-a-1]:Cc[a]).apply(null,Vb)},l:function(a){a>>>=0;var b=v().length;if(a<=b||2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%
Wb.push(d?la()[c++>>1]:A()[c]),++c;return Ua[a].apply(null,Wb)},J:function(){},r:function(){},f:Rb,g:$a,d:hb,p:function(){return Ya|0},o:function(){return Xa|0},C:function(a,b,c){v().copyWithin(a,b,b+c)},E:function(a,b,c){Vb.length=b;c>>=3;for(var d=0;d<b;d++)Vb[d]=la()[c+d];return(0>a?Ua[-a-1]:Cc[a]).apply(null,Vb)},k:function(a){a>>>=0;var b=v().length;if(a<=b||2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%
65536);a:{try{m.grow(Math.min(2147483648,d)-n.byteLength+65535>>>16);u(m.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},F:function(a,b,c){return Yb(a)?Zb(a,b,c):ac(a,b,c)},e:function(){},G:function(a,b){var c={};b>>=2;c.alpha=!!A()[b];c.depth=!!A()[b+1];c.stencil=!!A()[b+2];c.antialias=!!A()[b+3];c.premultipliedAlpha=!!A()[b+4];c.preserveDrawingBuffer=!!A()[b+5];var d=A()[b+6];c.powerPreference=gc[d];c.failIfMajorPerformanceCaveat=!!A()[b+7];c.Mb=A()[b+8];c.qc=A()[b+9];c.nb=A()[b+
10];c.zb=A()[b+11];c.tc=A()[b+12];c.uc=A()[b+13];a=Yb(a);!a||c.zb?c=0:(a=a.getContext("webgl",c))?(b=R(8),A()[b+4>>2]=P|0,d={nc:b,attributes:c,version:c.Mb,Za:a},a.canvas&&(a.canvas.$a=d),("undefined"===typeof c.nb||c.nb)&&ec(d),c=b):c=0;return c},O:function(a,b){var c=0;ic().forEach(function(d,f){var g=b+c;f=A()[a+4*f>>2]=g;for(g=0;g<d.length;++g)e()[f++>>0]=d.charCodeAt(g);e()[f>>0]=0;c+=d.length+1});return 0},P:function(a,b){var c=ic();A()[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+
1});A()[b>>2]=d;return 0},Q:lc,z:mc,s:nc,B:function(){Q.Kb()},a:m||D.wasmMemory,D:ib,U:function(a,b,c,d){if("undefined"===typeof SharedArrayBuffer)return J("Current environment does not support SharedArrayBuffer, pthreads are not available!"),6;if(!a)return J("pthread_create called with a null thread pointer!"),28;var f=[];if(G&&0===f.length)return Ec(687865856,a,b,c,d);var g=0,l=0,k=0,q=0;if(b){var t=A()[b>>2];t+=81920;g=A()[b+8>>2];l=0!==A()[b+12>>2];if(0===A()[b+16>>2]){var r=A()[b+20>>2],w=A()[b+
@ -89,16 +89,17 @@ t,wa(0<g));r=R(232);for(w=0;58>w;++w)C()[(r>>2)+w]=0;A()[a>>2]=r;A()[r+12>>2]=r;
(function(){function a(f,g){D.asm=f.exports;M=D.asm.Y;ua=g;if(!G){var l=Q.Ma.length;Q.Ma.forEach(function(k){Q.qb(k,function(){if(!--l&&(N--,D.monitorRunDependencies&&D.monitorRunDependencies(N),0==N&&(null!==Oa&&(clearInterval(Oa),Oa=null),Pa))){var q=Pa;Pa=null;q()}})})}}function b(f){a(f.instance,f.module)}function c(f){return Sa().then(function(g){return WebAssembly.instantiate(g,d)}).then(f,function(g){J("failed to asynchronously prepare wasm: "+g);K(g)})}var d={a:Gc};G||(wa(!G,"addRunDependency cannot be used in a pthread worker"),
N++,D.monitorRunDependencies&&D.monitorRunDependencies(N));if(D.instantiateWasm)try{return D.instantiateWasm(d,a)}catch(f){return J("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return ta||"function"!==typeof WebAssembly.instantiateStreaming||Qa()||"function"!==typeof fetch?c(b):fetch(O,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,d).then(b,function(g){J("wasm streaming compile failed: "+g);J("falling back to ArrayBuffer instantiation");
return c(b)})})})().catch(oa);return{}})();var Dc=D.___wasm_call_ctors=function(){return(Dc=D.___wasm_call_ctors=D.asm.Z).apply(null,arguments)},R=D._malloc=function(){return(R=D._malloc=D.asm._).apply(null,arguments)},S=D._free=function(){return(S=D._free=D.asm.$).apply(null,arguments)},zc=D.___errno_location=function(){return(zc=D.___errno_location=D.asm.aa).apply(null,arguments)},Kb=D.___getTypeName=function(){return(Kb=D.___getTypeName=D.asm.ba).apply(null,arguments)};
D.___embind_register_native_and_builtin_types=function(){return(D.___embind_register_native_and_builtin_types=D.asm.ca).apply(null,arguments)};var oc=D._emscripten_get_global_libc=function(){return(oc=D._emscripten_get_global_libc=D.asm.da).apply(null,arguments)};D.___em_js__initPthreadsJS=function(){return(D.___em_js__initPthreadsJS=D.asm.ea).apply(null,arguments)};
var Sb=D.stackSave=function(){return(Sb=D.stackSave=D.asm.fa).apply(null,arguments)},gb=D.stackRestore=function(){return(gb=D.stackRestore=D.asm.ga).apply(null,arguments)},Tb=D.stackAlloc=function(){return(Tb=D.stackAlloc=D.asm.ha).apply(null,arguments)},Fc=D._memalign=function(){return(Fc=D._memalign=D.asm.ia).apply(null,arguments)};D._emscripten_main_browser_thread_id=function(){return(D._emscripten_main_browser_thread_id=D.asm.ja).apply(null,arguments)};
var db=D.___pthread_tsd_run_dtors=function(){return(db=D.___pthread_tsd_run_dtors=D.asm.ka).apply(null,arguments)},eb=D._emscripten_main_thread_process_queued_calls=function(){return(eb=D._emscripten_main_thread_process_queued_calls=D.asm.la).apply(null,arguments)};D._emscripten_current_thread_process_queued_calls=function(){return(D._emscripten_current_thread_process_queued_calls=D.asm.ma).apply(null,arguments)};
var bb=D._emscripten_register_main_browser_thread_id=function(){return(bb=D._emscripten_register_main_browser_thread_id=D.asm.na).apply(null,arguments)},Ta=D._do_emscripten_dispatch_to_thread=function(){return(Ta=D._do_emscripten_dispatch_to_thread=D.asm.oa).apply(null,arguments)};D._emscripten_async_run_in_main_thread=function(){return(D._emscripten_async_run_in_main_thread=D.asm.pa).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread=function(){return(D._emscripten_sync_run_in_main_thread=D.asm.qa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_0=function(){return(D._emscripten_sync_run_in_main_thread_0=D.asm.ra).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_1=function(){return(D._emscripten_sync_run_in_main_thread_1=D.asm.sa).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_2=function(){return(D._emscripten_sync_run_in_main_thread_2=D.asm.ta).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_xprintf_varargs=function(){return(D._emscripten_sync_run_in_main_thread_xprintf_varargs=D.asm.ua).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_3=function(){return(D._emscripten_sync_run_in_main_thread_3=D.asm.va).apply(null,arguments)};
var Ec=D._emscripten_sync_run_in_main_thread_4=function(){return(Ec=D._emscripten_sync_run_in_main_thread_4=D.asm.wa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_5=function(){return(D._emscripten_sync_run_in_main_thread_5=D.asm.xa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_6=function(){return(D._emscripten_sync_run_in_main_thread_6=D.asm.ya).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_7=function(){return(D._emscripten_sync_run_in_main_thread_7=D.asm.za).apply(null,arguments)};var Ub=D._emscripten_run_in_main_runtime_thread_js=function(){return(Ub=D._emscripten_run_in_main_runtime_thread_js=D.asm.Aa).apply(null,arguments)},$b=D.__emscripten_call_on_thread=function(){return($b=D.__emscripten_call_on_thread=D.asm.Ba).apply(null,arguments)};D._emscripten_tls_init=function(){return(D._emscripten_tls_init=D.asm.Ca).apply(null,arguments)};
D.dynCall_viijii=function(){return(D.dynCall_viijii=D.asm.Da).apply(null,arguments)};D.dynCall_iiji=function(){return(D.dynCall_iiji=D.asm.Ea).apply(null,arguments)};D.dynCall_jiji=function(){return(D.dynCall_jiji=D.asm.Fa).apply(null,arguments)};D.dynCall_iiiiiijj=function(){return(D.dynCall_iiiiiijj=D.asm.Ga).apply(null,arguments)};D.dynCall_iiiiij=function(){return(D.dynCall_iiiiij=D.asm.Ha).apply(null,arguments)};D.dynCall_iiiiijj=function(){return(D.dynCall_iiiiijj=D.asm.Ia).apply(null,arguments)};
var cb=D._main_thread_futex=74984;D.PThread=Q;D.PThread=Q;D._pthread_self=pc;D.wasmMemory=m;D.ExitStatus=Hc;var Ic;function Hc(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}Pa=function Jc(){Ic||Kc();Ic||(Pa=Jc)};
D.___embind_register_native_and_builtin_types=function(){return(D.___embind_register_native_and_builtin_types=D.asm.ca).apply(null,arguments)};D.___em_js__initPthreadsJS=function(){return(D.___em_js__initPthreadsJS=D.asm.da).apply(null,arguments)};
var oc=D._emscripten_get_global_libc=function(){return(oc=D._emscripten_get_global_libc=D.asm.ea).apply(null,arguments)},Sb=D.stackSave=function(){return(Sb=D.stackSave=D.asm.fa).apply(null,arguments)},gb=D.stackRestore=function(){return(gb=D.stackRestore=D.asm.ga).apply(null,arguments)},Tb=D.stackAlloc=function(){return(Tb=D.stackAlloc=D.asm.ha).apply(null,arguments)},Fc=D._memalign=function(){return(Fc=D._memalign=D.asm.ia).apply(null,arguments)};
D._emscripten_main_browser_thread_id=function(){return(D._emscripten_main_browser_thread_id=D.asm.ja).apply(null,arguments)};var db=D.___pthread_tsd_run_dtors=function(){return(db=D.___pthread_tsd_run_dtors=D.asm.ka).apply(null,arguments)},eb=D._emscripten_main_thread_process_queued_calls=function(){return(eb=D._emscripten_main_thread_process_queued_calls=D.asm.la).apply(null,arguments)};
D._emscripten_current_thread_process_queued_calls=function(){return(D._emscripten_current_thread_process_queued_calls=D.asm.ma).apply(null,arguments)};var bb=D._emscripten_register_main_browser_thread_id=function(){return(bb=D._emscripten_register_main_browser_thread_id=D.asm.na).apply(null,arguments)},Ta=D._do_emscripten_dispatch_to_thread=function(){return(Ta=D._do_emscripten_dispatch_to_thread=D.asm.oa).apply(null,arguments)};
D._emscripten_async_run_in_main_thread=function(){return(D._emscripten_async_run_in_main_thread=D.asm.pa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread=function(){return(D._emscripten_sync_run_in_main_thread=D.asm.qa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_0=function(){return(D._emscripten_sync_run_in_main_thread_0=D.asm.ra).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_1=function(){return(D._emscripten_sync_run_in_main_thread_1=D.asm.sa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_2=function(){return(D._emscripten_sync_run_in_main_thread_2=D.asm.ta).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_xprintf_varargs=function(){return(D._emscripten_sync_run_in_main_thread_xprintf_varargs=D.asm.ua).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_3=function(){return(D._emscripten_sync_run_in_main_thread_3=D.asm.va).apply(null,arguments)};var Ec=D._emscripten_sync_run_in_main_thread_4=function(){return(Ec=D._emscripten_sync_run_in_main_thread_4=D.asm.wa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_5=function(){return(D._emscripten_sync_run_in_main_thread_5=D.asm.xa).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_6=function(){return(D._emscripten_sync_run_in_main_thread_6=D.asm.ya).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_7=function(){return(D._emscripten_sync_run_in_main_thread_7=D.asm.za).apply(null,arguments)};
var Ub=D._emscripten_run_in_main_runtime_thread_js=function(){return(Ub=D._emscripten_run_in_main_runtime_thread_js=D.asm.Aa).apply(null,arguments)},$b=D.__emscripten_call_on_thread=function(){return($b=D.__emscripten_call_on_thread=D.asm.Ba).apply(null,arguments)};D._emscripten_tls_init=function(){return(D._emscripten_tls_init=D.asm.Ca).apply(null,arguments)};D.dynCall_viijii=function(){return(D.dynCall_viijii=D.asm.Da).apply(null,arguments)};
D.dynCall_iiji=function(){return(D.dynCall_iiji=D.asm.Ea).apply(null,arguments)};D.dynCall_jiji=function(){return(D.dynCall_jiji=D.asm.Fa).apply(null,arguments)};D.dynCall_iiiiiijj=function(){return(D.dynCall_iiiiiijj=D.asm.Ga).apply(null,arguments)};D.dynCall_iiiiij=function(){return(D.dynCall_iiiiij=D.asm.Ha).apply(null,arguments)};D.dynCall_iiiiijj=function(){return(D.dynCall_iiiiijj=D.asm.Ia).apply(null,arguments)};var cb=D._main_thread_futex=4638520;D.PThread=Q;D.PThread=Q;D._pthread_self=pc;
D.wasmMemory=m;D.ExitStatus=Hc;var Ic;function Hc(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}Pa=function Jc(){Ic||Kc();Ic||(Pa=Jc)};
function Kc(){function a(){if(!Ic&&(Ic=!0,D.calledRun=!0,!va)){Va(Ka);G||Va(La);na(D);if(D.onRuntimeInitialized)D.onRuntimeInitialized();if(!G){if(D.postRun)for("function"==typeof D.postRun&&(D.postRun=[D.postRun]);D.postRun.length;){var b=D.postRun.shift();Ma.unshift(b)}Va(Ma)}}}if(!(0<N)){if(!G){if(D.preRun)for("function"==typeof D.preRun&&(D.preRun=[D.preRun]);D.preRun.length;)Na();Va(Ja)}0<N||(D.setStatus?(D.setStatus("Running..."),setTimeout(function(){setTimeout(function(){D.setStatus("")},
1);a()},1)):a())}}D.run=Kc;if(D.preInit)for("function"==typeof D.preInit&&(D.preInit=[D.preInit]);0<D.preInit.length;)D.preInit.pop()();G||(noExitRuntime=!0);G?Q.Lb():Kc();

Binary file not shown.

View File

@ -17,7 +17,7 @@ function Da(a){return 2*a.length}function Ea(a,b){for(var c=0,d="";!(c>=b/4);){v
function Ga(a){for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&57343>=d&&++c;b+=4}return b}function Ha(a,b){e().set(a,b)}var n,aa,ba,ca,fa,ha,ia,ka,ma;function u(a){n=a;D.HEAP8=aa=new Int8Array(a);D.HEAP16=ca=new Int16Array(a);D.HEAP32=ha=new Int32Array(a);D.HEAPU8=ba=new Uint8Array(a);D.HEAPU16=fa=new Uint16Array(a);D.HEAPU32=ia=new Uint32Array(a);D.HEAPF32=ka=new Float32Array(a);D.HEAPF64=ma=new Float64Array(a)}var Ia=D.INITIAL_MEMORY||16777216;
if(G)m=D.wasmMemory,n=D.buffer;else if(D.wasmMemory)m=D.wasmMemory;else if(m=new WebAssembly.Memory({initial:Ia/65536,maximum:32768,shared:!0}),!(m.buffer instanceof SharedArrayBuffer))throw J("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag"),Error("bad memory");m&&(n=m.buffer);Ia=n.byteLength;u(n);var M,Ja=[],Ka=[],La=[],Ma=[];
function Na(){var a=D.preRun.shift();Ja.unshift(a)}var N=0,Oa=null,Pa=null;D.preloadedImages={};D.preloadedAudios={};function K(a){if(D.onAbort)D.onAbort(a);G&&console.error("Pthread aborting at "+Error().stack);J(a);va=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");oa(a);throw a;}function Qa(){var a=O;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var O="jxl_enc_mt_simd.wasm";
Qa()||(O=qa(O));function Ra(){try{if(ta)return new Uint8Array(ta);if(ra)return ra(O);throw"both async and sync fetching of the wasm failed";}catch(a){K(a)}}function Sa(){return ta||"function"!==typeof fetch?Promise.resolve().then(Ra):fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return Ra()})}var Ua={60549:function(a,b){setTimeout(function(){Ta(a,b)},0)},60627:function(){throw"Canceled!";}};
Qa()||(O=qa(O));function Ra(){try{if(ta)return new Uint8Array(ta);if(ra)return ra(O);throw"both async and sync fetching of the wasm failed";}catch(a){K(a)}}function Sa(){return ta||"function"!==typeof fetch?Promise.resolve().then(Ra):fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return Ra()})}var Ua={60165:function(a,b){setTimeout(function(){Ta(a,b)},0)},60243:function(){throw"Canceled!";}};
function Va(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(D);else{var c=b.Bb;"number"===typeof c?void 0===b.Va?M.get(c)():M.get(c)(b.Va):c(void 0===b.Va?null:b.Va)}}}function Wa(a,b,c){var d;-1!=a.indexOf("j")?d=c&&c.length?D["dynCall_"+a].apply(null,[b].concat(c)):D["dynCall_"+a].call(null,b):d=M.get(b).apply(null,c);return d}D.dynCall=Wa;var P=0,Xa=0,Ya=0;function Za(a,b,c){P=a|0;Ya=b|0;Xa=c|0}D.registerPthreadPtr=Za;
function $a(a,b){if(0>=a||a>e().length||a&1||0>b)return-28;if(0==b)return 0;2147483647<=b&&(b=Infinity);var c=Atomics.load(A(),Q.rb>>2),d=0;if(c==a&&Atomics.compareExchange(A(),Q.rb>>2,c,0)==c&&(--b,d=1,0>=b))return 1;a=Atomics.notify(A(),a>>2,b);if(0<=a)return a+d;throw"Atomics.notify returned an unexpected value "+a;}D._emscripten_futex_wake=$a;
function ab(a){if(G)throw"Internal Error! cleanupThread() can only ever be called from main application thread!";if(!a)throw"Internal Error! Null pthread_ptr in cleanupThread!";A()[a+12>>2]=0;(a=Q.Oa[a])&&Q.bb(a.worker)}
@ -78,10 +78,10 @@ r){if("number"!==typeof r&&"boolean"!==typeof r)throw new TypeError('Cannot conv
Uint32Array,Float32Array,Float64Array][b];c=W(c);V(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{Gb:!0})},u:function(a,b){b=W(b);var c="std::string"===b;V(a,{name:b,fromWireType:function(d){var f=C()[d>>2];if(c)for(var g=d+4,l=0;l<=f;++l){var k=d+4+l;if(l==f||0==v()[k]){g=L(g,k-g);if(void 0===q)var q=g;else q+=String.fromCharCode(0),q+=g;g=k+1}}else{q=Array(f);for(l=0;l<f;++l)q[l]=String.fromCharCode(v()[d+4+l]);q=q.join("")}S(d);return q},toWireType:function(d,f){f instanceof
ArrayBuffer&&(f=new Uint8Array(f));var g="string"===typeof f;g||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array||X("Cannot pass non-string to std::string");var l=(c&&g?function(){return Aa(f)}:function(){return f.length})(),k=R(4+l+1);C()[k>>2]=l;if(c&&g)za(f,k+4,l+1);else if(g)for(g=0;g<l;++g){var q=f.charCodeAt(g);255<q&&(S(k),X("String has UTF-16 code units that do not fit in 8 bits"));v()[k+4+g]=q}else for(g=0;g<l;++g)v()[k+4+g]=f[g];null!==d&&d.push(S,k);return k},
argPackAdvance:8,readValueFromPointer:nb,Pa:function(d){S(d)}})},q:function(a,b,c){c=W(c);if(2===b){var d=Ba;var f=Ca;var g=Da;var l=function(){return ea()};var k=1}else 4===b&&(d=Ea,f=Fa,g=Ga,l=function(){return C()},k=2);V(a,{name:c,fromWireType:function(q){for(var t=C()[q>>2],r=l(),w,z=q+4,h=0;h<=t;++h){var p=q+4+h*b;if(h==t||0==r[p>>k])z=d(z,p-z),void 0===w?w=z:(w+=String.fromCharCode(0),w+=z),z=p+b}S(q);return w},toWireType:function(q,t){"string"!==typeof t&&X("Cannot pass non-string to C++ string type "+
c);var r=g(t),w=R(4+r+b);C()[w>>2]=r>>k;f(t,w+4,r+b);null!==q&&q.push(S,w);return w},argPackAdvance:8,readValueFromPointer:nb,Pa:function(q){S(q)}})},x:function(a,b,c,d,f,g){lb[a]={name:W(b),Ob:Hb(c,d),Pb:Hb(f,g),ob:[]}},k:function(a,b,c,d,f,g,l,k,q,t){lb[a].ob.push({Ab:W(b),Fb:c,Db:Hb(d,f),Eb:g,Yb:l,Xb:Hb(k,q),Zb:t})},T:function(a,b){b=W(b);V(a,{oc:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},H:function(a,b){if(a==b)postMessage({cmd:"processQueuedMainThreadWork"});
c);var r=g(t),w=R(4+r+b);C()[w>>2]=r>>k;f(t,w+4,r+b);null!==q&&q.push(S,w);return w},argPackAdvance:8,readValueFromPointer:nb,Pa:function(q){S(q)}})},x:function(a,b,c,d,f,g){lb[a]={name:W(b),Ob:Hb(c,d),Pb:Hb(f,g),ob:[]}},l:function(a,b,c,d,f,g,l,k,q,t){lb[a].ob.push({Ab:W(b),Fb:c,Db:Hb(d,f),Eb:g,Yb:l,Xb:Hb(k,q),Zb:t})},T:function(a,b){b=W(b);V(a,{oc:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},H:function(a,b){if(a==b)postMessage({cmd:"processQueuedMainThreadWork"});
else if(G)postMessage({targetThread:a,cmd:"processThreadQueue"});else{a=(a=Q.Oa[a])&&a.worker;if(!a)return;a.postMessage({cmd:"processThreadQueue"})}return 1},m:yb,W:function(a){if(0===a)return zb(Ob());var b=Nb[a];a=void 0===b?W(a):b;return zb(Ob()[a])},V:function(a){4<a&&(Y[a].jb+=1)},y:function(a,b,c,d){a||X("Cannot use deleted val. handle = "+a);a=Y[a].value;var f=Qb[b];if(!f){f="";for(var g=0;g<b;++g)f+=(0!==g?", ":"")+"arg"+g;var l="return function emval_allocator_"+b+"(constructor, argTypes, args) {\n";
for(g=0;g<b;++g)l+="var argType"+g+" = requireRegisteredType(Module['HEAP32'][(argTypes >>> 2) + "+g+'], "parameter '+g+'");\nvar arg'+g+" = argType"+g+".readValueFromPointer(args);\nargs += argType"+g+"['argPackAdvance'];\n";f=(new Function("requireRegisteredType","Module","__emval_register",l+("var obj = new constructor("+f+");\nreturn __emval_register(obj);\n}\n")))(Pb,D,zb);Qb[b]=f}return f(a,c,d)},b:function(){K()},n:function(a,b,c){Wb.length=0;var d;for(c>>=2;d=v()[b++];)(d=105>d)&&c&1&&c++,
Wb.push(d?la()[c++>>1]:A()[c]),++c;return Ua[a].apply(null,Wb)},J:function(){},r:function(){},f:Rb,g:$a,d:hb,p:function(){return Ya|0},o:function(){return Xa|0},C:function(a,b,c){v().copyWithin(a,b,b+c)},E:function(a,b,c){Vb.length=b;c>>=3;for(var d=0;d<b;d++)Vb[d]=la()[c+d];return(0>a?Ua[-a-1]:Cc[a]).apply(null,Vb)},l:function(a){a>>>=0;var b=v().length;if(a<=b||2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%
Wb.push(d?la()[c++>>1]:A()[c]),++c;return Ua[a].apply(null,Wb)},J:function(){},r:function(){},f:Rb,g:$a,d:hb,p:function(){return Ya|0},o:function(){return Xa|0},C:function(a,b,c){v().copyWithin(a,b,b+c)},E:function(a,b,c){Vb.length=b;c>>=3;for(var d=0;d<b;d++)Vb[d]=la()[c+d];return(0>a?Ua[-a-1]:Cc[a]).apply(null,Vb)},k:function(a){a>>>=0;var b=v().length;if(a<=b||2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%
65536);a:{try{m.grow(Math.min(2147483648,d)-n.byteLength+65535>>>16);u(m.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},F:function(a,b,c){return Yb(a)?Zb(a,b,c):ac(a,b,c)},e:function(){},G:function(a,b){var c={};b>>=2;c.alpha=!!A()[b];c.depth=!!A()[b+1];c.stencil=!!A()[b+2];c.antialias=!!A()[b+3];c.premultipliedAlpha=!!A()[b+4];c.preserveDrawingBuffer=!!A()[b+5];var d=A()[b+6];c.powerPreference=gc[d];c.failIfMajorPerformanceCaveat=!!A()[b+7];c.Mb=A()[b+8];c.qc=A()[b+9];c.nb=A()[b+
10];c.zb=A()[b+11];c.tc=A()[b+12];c.uc=A()[b+13];a=Yb(a);!a||c.zb?c=0:(a=a.getContext("webgl",c))?(b=R(8),A()[b+4>>2]=P|0,d={nc:b,attributes:c,version:c.Mb,Za:a},a.canvas&&(a.canvas.$a=d),("undefined"===typeof c.nb||c.nb)&&ec(d),c=b):c=0;return c},O:function(a,b){var c=0;ic().forEach(function(d,f){var g=b+c;f=A()[a+4*f>>2]=g;for(g=0;g<d.length;++g)e()[f++>>0]=d.charCodeAt(g);e()[f>>0]=0;c+=d.length+1});return 0},P:function(a,b){var c=ic();A()[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+
1});A()[b>>2]=d;return 0},Q:lc,z:mc,s:nc,B:function(){Q.Kb()},a:m||D.wasmMemory,D:ib,U:function(a,b,c,d){if("undefined"===typeof SharedArrayBuffer)return J("Current environment does not support SharedArrayBuffer, pthreads are not available!"),6;if(!a)return J("pthread_create called with a null thread pointer!"),28;var f=[];if(G&&0===f.length)return Ec(687865856,a,b,c,d);var g=0,l=0,k=0,q=0;if(b){var t=A()[b>>2];t+=81920;g=A()[b+8>>2];l=0!==A()[b+12>>2];if(0===A()[b+16>>2]){var r=A()[b+20>>2],w=A()[b+
@ -90,16 +90,17 @@ t,wa(0<g));r=R(232);for(w=0;58>w;++w)C()[(r>>2)+w]=0;A()[a>>2]=r;A()[r+12>>2]=r;
(function(){function a(f,g){D.asm=f.exports;M=D.asm.Y;ua=g;if(!G){var l=Q.Ma.length;Q.Ma.forEach(function(k){Q.qb(k,function(){if(!--l&&(N--,D.monitorRunDependencies&&D.monitorRunDependencies(N),0==N&&(null!==Oa&&(clearInterval(Oa),Oa=null),Pa))){var q=Pa;Pa=null;q()}})})}}function b(f){a(f.instance,f.module)}function c(f){return Sa().then(function(g){return WebAssembly.instantiate(g,d)}).then(f,function(g){J("failed to asynchronously prepare wasm: "+g);K(g)})}var d={a:Gc};G||(wa(!G,"addRunDependency cannot be used in a pthread worker"),
N++,D.monitorRunDependencies&&D.monitorRunDependencies(N));if(D.instantiateWasm)try{return D.instantiateWasm(d,a)}catch(f){return J("Module.instantiateWasm callback failed with error: "+f),!1}(function(){return ta||"function"!==typeof WebAssembly.instantiateStreaming||Qa()||"function"!==typeof fetch?c(b):fetch(O,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,d).then(b,function(g){J("wasm streaming compile failed: "+g);J("falling back to ArrayBuffer instantiation");
return c(b)})})})().catch(oa);return{}})();var Dc=D.___wasm_call_ctors=function(){return(Dc=D.___wasm_call_ctors=D.asm.Z).apply(null,arguments)},R=D._malloc=function(){return(R=D._malloc=D.asm._).apply(null,arguments)},S=D._free=function(){return(S=D._free=D.asm.$).apply(null,arguments)},zc=D.___errno_location=function(){return(zc=D.___errno_location=D.asm.aa).apply(null,arguments)},Kb=D.___getTypeName=function(){return(Kb=D.___getTypeName=D.asm.ba).apply(null,arguments)};
D.___embind_register_native_and_builtin_types=function(){return(D.___embind_register_native_and_builtin_types=D.asm.ca).apply(null,arguments)};var oc=D._emscripten_get_global_libc=function(){return(oc=D._emscripten_get_global_libc=D.asm.da).apply(null,arguments)};D.___em_js__initPthreadsJS=function(){return(D.___em_js__initPthreadsJS=D.asm.ea).apply(null,arguments)};
var Sb=D.stackSave=function(){return(Sb=D.stackSave=D.asm.fa).apply(null,arguments)},gb=D.stackRestore=function(){return(gb=D.stackRestore=D.asm.ga).apply(null,arguments)},Tb=D.stackAlloc=function(){return(Tb=D.stackAlloc=D.asm.ha).apply(null,arguments)},Fc=D._memalign=function(){return(Fc=D._memalign=D.asm.ia).apply(null,arguments)};D._emscripten_main_browser_thread_id=function(){return(D._emscripten_main_browser_thread_id=D.asm.ja).apply(null,arguments)};
var db=D.___pthread_tsd_run_dtors=function(){return(db=D.___pthread_tsd_run_dtors=D.asm.ka).apply(null,arguments)},eb=D._emscripten_main_thread_process_queued_calls=function(){return(eb=D._emscripten_main_thread_process_queued_calls=D.asm.la).apply(null,arguments)};D._emscripten_current_thread_process_queued_calls=function(){return(D._emscripten_current_thread_process_queued_calls=D.asm.ma).apply(null,arguments)};
var bb=D._emscripten_register_main_browser_thread_id=function(){return(bb=D._emscripten_register_main_browser_thread_id=D.asm.na).apply(null,arguments)},Ta=D._do_emscripten_dispatch_to_thread=function(){return(Ta=D._do_emscripten_dispatch_to_thread=D.asm.oa).apply(null,arguments)};D._emscripten_async_run_in_main_thread=function(){return(D._emscripten_async_run_in_main_thread=D.asm.pa).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread=function(){return(D._emscripten_sync_run_in_main_thread=D.asm.qa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_0=function(){return(D._emscripten_sync_run_in_main_thread_0=D.asm.ra).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_1=function(){return(D._emscripten_sync_run_in_main_thread_1=D.asm.sa).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_2=function(){return(D._emscripten_sync_run_in_main_thread_2=D.asm.ta).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_xprintf_varargs=function(){return(D._emscripten_sync_run_in_main_thread_xprintf_varargs=D.asm.ua).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_3=function(){return(D._emscripten_sync_run_in_main_thread_3=D.asm.va).apply(null,arguments)};
var Ec=D._emscripten_sync_run_in_main_thread_4=function(){return(Ec=D._emscripten_sync_run_in_main_thread_4=D.asm.wa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_5=function(){return(D._emscripten_sync_run_in_main_thread_5=D.asm.xa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_6=function(){return(D._emscripten_sync_run_in_main_thread_6=D.asm.ya).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_7=function(){return(D._emscripten_sync_run_in_main_thread_7=D.asm.za).apply(null,arguments)};var Ub=D._emscripten_run_in_main_runtime_thread_js=function(){return(Ub=D._emscripten_run_in_main_runtime_thread_js=D.asm.Aa).apply(null,arguments)},$b=D.__emscripten_call_on_thread=function(){return($b=D.__emscripten_call_on_thread=D.asm.Ba).apply(null,arguments)};D._emscripten_tls_init=function(){return(D._emscripten_tls_init=D.asm.Ca).apply(null,arguments)};
D.dynCall_viijii=function(){return(D.dynCall_viijii=D.asm.Da).apply(null,arguments)};D.dynCall_iiji=function(){return(D.dynCall_iiji=D.asm.Ea).apply(null,arguments)};D.dynCall_jiji=function(){return(D.dynCall_jiji=D.asm.Fa).apply(null,arguments)};D.dynCall_iiiiiijj=function(){return(D.dynCall_iiiiiijj=D.asm.Ga).apply(null,arguments)};D.dynCall_iiiiij=function(){return(D.dynCall_iiiiij=D.asm.Ha).apply(null,arguments)};D.dynCall_iiiiijj=function(){return(D.dynCall_iiiiijj=D.asm.Ia).apply(null,arguments)};
var cb=D._main_thread_futex=75048;D.PThread=Q;D.PThread=Q;D._pthread_self=pc;D.wasmMemory=m;D.ExitStatus=Hc;var Ic;function Hc(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}Pa=function Jc(){Ic||Kc();Ic||(Pa=Jc)};
D.___embind_register_native_and_builtin_types=function(){return(D.___embind_register_native_and_builtin_types=D.asm.ca).apply(null,arguments)};D.___em_js__initPthreadsJS=function(){return(D.___em_js__initPthreadsJS=D.asm.da).apply(null,arguments)};
var oc=D._emscripten_get_global_libc=function(){return(oc=D._emscripten_get_global_libc=D.asm.ea).apply(null,arguments)},Sb=D.stackSave=function(){return(Sb=D.stackSave=D.asm.fa).apply(null,arguments)},gb=D.stackRestore=function(){return(gb=D.stackRestore=D.asm.ga).apply(null,arguments)},Tb=D.stackAlloc=function(){return(Tb=D.stackAlloc=D.asm.ha).apply(null,arguments)},Fc=D._memalign=function(){return(Fc=D._memalign=D.asm.ia).apply(null,arguments)};
D._emscripten_main_browser_thread_id=function(){return(D._emscripten_main_browser_thread_id=D.asm.ja).apply(null,arguments)};var db=D.___pthread_tsd_run_dtors=function(){return(db=D.___pthread_tsd_run_dtors=D.asm.ka).apply(null,arguments)},eb=D._emscripten_main_thread_process_queued_calls=function(){return(eb=D._emscripten_main_thread_process_queued_calls=D.asm.la).apply(null,arguments)};
D._emscripten_current_thread_process_queued_calls=function(){return(D._emscripten_current_thread_process_queued_calls=D.asm.ma).apply(null,arguments)};var bb=D._emscripten_register_main_browser_thread_id=function(){return(bb=D._emscripten_register_main_browser_thread_id=D.asm.na).apply(null,arguments)},Ta=D._do_emscripten_dispatch_to_thread=function(){return(Ta=D._do_emscripten_dispatch_to_thread=D.asm.oa).apply(null,arguments)};
D._emscripten_async_run_in_main_thread=function(){return(D._emscripten_async_run_in_main_thread=D.asm.pa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread=function(){return(D._emscripten_sync_run_in_main_thread=D.asm.qa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_0=function(){return(D._emscripten_sync_run_in_main_thread_0=D.asm.ra).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_1=function(){return(D._emscripten_sync_run_in_main_thread_1=D.asm.sa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_2=function(){return(D._emscripten_sync_run_in_main_thread_2=D.asm.ta).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_xprintf_varargs=function(){return(D._emscripten_sync_run_in_main_thread_xprintf_varargs=D.asm.ua).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_3=function(){return(D._emscripten_sync_run_in_main_thread_3=D.asm.va).apply(null,arguments)};var Ec=D._emscripten_sync_run_in_main_thread_4=function(){return(Ec=D._emscripten_sync_run_in_main_thread_4=D.asm.wa).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_5=function(){return(D._emscripten_sync_run_in_main_thread_5=D.asm.xa).apply(null,arguments)};
D._emscripten_sync_run_in_main_thread_6=function(){return(D._emscripten_sync_run_in_main_thread_6=D.asm.ya).apply(null,arguments)};D._emscripten_sync_run_in_main_thread_7=function(){return(D._emscripten_sync_run_in_main_thread_7=D.asm.za).apply(null,arguments)};
var Ub=D._emscripten_run_in_main_runtime_thread_js=function(){return(Ub=D._emscripten_run_in_main_runtime_thread_js=D.asm.Aa).apply(null,arguments)},$b=D.__emscripten_call_on_thread=function(){return($b=D.__emscripten_call_on_thread=D.asm.Ba).apply(null,arguments)};D._emscripten_tls_init=function(){return(D._emscripten_tls_init=D.asm.Ca).apply(null,arguments)};D.dynCall_viijii=function(){return(D.dynCall_viijii=D.asm.Da).apply(null,arguments)};
D.dynCall_iiji=function(){return(D.dynCall_iiji=D.asm.Ea).apply(null,arguments)};D.dynCall_jiji=function(){return(D.dynCall_jiji=D.asm.Fa).apply(null,arguments)};D.dynCall_iiiiiijj=function(){return(D.dynCall_iiiiiijj=D.asm.Ga).apply(null,arguments)};D.dynCall_iiiiij=function(){return(D.dynCall_iiiiij=D.asm.Ha).apply(null,arguments)};D.dynCall_iiiiijj=function(){return(D.dynCall_iiiiijj=D.asm.Ia).apply(null,arguments)};var cb=D._main_thread_futex=4638632;D.PThread=Q;D.PThread=Q;D._pthread_self=pc;
D.wasmMemory=m;D.ExitStatus=Hc;var Ic;function Hc(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}Pa=function Jc(){Ic||Kc();Ic||(Pa=Jc)};
function Kc(){function a(){if(!Ic&&(Ic=!0,D.calledRun=!0,!va)){Va(Ka);G||Va(La);na(D);if(D.onRuntimeInitialized)D.onRuntimeInitialized();if(!G){if(D.postRun)for("function"==typeof D.postRun&&(D.postRun=[D.postRun]);D.postRun.length;){var b=D.postRun.shift();Ma.unshift(b)}Va(Ma)}}}if(!(0<N)){if(!G){if(D.preRun)for("function"==typeof D.preRun&&(D.preRun=[D.preRun]);D.preRun.length;)Na();Va(Ja)}0<N||(D.setStatus?(D.setStatus("Running..."),setTimeout(function(){setTimeout(function(){D.setStatus("")},
1);a()},1)):a())}}D.run=Kc;if(D.preInit)for("function"==typeof D.preInit&&(D.preInit=[D.preInit]);0<D.preInit.length;)D.preInit.pop()();G||(noExitRuntime=!0);G?Q.Lb():Kc();

Binary file not shown.

View File

@ -50,9 +50,9 @@ v.push(q+"}\n");k=$a(v).apply(null,p);l=b-1;if(!f.hasOwnProperty(m))throw new Qa
readValueFromPointer:d},{ka:!0})},k:function(a,b){b=V(b);var c="std::string"===b;T(a,{name:b,fromWireType:function(d){var g=J[d>>2];if(c)for(var h=d+4,n=0;n<=g;++n){var m=d+4+n;if(n==g||0==D[m]){h=ma(h,m-h);if(void 0===k)var k=h;else k+=String.fromCharCode(0),k+=h;h=m+1}}else{k=Array(g);for(n=0;n<g;++n)k[n]=String.fromCharCode(D[d+4+n]);k=k.join("")}Z(d);return k},toWireType:function(d,g){g instanceof ArrayBuffer&&(g=new Uint8Array(g));var h="string"===typeof g;h||g instanceof Uint8Array||g instanceof
Uint8ClampedArray||g instanceof Int8Array||W("Cannot pass non-string to std::string");var n=(c&&h?function(){return oa(g)}:function(){return g.length})(),m=Bb(4+n+1);J[m>>2]=n;if(c&&h)na(g,D,m+4,n+1);else if(h)for(h=0;h<n;++h){var k=g.charCodeAt(h);255<k&&(Z(m),W("String has UTF-16 code units that do not fit in 8 bits"));D[m+4+h]=k}else for(h=0;h<n;++h)D[m+4+h]=g[h];null!==d&&d.push(Z,m);return m},argPackAdvance:8,readValueFromPointer:La,T:function(d){Z(d)}})},h:function(a,b,c){c=V(c);if(2===b){var d=
qa;var g=ra;var h=sa;var n=function(){return E};var m=1}else 4===b&&(d=ta,g=ua,h=va,n=function(){return J},m=2);T(a,{name:c,fromWireType:function(k){for(var q=J[k>>2],p=n(),r,x=k+4,e=0;e<=q;++e){var l=k+4+e*b;if(e==q||0==p[l>>m])x=d(x,l-x),void 0===r?r=x:(r+=String.fromCharCode(0),r+=x),x=l+b}Z(k);return r},toWireType:function(k,q){"string"!==typeof q&&W("Cannot pass non-string to C++ string type "+c);var p=h(q),r=Bb(4+p+b);J[r>>2]=p>>m;g(q,r+4,p+b);null!==k&&k.push(Z,r);return r},argPackAdvance:8,
readValueFromPointer:La,T:function(k){Z(k)}})},n:function(a,b,c,d,g,h){Q[a]={name:V(b),ma:Y(c,d),na:Y(g,h),ba:[]}},e:function(a,b,c,d,g,h,n,m,k,q){Q[a].ba.push({fa:V(b),ja:c,ha:Y(d,g),ia:h,ua:n,ta:Y(m,k),va:q})},A:function(a,b){b=V(b);T(a,{Aa:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},g:Wa,C:function(a){if(0===a)return Xa(kb());var b=jb[a];a=void 0===b?V(a):b;return Xa(kb()[a])},B:function(a){4<a&&(X[a].aa+=1)},o:function(a,b,c,d){a||W("Cannot use deleted val. handle = "+
readValueFromPointer:La,T:function(k){Z(k)}})},n:function(a,b,c,d,g,h){Q[a]={name:V(b),ma:Y(c,d),na:Y(g,h),ba:[]}},f:function(a,b,c,d,g,h,n,m,k,q){Q[a].ba.push({fa:V(b),ja:c,ha:Y(d,g),ia:h,ua:n,ta:Y(m,k),va:q})},A:function(a,b){b=V(b);T(a,{Aa:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},g:Wa,C:function(a){if(0===a)return Xa(kb());var b=jb[a];a=void 0===b?V(a):b;return Xa(kb()[a])},B:function(a){4<a&&(X[a].aa+=1)},o:function(a,b,c,d){a||W("Cannot use deleted val. handle = "+
a);a=X[a].value;var g=mb[b];if(!g){g="";for(var h=0;h<b;++h)g+=(0!==h?", ":"")+"arg"+h;var n="return function emval_allocator_"+b+"(constructor, argTypes, args) {\n";for(h=0;h<b;++h)n+="var argType"+h+" = requireRegisteredType(Module['HEAP32'][(argTypes >>> 2) + "+h+'], "parameter '+h+'");\nvar arg'+h+" = argType"+h+".readValueFromPointer(args);\nargs += argType"+h+"['argPackAdvance'];\n";g=(new Function("requireRegisteredType","Module","__emval_register",n+("var obj = new constructor("+g+");\nreturn __emval_register(obj);\n}\n")))(lb,
f,Xa);mb[b]=g}return g(a,c,d)},b:function(){y()},t:function(a,b,c){D.copyWithin(a,b,b+c)},f:function(a){a>>>=0;var b=D.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{C.grow(Math.min(2147483648,d)-H.byteLength+65535>>>16);ya(C.buffer);var g=1;break a}catch(h){}g=void 0}if(g)return!0}return!1},v:function(a,b){var c=0;ob().forEach(function(d,g){var h=b+c;g=G[a+4*g>>2]=h;for(h=0;h<d.length;++h)I[g++>>
f,Xa);mb[b]=g}return g(a,c,d)},b:function(){y()},t:function(a,b,c){D.copyWithin(a,b,b+c)},e:function(a){a>>>=0;var b=D.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{C.grow(Math.min(2147483648,d)-H.byteLength+65535>>>16);ya(C.buffer);var g=1;break a}catch(h){}g=void 0}if(g)return!0}return!1},v:function(a,b){var c=0;ob().forEach(function(d,g){var h=b+c;g=G[a+4*g>>2]=h;for(h=0;h<d.length;++h)I[g++>>
0]=d.charCodeAt(h);I[g>>0]=0;c+=d.length+1});return 0},w:function(a,b){var c=ob();G[a>>2]=c.length;var d=0;c.forEach(function(g){d+=g.length+1});G[b>>2]=d;return 0},x:function(){return 0},r:function(){},i:function(a,b,c,d){for(var g=0,h=0;h<c;h++){for(var n=G[b+8*h>>2],m=G[b+(8*h+4)>>2],k=0;k<m;k++){var q=D[n+k],p=qb[a];if(0===q||10===q){q=1===a?ja:z;var r;for(r=0;p[r]&&!(NaN<=r);)++r;r=la.decode(p.subarray?p.subarray(0,r):new Uint8Array(p.slice(0,r)));q(r);p.length=0}else p.push(q)}g+=m}G[d>>2]=
g;return 0},a:C,s:function(){},u:function(a,b,c,d){return wb(a,b,c,d)}};
(function(){function a(g){f.asm=g.exports;K=f.asm.E;L--;f.monitorRunDependencies&&f.monitorRunDependencies(L);0==L&&(null!==Fa&&(clearInterval(Fa),Fa=null),M&&(g=M,M=null,g()))}function b(g){a(g.instance)}function c(g){return Promise.resolve().then(Ia).then(function(h){return WebAssembly.instantiate(h,d)}).then(g,function(h){z("failed to asynchronously prepare wasm: "+h);y(h)})}var d={a:Cb};L++;f.monitorRunDependencies&&f.monitorRunDependencies(L);if(f.instantiateWasm)try{return f.instantiateWasm(d,

Binary file not shown.

View File

@ -1,47 +1,51 @@
CODEC_URL := https://github.com/mozilla/mozjpeg/archive/v3.3.1.tar.gz
CODEC_DIR := node_modules/mozjpeg
CODEC_BUILD_DIR := $(CODEC_DIR)/build
CODEC_OUT_RELATIVE := .libs/libjpeg.a rdswitch.o
CODEC_OUT := $(addprefix $(CODEC_DIR)/, $(CODEC_OUT_RELATIVE))
ENVIRONMENT = worker
CODEC_OUT := $(addprefix $(CODEC_BUILD_DIR)/, $(CODEC_OUT_RELATIVE))
OUT_JS := enc/mozjpeg_enc.js enc/mozjpeg_node_enc.js dec/mozjpeg_node_dec.js
OUT_WASM := $(OUT_JS:.js=.wasm)
OUT_WASM := enc/mozjpeg_enc.wasm
OPTIMIZE := 3
override CC = $(WASI_SDK_PREFIX)/bin/clang
override CXX = $(WASI_SDK_PREFIX)/bin/clang++
override CXXFLAGS += --sysroot=$(WASI_SDK_PREFIX)/share/wasi-sysroot -O$(OPTIMIZE)
override CFLAGS += --sysroot=$(WASI_SDK_PREFIX)/share/wasi-sysroot -O$(OPTIMIZE)
override RANLIB = $(WASI_SDK_PREFIX)/bin/ranlib
# Without this export, configure doesnt seem to see $CC and $CFLAGS
export
.PHONY: all clean
all: $(OUT_JS)
all: $(OUT_WASM)
# Define dependencies for all variations of build artifacts.
$(filter enc/%,$(OUT_JS)): enc/mozjpeg_enc.cpp
$(filter dec/%,$(OUT_JS)): dec/mozjpeg_dec.cpp
enc/mozjpeg_node_enc.js dec/mozjpeg_node_dec.js: ENVIRONMENT = node
%.js: $(CODEC_OUT)
$(OUT_WASM): $(CODEC_OUT)
$(CXX) \
-I $(CODEC_BUILD_DIR) \
-I $(CODEC_DIR) \
${CXXFLAGS} \
${LDFLAGS} \
--closure 1 \
--bind \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s TEXTDECODER=2 \
-s ENVIRONMENT=$(ENVIRONMENT) \
-s EXPORT_ES6=1 \
-o $@ \
$+
enc/mozjpeg_enc.cpp \
$(CODEC_OUT)
$(BINARYEN_PREFIX)/bin/wasm-opt --strip-debug --strip-dwarf --strip-producers --strip-target-features -O4 -o $(OUT_WASM) $(OUT_WASM)
# This one is a bit special: there is no rule for .libs/libjpeg.a
# so we use libjpeg.la which implicitly builds that one instead.
$(CODEC_DIR)/.libs/libjpeg.a: $(CODEC_DIR)/Makefile
$(MAKE) -C $(CODEC_DIR) libjpeg.la
$(CODEC_BUILD_DIR)/.libs/libjpeg.a: $(CODEC_BUILD_DIR)/Makefile
$(MAKE) -C $(CODEC_BUILD_DIR) libjpeg.la
$(CODEC_DIR)/rdswitch.o: $(CODEC_DIR)/Makefile
$(MAKE) -C $(CODEC_DIR) rdswitch.o
$(CODEC_BUILD_DIR)/rdswitch.o: $(CODEC_BUILD_DIR)/Makefile
$(MAKE) -C $(CODEC_BUILD_DIR) rdswitch.o
$(CODEC_DIR)/Makefile: $(CODEC_DIR)/configure
cd $(CODEC_DIR) && ./configure \
$(CODEC_BUILD_DIR)/Makefile: $(CODEC_DIR)/configure
mkdir -p $(CODEC_BUILD_DIR) && \
cd $(CODEC_BUILD_DIR) && \
../configure \
--target=wasm32-wasi \
--host=wasm32-wasi \
--disable-shared \
--without-turbojpeg \
--without-simd \
@ -59,7 +63,10 @@ $(CODEC_DIR)/configure.ac: $(CODEC_DIR)
$(CODEC_DIR):
mkdir -p $@
curl -sL $(CODEC_URL) | tar xz --strip 1 -C $@
cp $(WASI_SDK_PREFIX)/share/misc/config.* $(CODEC_DIR)
# ^ Monkey-path autoconf files as Ubuntus autoconf tools are too old
# to recognize WASI
clean:
$(RM) $(OUT_JS) $(OUT_WASM)
$(MAKE) -C $(CODEC_DIR) clean
$(RM) $(OUT_WASM)
$(RM) -r $(CODEC_BUILD_DIR)

View File

@ -1,10 +1,6 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <inttypes.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <string>
#include "config.h"
#include "jpeglib.h"
@ -12,14 +8,6 @@ extern "C" {
#include "cdjpeg.h"
}
using namespace emscripten;
// MozJPEG doesnt expose a numeric version, so I have to do some fun C macro
// hackery to turn it into a string. More details here:
// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
#define xstr(s) str(s)
#define str(s) #s
struct MozJpegOptions {
int quality;
bool baseline;
@ -39,26 +27,17 @@ struct MozJpegOptions {
int chroma_quality;
};
int version() {
char buffer[] = xstr(MOZJPEG_VERSION);
int version = 0;
int last_index = 0;
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == '.') {
buffer[i] = '\0';
version = version << 8 | atoi(&buffer[last_index]);
buffer[i] = '.';
last_index = i + 1;
}
}
version = version << 8 | atoi(&buffer[last_index]);
return version;
}
thread_local struct MozJpegOptions opts = {};
thread_local const val Uint8Array = val::global("Uint8Array");
struct DynArray {
size_t size;
uint8_t* ptr;
};
val encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts) {
uint8_t* image_buffer = (uint8_t*)image_in.c_str();
__attribute__((export_name("encode"))) intptr_t* encode(uintptr_t* image_in,
int image_width,
int image_height) {
uint8_t* image_buffer = reinterpret_cast<uint8_t*>(image_in);
// The code below is basically the `write_JPEG_file` function from
// https://github.com/mozilla/mozjpeg/blob/master/example.c
@ -141,7 +120,6 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_TRELLIS_EOB_OPT, opts.trellis_opt_zero);
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_TRELLIS_Q_OPT, opts.trellis_opt_table);
jpeg_c_set_int_param(&cinfo, JINT_TRELLIS_NUM_LOOPS, opts.trellis_loops);
jpeg_c_set_int_param(&cinfo, JINT_DC_SCAN_OPT_MODE, 0);
// A little hacky to build a string for this, but it means we can use
// set_quality_ratings which does some useful heuristic stuff.
@ -200,35 +178,47 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
/* Step 7: release JPEG compression object */
auto js_result = Uint8Array.new_(typed_memory_view(size, output));
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
free(output);
/* And we're done! */
return js_result;
auto result = new DynArray();
result->size = size;
result->ptr = output;
return reinterpret_cast<intptr_t*>(result);
}
EMSCRIPTEN_BINDINGS(my_module) {
value_object<MozJpegOptions>("MozJpegOptions")
.field("quality", &MozJpegOptions::quality)
.field("baseline", &MozJpegOptions::baseline)
.field("arithmetic", &MozJpegOptions::arithmetic)
.field("progressive", &MozJpegOptions::progressive)
.field("optimize_coding", &MozJpegOptions::optimize_coding)
.field("smoothing", &MozJpegOptions::smoothing)
.field("color_space", &MozJpegOptions::color_space)
.field("quant_table", &MozJpegOptions::quant_table)
.field("trellis_multipass", &MozJpegOptions::trellis_multipass)
.field("trellis_opt_zero", &MozJpegOptions::trellis_opt_zero)
.field("trellis_opt_table", &MozJpegOptions::trellis_opt_table)
.field("trellis_loops", &MozJpegOptions::trellis_loops)
.field("chroma_subsample", &MozJpegOptions::chroma_subsample)
.field("auto_subsample", &MozJpegOptions::auto_subsample)
.field("separate_chroma_quality", &MozJpegOptions::separate_chroma_quality)
.field("chroma_quality", &MozJpegOptions::chroma_quality);
function("version", &version);
function("encode", &encode);
__attribute__((export_name("alloc"))) uintptr_t* alloc(size_t size) {
return reinterpret_cast<uintptr_t*>(malloc(size));
}
__attribute__((export_name("dealloc"))) void dealloc(uintptr_t* ptr) {
return free(ptr);
}
#define MAKE_SETTER(type, name) \
__attribute__((export_name("set_opts_" #name))) void set_opts_##name(type val) { \
opts.name = val; \
}
MAKE_SETTER(int, quality);
MAKE_SETTER(bool, baseline);
MAKE_SETTER(bool, arithmetic);
MAKE_SETTER(bool, progressive);
MAKE_SETTER(bool, optimize_coding);
MAKE_SETTER(int, smoothing);
MAKE_SETTER(int, color_space);
MAKE_SETTER(int, quant_table);
MAKE_SETTER(bool, trellis_multipass);
MAKE_SETTER(bool, trellis_opt_zero);
MAKE_SETTER(bool, trellis_opt_table);
MAKE_SETTER(int, trellis_loops);
MAKE_SETTER(bool, auto_subsample);
MAKE_SETTER(int, chroma_subsample);
MAKE_SETTER(bool, separate_chroma_quality);
MAKE_SETTER(int, chroma_quality);
// To satisfy WASI SDK compiler and make sure that init code runs.
int main() {
return 0;
}

View File

@ -23,15 +23,29 @@ export interface EncodeOptions {
chroma_quality: number;
}
export interface MozJPEGModule extends EmscriptenWasm.Module {
export interface MozJPEGModuleExports {
memory: WebAssembly.Memory;
alloc(size: number): number;
dealloc(ptr: number): void;
encode(
data: BufferSource,
data: number,
width: number,
height: number,
options: EncodeOptions,
): Uint8Array;
}
declare var moduleFactory: EmscriptenWasm.ModuleFactory<MozJPEGModule>;
export default moduleFactory;
height: number
): number;
set_opts_quality( quality: number): void;
set_opts_baseline( baseline: boolean): void;
set_opts_arithmetic( arithmetic: boolean): void;
set_opts_progressive( progressive: boolean): void;
set_opts_optimize_coding( optimize_coding: boolean): void;
set_opts_smoothing( smoothing: number): void;
set_opts_color_space( color_space: number): void;
set_opts_quant_table( quant_table: number): void;
set_opts_trellis_multipass( trellis_multipass: boolean): void;
set_opts_trellis_opt_zero( trellis_opt_zero: boolean): void;
set_opts_trellis_opt_table( trellis_opt_table: boolean): void;
set_opts_trellis_loops( trellis_loops: number): void;
set_opts_auto_subsample( auto_subsample: boolean): void;
set_opts_chroma_subsample( chroma_subsample: number): void;
set_opts_separate_chroma_quality( separate_chroma_quality: boolean): void;
set_opts_chroma_quality( chroma_quality: number): void;
}

View File

@ -1,60 +0,0 @@
var Module = (function() {
var _scriptDir = import.meta.url;
return (
function(Module) {
Module = Module || {};
var f;f||(f=typeof Module !== 'undefined' ? Module : {});var aa,ba;f.ready=new Promise(function(a,b){aa=a;ba=b});var r={},t;for(t in f)f.hasOwnProperty(t)&&(r[t]=f[t]);var ca="./this.program";function ea(a,b){throw b;}var u="",fa;u=self.location.href;_scriptDir&&(u=_scriptDir);0!==u.indexOf("blob:")?u=u.substr(0,u.lastIndexOf("/")+1):u="";fa=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)};
var ha=f.print||console.log.bind(console),v=f.printErr||console.warn.bind(console);for(t in r)r.hasOwnProperty(t)&&(f[t]=r[t]);r=null;f.thisProgram&&(ca=f.thisProgram);f.quit&&(ea=f.quit);var w;f.wasmBinary&&(w=f.wasmBinary);var noExitRuntime;f.noExitRuntime&&(noExitRuntime=f.noExitRuntime);"object"!==typeof WebAssembly&&A("no native wasm support detected");var B,ia=!1,ja=new TextDecoder("utf8");
function ka(a,b,c){var d=C;if(0<c){c=b+c-1;for(var e=0;e<a.length;++e){var g=a.charCodeAt(e);if(55296<=g&&57343>=g){var m=a.charCodeAt(++e);g=65536+((g&1023)<<10)|m&1023}if(127>=g){if(b>=c)break;d[b++]=g}else{if(2047>=g){if(b+1>=c)break;d[b++]=192|g>>6}else{if(65535>=g){if(b+2>=c)break;d[b++]=224|g>>12}else{if(b+3>=c)break;d[b++]=240|g>>18;d[b++]=128|g>>12&63}d[b++]=128|g>>6&63}d[b++]=128|g&63}}d[b]=0}}var la=new TextDecoder("utf-16le");
function ma(a,b){var c=a>>1;for(b=c+b/2;!(c>=b)&&D[c];)++c;return la.decode(C.subarray(a,c<<1))}function na(a,b,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var d=b;c=c<2*a.length?c/2:a.length;for(var e=0;e<c;++e)E[b>>1]=a.charCodeAt(e),b+=2;E[b>>1]=0;return b-d}function oa(a){return 2*a.length}function pa(a,b){for(var c=0,d="";!(c>=b/4);){var e=G[a+4*c>>2];if(0==e)break;++c;65536<=e?(e-=65536,d+=String.fromCharCode(55296|e>>10,56320|e&1023)):d+=String.fromCharCode(e)}return d}
function qa(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var d=b;c=d+c-4;for(var e=0;e<a.length;++e){var g=a.charCodeAt(e);if(55296<=g&&57343>=g){var m=a.charCodeAt(++e);g=65536+((g&1023)<<10)|m&1023}G[b>>2]=g;b+=4;if(b+4>c)break}G[b>>2]=0;return b-d}function ra(a){for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&57343>=d&&++c;b+=4}return b}var H,I,C,E,D,G,J,sa,ta;
function ua(a){H=a;f.HEAP8=I=new Int8Array(a);f.HEAP16=E=new Int16Array(a);f.HEAP32=G=new Int32Array(a);f.HEAPU8=C=new Uint8Array(a);f.HEAPU16=D=new Uint16Array(a);f.HEAPU32=J=new Uint32Array(a);f.HEAPF32=sa=new Float32Array(a);f.HEAPF64=ta=new Float64Array(a)}var va=f.INITIAL_MEMORY||16777216;f.wasmMemory?B=f.wasmMemory:B=new WebAssembly.Memory({initial:va/65536,maximum:32768});B&&(H=B.buffer);va=H.byteLength;ua(H);var K,wa=[],xa=[],ya=[],za=[];
function Aa(){var a=f.preRun.shift();wa.unshift(a)}var L=0,Ba=null,M=null;f.preloadedImages={};f.preloadedAudios={};function A(a){if(f.onAbort)f.onAbort(a);v(a);ia=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");ba(a);throw a;}function Ca(){var a=N;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var N="mozjpeg_enc.wasm";
if(!Ca()){var Da=N;N=f.locateFile?f.locateFile(Da,u):u+Da}function Ea(){try{if(w)return new Uint8Array(w);if(fa)return fa(N);throw"both async and sync fetching of the wasm failed";}catch(a){A(a)}}function Fa(){return w||"function"!==typeof fetch?Promise.resolve().then(Ea):fetch(N,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+N+"'";return a.arrayBuffer()}).catch(function(){return Ea()})}
function O(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(f);else{var c=b.R;"number"===typeof c?void 0===b.L?K.get(c)():K.get(c)(b.L):c(void 0===b.L?null:b.L)}}}var P={};function Ga(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function Q(a){return this.fromWireType(J[a>>2])}var R={},S={},Ha={};function Ia(a){if(void 0===a)return"_unknown";a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?"_"+a:a}
function Ja(a,b){a=Ia(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}function Ka(a){var b=Error,c=Ja(a,function(d){this.name=a;this.message=d;d=Error(d).stack;void 0!==d&&(this.stack=this.toString()+"\n"+d.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(b.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message};return c}
var La=void 0;function Ma(a,b,c){function d(h){h=c(h);if(h.length!==a.length)throw new La("Mismatched type converter count");for(var n=0;n<a.length;++n)T(a[n],h[n])}a.forEach(function(h){Ha[h]=b});var e=Array(b.length),g=[],m=0;b.forEach(function(h,n){S.hasOwnProperty(h)?e[n]=S[h]:(g.push(h),R.hasOwnProperty(h)||(R[h]=[]),R[h].push(function(){e[n]=S[h];++m;m===g.length&&d(e)}))});0===g.length&&d(e)}
function Na(a){switch(a){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+a);}}var Oa=void 0;function U(a){for(var b="";C[a];)b+=Oa[C[a++]];return b}var Pa=void 0;function W(a){throw new Pa(a);}
function T(a,b,c){c=c||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var d=b.name;a||W('type "'+d+'" must have a positive integer typeid pointer');if(S.hasOwnProperty(a)){if(c.V)return;W("Cannot register type '"+d+"' twice")}S[a]=b;delete Ha[a];R.hasOwnProperty(a)&&(b=R[a],delete R[a],b.forEach(function(e){e()}))}var Qa=[],X=[{},{value:void 0},{value:null},{value:!0},{value:!1}];
function Ra(a){4<a&&0===--X[a].M&&(X[a]=void 0,Qa.push(a))}function Sa(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=Qa.length?Qa.pop():X.length;X[b]={M:1,value:a};return b}}function Ta(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}
function Ua(a,b){switch(b){case 2:return function(c){return this.fromWireType(sa[c>>2])};case 3:return function(c){return this.fromWireType(ta[c>>3])};default:throw new TypeError("Unknown float type: "+a);}}function Va(a){var b=Function;if(!(b instanceof Function))throw new TypeError("new_ called with constructor type "+typeof b+" which is not a function");var c=Ja(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c}
function Wa(a,b){var c=f;if(void 0===c[a].J){var d=c[a];c[a]=function(){c[a].J.hasOwnProperty(arguments.length)||W("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+c[a].J+")!");return c[a].J[arguments.length].apply(this,arguments)};c[a].J=[];c[a].J[d.O]=d}}
function Xa(a,b,c){f.hasOwnProperty(a)?((void 0===c||void 0!==f[a].J&&void 0!==f[a].J[c])&&W("Cannot register public name '"+a+"' twice"),Wa(a,a),f.hasOwnProperty(c)&&W("Cannot register multiple overloads of a function with the same number of arguments ("+c+")!"),f[a].J[c]=b):(f[a]=b,void 0!==c&&(f[a].ba=c))}function Ya(a,b){for(var c=[],d=0;d<a;d++)c.push(G[(b>>2)+d]);return c}
function Za(a,b){0<=a.indexOf("j")||A("Assertion failed: getDynCaller should only be called with i64 sigs");var c=[];return function(){c.length=arguments.length;for(var d=0;d<arguments.length;d++)c[d]=arguments[d];var e;-1!=a.indexOf("j")?e=c&&c.length?f["dynCall_"+a].apply(null,[b].concat(c)):f["dynCall_"+a].call(null,b):e=K.get(b).apply(null,c);return e}}
function Y(a,b){a=U(a);var c=-1!=a.indexOf("j")?Za(a,b):K.get(b);"function"!==typeof c&&W("unknown function pointer with signature "+a+": "+b);return c}var $a=void 0;function ab(a){a=bb(a);var b=U(a);Z(a);return b}function cb(a,b){function c(g){e[g]||S[g]||(Ha[g]?Ha[g].forEach(c):(d.push(g),e[g]=!0))}var d=[],e={};b.forEach(c);throw new $a(a+": "+d.map(ab).join([", "]));}
function db(a,b,c){switch(b){case 0:return c?function(d){return I[d]}:function(d){return C[d]};case 1:return c?function(d){return E[d>>1]}:function(d){return D[d>>1]};case 2:return c?function(d){return G[d>>2]}:function(d){return J[d>>2]};default:throw new TypeError("Unknown integer type: "+a);}}var eb={};function fb(){return"object"===typeof globalThis?globalThis:Function("return this")()}function gb(a,b){var c=S[a];void 0===c&&W(b+" has unknown type "+ab(a));return c}var hb={},ib={};
function jb(){if(!kb){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"===typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:ca||"./this.program"},b;for(b in ib)a[b]=ib[b];var c=[];for(b in a)c.push(b+"="+a[b]);kb=c}return kb}var kb,lb=[null,[],[]];La=f.InternalError=Ka("InternalError");for(var mb=Array(256),nb=0;256>nb;++nb)mb[nb]=String.fromCharCode(nb);Oa=mb;Pa=f.BindingError=Ka("BindingError");
f.count_emval_handles=function(){for(var a=0,b=5;b<X.length;++b)void 0!==X[b]&&++a;return a};f.get_first_emval=function(){for(var a=5;a<X.length;++a)if(void 0!==X[a])return X[a];return null};$a=f.UnboundTypeError=Ka("UnboundTypeError");xa.push({R:function(){ob()}});
var rb={B:function(){},n:function(a){var b=P[a];delete P[a];var c=b.W,d=b.X,e=b.N,g=e.map(function(m){return m.U}).concat(e.map(function(m){return m.Z}));Ma([a],g,function(m){var h={};e.forEach(function(n,k){var l=m[k],q=n.S,x=n.T,y=m[k+e.length],p=n.Y,da=n.$;h[n.P]={read:function(z){return l.fromWireType(q(x,z))},write:function(z,F){var V=[];p(da,z,y.toWireType(V,F));Ga(V)}}});return[{name:b.name,fromWireType:function(n){var k={},l;for(l in h)k[l]=h[l].read(n);d(n);return k},toWireType:function(n,
k){for(var l in h)if(!(l in k))throw new TypeError('Missing field: "'+l+'"');var q=c();for(l in h)h[l].write(q,k[l]);null!==n&&n.push(d,q);return q},argPackAdvance:8,readValueFromPointer:Q,K:d}]})},y:function(a,b,c,d,e){var g=Na(c);b=U(b);T(a,{name:b,fromWireType:function(m){return!!m},toWireType:function(m,h){return h?d:e},argPackAdvance:8,readValueFromPointer:function(m){if(1===c)var h=I;else if(2===c)h=E;else if(4===c)h=G;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(h[m>>
g])},K:null})},x:function(a,b){b=U(b);T(a,{name:b,fromWireType:function(c){var d=X[c].value;Ra(c);return d},toWireType:function(c,d){return Sa(d)},argPackAdvance:8,readValueFromPointer:Q,K:null})},k:function(a,b,c){c=Na(c);b=U(b);T(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,e){if("number"!==typeof e&&"boolean"!==typeof e)throw new TypeError('Cannot convert "'+Ta(e)+'" to '+this.name);return e},argPackAdvance:8,readValueFromPointer:Ua(b,c),K:null})},g:function(a,b,c,d,e,g){var m=
Ya(b,c);a=U(a);e=Y(d,e);Xa(a,function(){cb("Cannot call "+a+" due to unbound types",m)},b-1);Ma([],m,function(h){var n=a,k=a;h=[h[0],null].concat(h.slice(1));var l=e,q=h.length;2>q&&W("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var x=null!==h[1]&&!1,y=!1,p=1;p<h.length;++p)if(null!==h[p]&&void 0===h[p].K){y=!0;break}var da="void"!==h[0].name,z="",F="";for(p=0;p<q-2;++p)z+=(0!==p?", ":"")+"arg"+p,F+=(0!==p?", ":"")+"arg"+p+"Wired";k="return function "+Ia(k)+
"("+z+") {\nif (arguments.length !== "+(q-2)+") {\nthrowBindingError('function "+k+" called with ' + arguments.length + ' arguments, expected "+(q-2)+" args!');\n}\n";y&&(k+="var destructors = [];\n");var V=y?"destructors":"null";z="throwBindingError invoker fn runDestructors retType classParam".split(" ");l=[W,l,g,Ga,h[0],h[1]];x&&(k+="var thisWired = classParam.toWireType("+V+", this);\n");for(p=0;p<q-2;++p)k+="var arg"+p+"Wired = argType"+p+".toWireType("+V+", arg"+p+"); // "+h[p+2].name+"\n",
z.push("argType"+p),l.push(h[p+2]);x&&(F="thisWired"+(0<F.length?", ":"")+F);k+=(da?"var rv = ":"")+"invoker(fn"+(0<F.length?", ":"")+F+");\n";if(y)k+="runDestructors(destructors);\n";else for(p=x?1:2;p<h.length;++p)q=1===p?"thisWired":"arg"+(p-2)+"Wired",null!==h[p].K&&(k+=q+"_dtor("+q+"); // "+h[p].name+"\n",z.push(q+"_dtor"),l.push(h[p].K));da&&(k+="var ret = retType.fromWireType(rv);\nreturn ret;\n");z.push(k+"}\n");h=Va(z).apply(null,l);p=b-1;if(!f.hasOwnProperty(n))throw new La("Replacing nonexistant public symbol");
void 0!==f[n].J&&void 0!==p?f[n].J[p]=h:(f[n]=h,f[n].O=p);return[]})},d:function(a,b,c,d,e){function g(k){return k}b=U(b);-1===e&&(e=4294967295);var m=Na(c);if(0===d){var h=32-8*c;g=function(k){return k<<h>>>h}}var n=-1!=b.indexOf("unsigned");T(a,{name:b,fromWireType:g,toWireType:function(k,l){if("number"!==typeof l&&"boolean"!==typeof l)throw new TypeError('Cannot convert "'+Ta(l)+'" to '+this.name);if(l<d||l>e)throw new TypeError('Passing a number "'+Ta(l)+'" from JS side to C/C++ side to an argument of type "'+
b+'", which is outside the valid range ['+d+", "+e+"]!");return n?l>>>0:l|0},argPackAdvance:8,readValueFromPointer:db(b,m,0!==d),K:null})},c:function(a,b,c){function d(g){g>>=2;var m=J;return new e(H,m[g+1],m[g])}var e=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=U(c);T(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{V:!0})},l:function(a,b){b=U(b);var c="std::string"===b;T(a,{name:b,fromWireType:function(d){var e=J[d>>2];if(c)for(var g=
d+4,m=0;m<=e;++m){var h=d+4+m;if(m==e||0==C[h]){if(g){for(var n=g+(h-g),k=g;!(k>=n)&&C[k];)++k;g=ja.decode(C.subarray(g,k))}else g="";if(void 0===l)var l=g;else l+=String.fromCharCode(0),l+=g;g=h+1}}else{l=Array(e);for(m=0;m<e;++m)l[m]=String.fromCharCode(C[d+4+m]);l=l.join("")}Z(d);return l},toWireType:function(d,e){e instanceof ArrayBuffer&&(e=new Uint8Array(e));var g="string"===typeof e;g||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Int8Array||W("Cannot pass non-string to std::string");
var m=(c&&g?function(){for(var k=0,l=0;l<e.length;++l){var q=e.charCodeAt(l);55296<=q&&57343>=q&&(q=65536+((q&1023)<<10)|e.charCodeAt(++l)&1023);127>=q?++k:k=2047>=q?k+2:65535>=q?k+3:k+4}return k}:function(){return e.length})(),h=pb(4+m+1);J[h>>2]=m;if(c&&g)ka(e,h+4,m+1);else if(g)for(g=0;g<m;++g){var n=e.charCodeAt(g);255<n&&(Z(h),W("String has UTF-16 code units that do not fit in 8 bits"));C[h+4+g]=n}else for(g=0;g<m;++g)C[h+4+g]=e[g];null!==d&&d.push(Z,h);return h},argPackAdvance:8,readValueFromPointer:Q,
K:function(d){Z(d)}})},f:function(a,b,c){c=U(c);if(2===b){var d=ma;var e=na;var g=oa;var m=function(){return D};var h=1}else 4===b&&(d=pa,e=qa,g=ra,m=function(){return J},h=2);T(a,{name:c,fromWireType:function(n){for(var k=J[n>>2],l=m(),q,x=n+4,y=0;y<=k;++y){var p=n+4+y*b;if(y==k||0==l[p>>h])x=d(x,p-x),void 0===q?q=x:(q+=String.fromCharCode(0),q+=x),x=p+b}Z(n);return q},toWireType:function(n,k){"string"!==typeof k&&W("Cannot pass non-string to C++ string type "+c);var l=g(k),q=pb(4+l+b);J[q>>2]=l>>
h;e(k,q+4,l+b);null!==n&&n.push(Z,q);return q},argPackAdvance:8,readValueFromPointer:Q,K:function(n){Z(n)}})},o:function(a,b,c,d,e,g){P[a]={name:U(b),W:Y(c,d),X:Y(e,g),N:[]}},b:function(a,b,c,d,e,g,m,h,n,k){P[a].N.push({P:U(b),U:c,S:Y(d,e),T:g,Z:m,Y:Y(h,n),$:k})},z:function(a,b){b=U(b);T(a,{aa:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},h:Ra,v:function(a){if(0===a)return Sa(fb());var b=eb[a];a=void 0===b?U(a):b;return Sa(fb()[a])},m:function(a){4<a&&(X[a].M+=1)},
p:function(a,b,c,d){a||W("Cannot use deleted val. handle = "+a);a=X[a].value;var e=hb[b];if(!e){e="";for(var g=0;g<b;++g)e+=(0!==g?", ":"")+"arg"+g;var m="return function emval_allocator_"+b+"(constructor, argTypes, args) {\n";for(g=0;g<b;++g)m+="var argType"+g+" = requireRegisteredType(Module['HEAP32'][(argTypes >>> 2) + "+g+'], "parameter '+g+'");\nvar arg'+g+" = argType"+g+".readValueFromPointer(args);\nargs += argType"+g+"['argPackAdvance'];\n";e=(new Function("requireRegisteredType","Module",
"__emval_register",m+("var obj = new constructor("+e+");\nreturn __emval_register(obj);\n}\n")))(gb,f,Sa);hb[b]=e}return e(a,c,d)},i:function(){A()},s:function(a,b,c){C.copyWithin(a,b,b+c)},e:function(a){a>>>=0;var b=C.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{B.grow(Math.min(2147483648,d)-H.byteLength+65535>>>16);ua(B.buffer);var e=1;break a}catch(g){}e=void 0}if(e)return!0}return!1},
t:function(a,b){var c=0;jb().forEach(function(d,e){var g=b+c;e=G[a+4*e>>2]=g;for(g=0;g<d.length;++g)I[e++>>0]=d.charCodeAt(g);I[e>>0]=0;c+=d.length+1});return 0},u:function(a,b){var c=jb();G[a>>2]=c.length;var d=0;c.forEach(function(e){d+=e.length+1});G[b>>2]=d;return 0},A:function(a){if(!noExitRuntime){if(f.onExit)f.onExit(a);ia=!0}ea(a,new qb(a))},w:function(){return 0},q:function(){},j:function(a,b,c,d){for(var e=0,g=0;g<c;g++){for(var m=G[b+8*g>>2],h=G[b+(8*g+4)>>2],n=0;n<h;n++){var k=C[m+n],
l=lb[a];if(0===k||10===k){for(k=0;l[k]&&!(NaN<=k);)++k;k=ja.decode(l.subarray?l.subarray(0,k):new Uint8Array(l.slice(0,k)));(1===a?ha:v)(k);l.length=0}else l.push(k)}e+=h}G[d>>2]=e;return 0},a:B,r:function(){}};
(function(){function a(e){f.asm=e.exports;K=f.asm.C;L--;f.monitorRunDependencies&&f.monitorRunDependencies(L);0==L&&(null!==Ba&&(clearInterval(Ba),Ba=null),M&&(e=M,M=null,e()))}function b(e){a(e.instance)}function c(e){return Fa().then(function(g){return WebAssembly.instantiate(g,d)}).then(e,function(g){v("failed to asynchronously prepare wasm: "+g);A(g)})}var d={a:rb};L++;f.monitorRunDependencies&&f.monitorRunDependencies(L);if(f.instantiateWasm)try{return f.instantiateWasm(d,a)}catch(e){return v("Module.instantiateWasm callback failed with error: "+
e),!1}(function(){return w||"function"!==typeof WebAssembly.instantiateStreaming||Ca()||"function"!==typeof fetch?c(b):fetch(N,{credentials:"same-origin"}).then(function(e){return WebAssembly.instantiateStreaming(e,d).then(b,function(g){v("wasm streaming compile failed: "+g);v("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(ba);return{}})();
var ob=f.___wasm_call_ctors=function(){return(ob=f.___wasm_call_ctors=f.asm.D).apply(null,arguments)},pb=f._malloc=function(){return(pb=f._malloc=f.asm.E).apply(null,arguments)},Z=f._free=function(){return(Z=f._free=f.asm.F).apply(null,arguments)},bb=f.___getTypeName=function(){return(bb=f.___getTypeName=f.asm.G).apply(null,arguments)};f.___embind_register_native_and_builtin_types=function(){return(f.___embind_register_native_and_builtin_types=f.asm.H).apply(null,arguments)};
f.dynCall_jiji=function(){return(f.dynCall_jiji=f.asm.I).apply(null,arguments)};var sb;function qb(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}M=function tb(){sb||ub();sb||(M=tb)};
function ub(){function a(){if(!sb&&(sb=!0,f.calledRun=!0,!ia)){O(xa);O(ya);aa(f);if(f.onRuntimeInitialized)f.onRuntimeInitialized();if(f.postRun)for("function"==typeof f.postRun&&(f.postRun=[f.postRun]);f.postRun.length;){var b=f.postRun.shift();za.unshift(b)}O(za)}}if(!(0<L)){if(f.preRun)for("function"==typeof f.preRun&&(f.preRun=[f.preRun]);f.preRun.length;)Aa();O(wa);0<L||(f.setStatus?(f.setStatus("Running..."),setTimeout(function(){setTimeout(function(){f.setStatus("")},1);a()},1)):a())}}
f.run=ub;if(f.preInit)for("function"==typeof f.preInit&&(f.preInit=[f.preInit]);0<f.preInit.length;)f.preInit.pop()();noExitRuntime=!0;ub();
return Module.ready
}
);
})();
export default Module;

Binary file not shown.

View File

@ -1,61 +0,0 @@
var Module = (function() {
var _scriptDir = import.meta.url;
return (
function(Module) {
Module = Module || {};
var f;f||(f=typeof Module !== 'undefined' ? Module : {});var aa,ba;f.ready=new Promise(function(a,b){aa=a;ba=b});var r={},t;for(t in f)f.hasOwnProperty(t)&&(r[t]=f[t]);var da="./this.program";function ea(a,b){throw b;}var fa="",ha,ia,ja,ka;fa=__dirname+"/";ha=function(a){ja||(ja=require("fs"));ka||(ka=require("path"));a=ka.normalize(a);return ja.readFileSync(a,null)};ia=function(a){a=ha(a);a.buffer||(a=new Uint8Array(a));a.buffer||u("Assertion failed: undefined");return a};
1<process.argv.length&&(da=process.argv[1].replace(/\\/g,"/"));process.argv.slice(2);process.on("uncaughtException",function(a){if(!(a instanceof la))throw a;});process.on("unhandledRejection",u);ea=function(a){process.exit(a)};f.inspect=function(){return"[Emscripten Module object]"};var ma=f.print||console.log.bind(console),v=f.printErr||console.warn.bind(console);for(t in r)r.hasOwnProperty(t)&&(f[t]=r[t]);r=null;f.thisProgram&&(da=f.thisProgram);f.quit&&(ea=f.quit);var w;f.wasmBinary&&(w=f.wasmBinary);
var noExitRuntime;f.noExitRuntime&&(noExitRuntime=f.noExitRuntime);"object"!==typeof WebAssembly&&u("no native wasm support detected");var A,na=!1,oa=new TextDecoder("utf8");
function pa(a,b,c){var d=B;if(0<c){c=b+c-1;for(var e=0;e<a.length;++e){var g=a.charCodeAt(e);if(55296<=g&&57343>=g){var m=a.charCodeAt(++e);g=65536+((g&1023)<<10)|m&1023}if(127>=g){if(b>=c)break;d[b++]=g}else{if(2047>=g){if(b+1>=c)break;d[b++]=192|g>>6}else{if(65535>=g){if(b+2>=c)break;d[b++]=224|g>>12}else{if(b+3>=c)break;d[b++]=240|g>>18;d[b++]=128|g>>12&63}d[b++]=128|g>>6&63}d[b++]=128|g&63}}d[b]=0}}var qa=new TextDecoder("utf-16le");
function ra(a,b){var c=a>>1;for(b=c+b/2;!(c>=b)&&C[c];)++c;return qa.decode(B.subarray(a,c<<1))}function sa(a,b,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var d=b;c=c<2*a.length?c/2:a.length;for(var e=0;e<c;++e)D[b>>1]=a.charCodeAt(e),b+=2;D[b>>1]=0;return b-d}function ta(a){return 2*a.length}function ua(a,b){for(var c=0,d="";!(c>=b/4);){var e=F[a+4*c>>2];if(0==e)break;++c;65536<=e?(e-=65536,d+=String.fromCharCode(55296|e>>10,56320|e&1023)):d+=String.fromCharCode(e)}return d}
function va(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var d=b;c=d+c-4;for(var e=0;e<a.length;++e){var g=a.charCodeAt(e);if(55296<=g&&57343>=g){var m=a.charCodeAt(++e);g=65536+((g&1023)<<10)|m&1023}F[b>>2]=g;b+=4;if(b+4>c)break}F[b>>2]=0;return b-d}function wa(a){for(var b=0,c=0;c<a.length;++c){var d=a.charCodeAt(c);55296<=d&&57343>=d&&++c;b+=4}return b}var G,H,B,D,C,F,I,xa,ya;
function za(a){G=a;f.HEAP8=H=new Int8Array(a);f.HEAP16=D=new Int16Array(a);f.HEAP32=F=new Int32Array(a);f.HEAPU8=B=new Uint8Array(a);f.HEAPU16=C=new Uint16Array(a);f.HEAPU32=I=new Uint32Array(a);f.HEAPF32=xa=new Float32Array(a);f.HEAPF64=ya=new Float64Array(a)}var Aa=f.INITIAL_MEMORY||16777216;f.wasmMemory?A=f.wasmMemory:A=new WebAssembly.Memory({initial:Aa/65536,maximum:32768});A&&(G=A.buffer);Aa=G.byteLength;za(G);var J,Ba=[],Ca=[],Da=[],Ea=[];
function Fa(){var a=f.preRun.shift();Ba.unshift(a)}var K=0,Ga=null,L=null;f.preloadedImages={};f.preloadedAudios={};function u(a){if(f.onAbort)f.onAbort(a);v(a);na=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");ba(a);throw a;}function Ha(){var a=M;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var M="mozjpeg_node_enc.wasm";
if(!Ha()){var Ia=M;M=f.locateFile?f.locateFile(Ia,fa):fa+Ia}function Ja(){try{if(w)return new Uint8Array(w);if(ia)return ia(M);throw"both async and sync fetching of the wasm failed";}catch(a){u(a)}}function N(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(f);else{var c=b.R;"number"===typeof c?void 0===b.L?J.get(c)():J.get(c)(b.L):c(void 0===b.L?null:b.L)}}}var O={};function Ka(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function P(a){return this.fromWireType(I[a>>2])}
var Q={},R={},S={};function La(a){if(void 0===a)return"_unknown";a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?"_"+a:a}function Ma(a,b){a=La(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}
function Na(a){var b=Error,c=Ma(a,function(d){this.name=a;this.message=d;d=Error(d).stack;void 0!==d&&(this.stack=this.toString()+"\n"+d.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(b.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message};return c}var Oa=void 0;
function Pa(a,b,c){function d(h){h=c(h);if(h.length!==a.length)throw new Oa("Mismatched type converter count");for(var k=0;k<a.length;++k)U(a[k],h[k])}a.forEach(function(h){S[h]=b});var e=Array(b.length),g=[],m=0;b.forEach(function(h,k){R.hasOwnProperty(h)?e[k]=R[h]:(g.push(h),Q.hasOwnProperty(h)||(Q[h]=[]),Q[h].push(function(){e[k]=R[h];++m;m===g.length&&d(e)}))});0===g.length&&d(e)}
function Qa(a){switch(a){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+a);}}var Ra=void 0;function V(a){for(var b="";B[a];)b+=Ra[B[a++]];return b}var Sa=void 0;function W(a){throw new Sa(a);}
function U(a,b,c){c=c||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var d=b.name;a||W('type "'+d+'" must have a positive integer typeid pointer');if(R.hasOwnProperty(a)){if(c.V)return;W("Cannot register type '"+d+"' twice")}R[a]=b;delete S[a];Q.hasOwnProperty(a)&&(b=Q[a],delete Q[a],b.forEach(function(e){e()}))}var Ta=[],X=[{},{value:void 0},{value:null},{value:!0},{value:!1}];
function Ua(a){4<a&&0===--X[a].M&&(X[a]=void 0,Ta.push(a))}function Va(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=Ta.length?Ta.pop():X.length;X[b]={M:1,value:a};return b}}function Wa(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}
function Xa(a,b){switch(b){case 2:return function(c){return this.fromWireType(xa[c>>2])};case 3:return function(c){return this.fromWireType(ya[c>>3])};default:throw new TypeError("Unknown float type: "+a);}}function Ya(a){var b=Function;if(!(b instanceof Function))throw new TypeError("new_ called with constructor type "+typeof b+" which is not a function");var c=Ma(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c}
function Za(a,b){var c=f;if(void 0===c[a].J){var d=c[a];c[a]=function(){c[a].J.hasOwnProperty(arguments.length)||W("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+c[a].J+")!");return c[a].J[arguments.length].apply(this,arguments)};c[a].J=[];c[a].J[d.O]=d}}
function $a(a,b,c){f.hasOwnProperty(a)?((void 0===c||void 0!==f[a].J&&void 0!==f[a].J[c])&&W("Cannot register public name '"+a+"' twice"),Za(a,a),f.hasOwnProperty(c)&&W("Cannot register multiple overloads of a function with the same number of arguments ("+c+")!"),f[a].J[c]=b):(f[a]=b,void 0!==c&&(f[a].ba=c))}function ab(a,b){for(var c=[],d=0;d<a;d++)c.push(F[(b>>2)+d]);return c}
function bb(a,b){0<=a.indexOf("j")||u("Assertion failed: getDynCaller should only be called with i64 sigs");var c=[];return function(){c.length=arguments.length;for(var d=0;d<arguments.length;d++)c[d]=arguments[d];var e;-1!=a.indexOf("j")?e=c&&c.length?f["dynCall_"+a].apply(null,[b].concat(c)):f["dynCall_"+a].call(null,b):e=J.get(b).apply(null,c);return e}}
function Y(a,b){a=V(a);var c=-1!=a.indexOf("j")?bb(a,b):J.get(b);"function"!==typeof c&&W("unknown function pointer with signature "+a+": "+b);return c}var cb=void 0;function db(a){a=eb(a);var b=V(a);Z(a);return b}function fb(a,b){function c(g){e[g]||R[g]||(S[g]?S[g].forEach(c):(d.push(g),e[g]=!0))}var d=[],e={};b.forEach(c);throw new cb(a+": "+d.map(db).join([", "]));}
function gb(a,b,c){switch(b){case 0:return c?function(d){return H[d]}:function(d){return B[d]};case 1:return c?function(d){return D[d>>1]}:function(d){return C[d>>1]};case 2:return c?function(d){return F[d>>2]}:function(d){return I[d>>2]};default:throw new TypeError("Unknown integer type: "+a);}}var hb={};function ib(){return"object"===typeof globalThis?globalThis:Function("return this")()}function jb(a,b){var c=R[a];void 0===c&&W(b+" has unknown type "+db(a));return c}var kb={},lb={};
function mb(){if(!nb){var a={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:("object"===typeof navigator&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",_:da||"./this.program"},b;for(b in lb)a[b]=lb[b];var c=[];for(b in a)c.push(b+"="+a[b]);nb=c}return nb}var nb,ob=[null,[],[]];Oa=f.InternalError=Na("InternalError");for(var pb=Array(256),qb=0;256>qb;++qb)pb[qb]=String.fromCharCode(qb);Ra=pb;Sa=f.BindingError=Na("BindingError");
f.count_emval_handles=function(){for(var a=0,b=5;b<X.length;++b)void 0!==X[b]&&++a;return a};f.get_first_emval=function(){for(var a=5;a<X.length;++a)if(void 0!==X[a])return X[a];return null};cb=f.UnboundTypeError=Na("UnboundTypeError");Ca.push({R:function(){rb()}});
var tb={B:function(){},n:function(a){var b=O[a];delete O[a];var c=b.W,d=b.X,e=b.N,g=e.map(function(m){return m.U}).concat(e.map(function(m){return m.Z}));Pa([a],g,function(m){var h={};e.forEach(function(k,n){var l=m[n],p=k.S,x=k.T,y=m[n+e.length],q=k.Y,ca=k.$;h[k.P]={read:function(z){return l.fromWireType(p(x,z))},write:function(z,E){var T=[];q(ca,z,y.toWireType(T,E));Ka(T)}}});return[{name:b.name,fromWireType:function(k){var n={},l;for(l in h)n[l]=h[l].read(k);d(k);return n},toWireType:function(k,
n){for(var l in h)if(!(l in n))throw new TypeError('Missing field: "'+l+'"');var p=c();for(l in h)h[l].write(p,n[l]);null!==k&&k.push(d,p);return p},argPackAdvance:8,readValueFromPointer:P,K:d}]})},y:function(a,b,c,d,e){var g=Qa(c);b=V(b);U(a,{name:b,fromWireType:function(m){return!!m},toWireType:function(m,h){return h?d:e},argPackAdvance:8,readValueFromPointer:function(m){if(1===c)var h=H;else if(2===c)h=D;else if(4===c)h=F;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(h[m>>
g])},K:null})},x:function(a,b){b=V(b);U(a,{name:b,fromWireType:function(c){var d=X[c].value;Ua(c);return d},toWireType:function(c,d){return Va(d)},argPackAdvance:8,readValueFromPointer:P,K:null})},k:function(a,b,c){c=Qa(c);b=V(b);U(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,e){if("number"!==typeof e&&"boolean"!==typeof e)throw new TypeError('Cannot convert "'+Wa(e)+'" to '+this.name);return e},argPackAdvance:8,readValueFromPointer:Xa(b,c),K:null})},g:function(a,b,c,d,e,g){var m=
ab(b,c);a=V(a);e=Y(d,e);$a(a,function(){fb("Cannot call "+a+" due to unbound types",m)},b-1);Pa([],m,function(h){var k=[h[0],null].concat(h.slice(1)),n=h=a,l=e,p=k.length;2>p&&W("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var x=null!==k[1]&&!1,y=!1,q=1;q<k.length;++q)if(null!==k[q]&&void 0===k[q].K){y=!0;break}var ca="void"!==k[0].name,z="",E="";for(q=0;q<p-2;++q)z+=(0!==q?", ":"")+"arg"+q,E+=(0!==q?", ":"")+"arg"+q+"Wired";n="return function "+La(n)+"("+
z+") {\nif (arguments.length !== "+(p-2)+") {\nthrowBindingError('function "+n+" called with ' + arguments.length + ' arguments, expected "+(p-2)+" args!');\n}\n";y&&(n+="var destructors = [];\n");var T=y?"destructors":"null";z="throwBindingError invoker fn runDestructors retType classParam".split(" ");l=[W,l,g,Ka,k[0],k[1]];x&&(n+="var thisWired = classParam.toWireType("+T+", this);\n");for(q=0;q<p-2;++q)n+="var arg"+q+"Wired = argType"+q+".toWireType("+T+", arg"+q+"); // "+k[q+2].name+"\n",z.push("argType"+
q),l.push(k[q+2]);x&&(E="thisWired"+(0<E.length?", ":"")+E);n+=(ca?"var rv = ":"")+"invoker(fn"+(0<E.length?", ":"")+E+");\n";if(y)n+="runDestructors(destructors);\n";else for(q=x?1:2;q<k.length;++q)p=1===q?"thisWired":"arg"+(q-2)+"Wired",null!==k[q].K&&(n+=p+"_dtor("+p+"); // "+k[q].name+"\n",z.push(p+"_dtor"),l.push(k[q].K));ca&&(n+="var ret = retType.fromWireType(rv);\nreturn ret;\n");z.push(n+"}\n");k=Ya(z).apply(null,l);q=b-1;if(!f.hasOwnProperty(h))throw new Oa("Replacing nonexistant public symbol");
void 0!==f[h].J&&void 0!==q?f[h].J[q]=k:(f[h]=k,f[h].O=q);return[]})},d:function(a,b,c,d,e){function g(n){return n}b=V(b);-1===e&&(e=4294967295);var m=Qa(c);if(0===d){var h=32-8*c;g=function(n){return n<<h>>>h}}var k=-1!=b.indexOf("unsigned");U(a,{name:b,fromWireType:g,toWireType:function(n,l){if("number"!==typeof l&&"boolean"!==typeof l)throw new TypeError('Cannot convert "'+Wa(l)+'" to '+this.name);if(l<d||l>e)throw new TypeError('Passing a number "'+Wa(l)+'" from JS side to C/C++ side to an argument of type "'+
b+'", which is outside the valid range ['+d+", "+e+"]!");return k?l>>>0:l|0},argPackAdvance:8,readValueFromPointer:gb(b,m,0!==d),K:null})},c:function(a,b,c){function d(g){g>>=2;var m=I;return new e(G,m[g+1],m[g])}var e=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=V(c);U(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{V:!0})},l:function(a,b){b=V(b);var c="std::string"===b;U(a,{name:b,fromWireType:function(d){var e=I[d>>2];if(c)for(var g=
d+4,m=0;m<=e;++m){var h=d+4+m;if(m==e||0==B[h]){if(g){for(var k=g+(h-g),n=g;!(n>=k)&&B[n];)++n;g=oa.decode(B.subarray(g,n))}else g="";if(void 0===l)var l=g;else l+=String.fromCharCode(0),l+=g;g=h+1}}else{l=Array(e);for(m=0;m<e;++m)l[m]=String.fromCharCode(B[d+4+m]);l=l.join("")}Z(d);return l},toWireType:function(d,e){e instanceof ArrayBuffer&&(e=new Uint8Array(e));var g="string"===typeof e;g||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Int8Array||W("Cannot pass non-string to std::string");
var m=(c&&g?function(){for(var n=0,l=0;l<e.length;++l){var p=e.charCodeAt(l);55296<=p&&57343>=p&&(p=65536+((p&1023)<<10)|e.charCodeAt(++l)&1023);127>=p?++n:n=2047>=p?n+2:65535>=p?n+3:n+4}return n}:function(){return e.length})(),h=sb(4+m+1);I[h>>2]=m;if(c&&g)pa(e,h+4,m+1);else if(g)for(g=0;g<m;++g){var k=e.charCodeAt(g);255<k&&(Z(h),W("String has UTF-16 code units that do not fit in 8 bits"));B[h+4+g]=k}else for(g=0;g<m;++g)B[h+4+g]=e[g];null!==d&&d.push(Z,h);return h},argPackAdvance:8,readValueFromPointer:P,
K:function(d){Z(d)}})},f:function(a,b,c){c=V(c);if(2===b){var d=ra;var e=sa;var g=ta;var m=function(){return C};var h=1}else 4===b&&(d=ua,e=va,g=wa,m=function(){return I},h=2);U(a,{name:c,fromWireType:function(k){for(var n=I[k>>2],l=m(),p,x=k+4,y=0;y<=n;++y){var q=k+4+y*b;if(y==n||0==l[q>>h])x=d(x,q-x),void 0===p?p=x:(p+=String.fromCharCode(0),p+=x),x=q+b}Z(k);return p},toWireType:function(k,n){"string"!==typeof n&&W("Cannot pass non-string to C++ string type "+c);var l=g(n),p=sb(4+l+b);I[p>>2]=l>>
h;e(n,p+4,l+b);null!==k&&k.push(Z,p);return p},argPackAdvance:8,readValueFromPointer:P,K:function(k){Z(k)}})},o:function(a,b,c,d,e,g){O[a]={name:V(b),W:Y(c,d),X:Y(e,g),N:[]}},b:function(a,b,c,d,e,g,m,h,k,n){O[a].N.push({P:V(b),U:c,S:Y(d,e),T:g,Z:m,Y:Y(h,k),$:n})},z:function(a,b){b=V(b);U(a,{aa:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},h:Ua,v:function(a){if(0===a)return Va(ib());var b=hb[a];a=void 0===b?V(a):b;return Va(ib()[a])},m:function(a){4<a&&(X[a].M+=1)},
p:function(a,b,c,d){a||W("Cannot use deleted val. handle = "+a);a=X[a].value;var e=kb[b];if(!e){e="";for(var g=0;g<b;++g)e+=(0!==g?", ":"")+"arg"+g;var m="return function emval_allocator_"+b+"(constructor, argTypes, args) {\n";for(g=0;g<b;++g)m+="var argType"+g+" = requireRegisteredType(Module['HEAP32'][(argTypes >>> 2) + "+g+'], "parameter '+g+'");\nvar arg'+g+" = argType"+g+".readValueFromPointer(args);\nargs += argType"+g+"['argPackAdvance'];\n";e=(new Function("requireRegisteredType","Module",
"__emval_register",m+("var obj = new constructor("+e+");\nreturn __emval_register(obj);\n}\n")))(jb,f,Va);kb[b]=e}return e(a,c,d)},i:function(){u()},s:function(a,b,c){B.copyWithin(a,b,b+c)},e:function(a){a>>>=0;var b=B.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);d=Math.max(16777216,a,d);0<d%65536&&(d+=65536-d%65536);a:{try{A.grow(Math.min(2147483648,d)-G.byteLength+65535>>>16);za(A.buffer);var e=1;break a}catch(g){}e=void 0}if(e)return!0}return!1},
t:function(a,b){var c=0;mb().forEach(function(d,e){var g=b+c;e=F[a+4*e>>2]=g;for(g=0;g<d.length;++g)H[e++>>0]=d.charCodeAt(g);H[e>>0]=0;c+=d.length+1});return 0},u:function(a,b){var c=mb();F[a>>2]=c.length;var d=0;c.forEach(function(e){d+=e.length+1});F[b>>2]=d;return 0},A:function(a){if(!noExitRuntime){if(f.onExit)f.onExit(a);na=!0}ea(a,new la(a))},w:function(){return 0},q:function(){},j:function(a,b,c,d){for(var e=0,g=0;g<c;g++){for(var m=F[b+8*g>>2],h=F[b+(8*g+4)>>2],k=0;k<h;k++){var n=B[m+k],
l=ob[a];if(0===n||10===n){n=1===a?ma:v;var p;for(p=0;l[p]&&!(NaN<=p);)++p;p=oa.decode(l.subarray?l.subarray(0,p):new Uint8Array(l.slice(0,p)));n(p);l.length=0}else l.push(n)}e+=h}F[d>>2]=e;return 0},a:A,r:function(){}};
(function(){function a(e){f.asm=e.exports;J=f.asm.C;K--;f.monitorRunDependencies&&f.monitorRunDependencies(K);0==K&&(null!==Ga&&(clearInterval(Ga),Ga=null),L&&(e=L,L=null,e()))}function b(e){a(e.instance)}function c(e){return Promise.resolve().then(Ja).then(function(g){return WebAssembly.instantiate(g,d)}).then(e,function(g){v("failed to asynchronously prepare wasm: "+g);u(g)})}var d={a:tb};K++;f.monitorRunDependencies&&f.monitorRunDependencies(K);if(f.instantiateWasm)try{return f.instantiateWasm(d,
a)}catch(e){return v("Module.instantiateWasm callback failed with error: "+e),!1}(function(){return w||"function"!==typeof WebAssembly.instantiateStreaming||Ha()||"function"!==typeof fetch?c(b):fetch(M,{credentials:"same-origin"}).then(function(e){return WebAssembly.instantiateStreaming(e,d).then(b,function(g){v("wasm streaming compile failed: "+g);v("falling back to ArrayBuffer instantiation");return c(b)})})})().catch(ba);return{}})();
var rb=f.___wasm_call_ctors=function(){return(rb=f.___wasm_call_ctors=f.asm.D).apply(null,arguments)},sb=f._malloc=function(){return(sb=f._malloc=f.asm.E).apply(null,arguments)},Z=f._free=function(){return(Z=f._free=f.asm.F).apply(null,arguments)},eb=f.___getTypeName=function(){return(eb=f.___getTypeName=f.asm.G).apply(null,arguments)};f.___embind_register_native_and_builtin_types=function(){return(f.___embind_register_native_and_builtin_types=f.asm.H).apply(null,arguments)};
f.dynCall_jiji=function(){return(f.dynCall_jiji=f.asm.I).apply(null,arguments)};var ub;function la(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}L=function vb(){ub||wb();ub||(L=vb)};
function wb(){function a(){if(!ub&&(ub=!0,f.calledRun=!0,!na)){N(Ca);N(Da);aa(f);if(f.onRuntimeInitialized)f.onRuntimeInitialized();if(f.postRun)for("function"==typeof f.postRun&&(f.postRun=[f.postRun]);f.postRun.length;){var b=f.postRun.shift();Ea.unshift(b)}N(Ea)}}if(!(0<K)){if(f.preRun)for("function"==typeof f.preRun&&(f.preRun=[f.preRun]);f.preRun.length;)Fa();N(Ba);0<K||(f.setStatus?(f.setStatus("Running..."),setTimeout(function(){setTimeout(function(){f.setStatus("")},1);a()},1)):a())}}
f.run=wb;if(f.preInit)for("function"==typeof f.preInit&&(f.preInit=[f.preInit]);0<f.preInit.length;)f.preInit.pop()();noExitRuntime=!0;wb();
return Module.ready
}
);
})();
export default Module;

View File

@ -1,5 +1,5 @@
{
"scripts": {
"build": "../build-cpp.sh"
"build": "../build-wasi-sdk.sh"
}
}

View File

@ -1,7 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "0.2.3"
@ -234,15 +232,6 @@ dependencies = [
"either",
]
[[package]]
name = "js-sys"
version = "0.3.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -361,6 +350,12 @@ dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
[[package]]
name = "oxipng"
version = "4.0.3"
@ -406,9 +401,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.26"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
@ -489,28 +484,24 @@ dependencies = [
"pest",
]
[[package]]
name = "spmc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5"
[[package]]
name = "squoosh-oxipng"
version = "0.1.0"
dependencies = [
"crossbeam-channel",
"libdeflater",
"log",
"once_cell",
"oxipng",
"rayon",
"wasm-bindgen",
"wasm-bindgen-rayon",
]
[[package]]
name = "syn"
version = "1.0.72"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
dependencies = [
"proc-macro2",
"quote",
@ -531,9 +522,9 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "wasm-bindgen"
version = "0.2.73"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@ -541,9 +532,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.73"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
dependencies = [
"bumpalo",
"lazy_static",
@ -556,9 +547,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.73"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -566,9 +557,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.73"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
dependencies = [
"proc-macro2",
"quote",
@ -577,20 +568,8 @@ dependencies = [
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-rayon"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3069d2a42e7a7e3bfde668f84adb5fbc35701ca2b39b27a064cbd5ede4e78194"
dependencies = [
"js-sys",
"rayon",
"spmc",
"wasm-bindgen",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.73"
version = "0.2.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"

View File

@ -12,15 +12,17 @@ wasm-opt = ["-O", "--no-validation"]
crate-type = ["cdylib"]
[dependencies]
oxipng = { version = "4.0.3", default-features = false, features = ["libdeflater"] }
oxipng = { version = "4.0.1", default-features = false, features = ["libdeflater"] }
libdeflater = { version = "0.7.1", features = ["freestanding"] }
wasm-bindgen = "0.2.73"
wasm-bindgen = "0.2.68"
log = { version = "0.4.11", features = ["release_max_level_off"] }
wasm-bindgen-rayon = { version = "1.0", optional = true }
rayon = { version = "1.5.0", optional = true }
once_cell = { version = "1.5.2", optional = true }
crossbeam-channel = { version = "0.5.0", optional = true }
[profile.release]
lto = true
opt-level = "s"
[features]
parallel = ["oxipng/parallel", "wasm-bindgen-rayon"]
parallel = ["oxipng/parallel", "rayon", "crossbeam-channel", "once_cell"]

View File

@ -6,4 +6,6 @@ rm -rf pkg,{-parallel}
export CFLAGS="${CFLAGS} -DUNALIGNED_ACCESS_IS_FAST=1"
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
# 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

View File

@ -1,98 +0,0 @@
/**
* Copyright 2021 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.
*/
// Note: we use `wasm_bindgen_worker_`-prefixed message types to make sure
// we can handle bundling into other files, which might happen to have their
// own `postMessage`/`onmessage` communication channels.
//
// If we didn't take that into the account, we could send much simpler signals
// like just `0` or whatever, but the code would be less resilient.
function waitForMsgType(target, type) {
return new Promise(resolve => {
target.addEventListener('message', function onMsg({ data }) {
if (data == null || data.type !== type) return;
target.removeEventListener('message', onMsg);
resolve(data);
});
});
}
waitForMsgType(self, 'wasm_bindgen_worker_init').then(async data => {
// # Note 1
// Our JS should have been generated in
// `[out-dir]/snippets/wasm-bindgen-rayon-[hash]/workerHelpers.js`,
// resolve the main module via `../../..`.
//
// This might need updating if the generated structure changes on wasm-bindgen
// side ever in the future, but works well with bundlers today. The whole
// point of this crate, after all, is to abstract away unstable features
// and temporary bugs so that you don't need to deal with them in your code.
//
// # Note 2
// This could be a regular import, but then some bundlers complain about
// circular deps.
//
// Dynamic import could be cheap if this file was inlined into the parent,
// which would require us just using `../../..` in `new Worker` below,
// but that doesn't work because wasm-pack unconditionally adds
// "sideEffects":false (see below).
//
// OTOH, even though it can't be inlined, it should be still reasonably
// cheap since the requested file is already in cache (it was loaded by
// the main thread).
const pkg = await import('../../..');
await pkg.default(data.module, data.memory);
postMessage({ type: 'wasm_bindgen_worker_ready' });
pkg.wbg_rayon_start_worker(data.receiver);
});
export async function startWorkers(module, memory, builder) {
const workerInit = {
type: 'wasm_bindgen_worker_init',
module,
memory,
receiver: builder.receiver()
};
try {
await Promise.all(
Array.from({ length: builder.numThreads() }, () => {
// Self-spawn into a new Worker.
//
// TODO: while `new URL('...', import.meta.url) becomes a semi-standard
// way to get asset URLs relative to the module across various bundlers
// and browser, ideally we should switch to `import.meta.resolve`
// once it becomes a standard.
//
// Note: we could use `../../..` as the URL here to inline workerHelpers.js
// into the parent entry instead of creating another split point -
// this would be preferable from optimization perspective -
// however, Webpack then eliminates all message handler code
// because wasm-pack produces "sideEffects":false in package.json
// unconditionally.
//
// The only way to work around that is to have side effect code
// in an entry point such as Worker file itself.
const worker = new Worker(new URL('./workerHelpers.js', import.meta.url), {
type: 'module'
});
worker.postMessage(workerInit);
return waitForMsgType(worker, 'wasm_bindgen_worker_ready');
})
);
builder.build();
} finally {
builder.free();
}
}

View File

@ -3,48 +3,29 @@
/**
* @param {Uint8Array} data
* @param {number} level
* @param {boolean} interlace
* @returns {Uint8Array}
*/
export function optimise(data: Uint8Array, level: number, interlace: boolean): Uint8Array;
export function optimise(data: Uint8Array, level: number): Uint8Array;
/**
* @param {number} num_threads
* @returns {Promise<any>}
* @param {number} num
* @returns {any}
*/
export function initThreadPool(num_threads: number): Promise<any>;
/**
* @param {number} receiver
*/
export function wbg_rayon_start_worker(receiver: number): void;
export function worker_initializer(num: number): any;
/**
*/
export class wbg_rayon_PoolBuilder {
free(): void;
/**
* @returns {number}
*/
numThreads(): number;
/**
* @returns {number}
*/
receiver(): number;
export function start_main_thread(): void;
/**
*/
build(): void;
}
export function start_worker_thread(): void;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput {
readonly optimise: (a: number, b: number, c: number, d: number, e: number) => void;
readonly __wbg_wbg_rayon_poolbuilder_free: (a: number) => void;
readonly wbg_rayon_poolbuilder_numThreads: (a: number) => number;
readonly wbg_rayon_poolbuilder_receiver: (a: number) => number;
readonly wbg_rayon_poolbuilder_build: (a: number) => void;
readonly initThreadPool: (a: number) => number;
readonly wbg_rayon_start_worker: (a: number) => void;
readonly optimise: (a: number, b: number, c: number, d: number) => void;
readonly worker_initializer: (a: number) => number;
readonly start_main_thread: () => void;
readonly start_worker_thread: () => void;
readonly __wbindgen_export_0: WebAssembly.Memory;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly __wbindgen_malloc: (a: number) => number;
readonly __wbindgen_free: (a: number, b: number) => void;
readonly __wbindgen_start: () => void;
@ -60,3 +41,4 @@ export interface InitOutput {
* @returns {Promise<InitOutput>}
*/
export default function init (module_or_path?: InitInput | Promise<InitInput>, maybe_memory?: WebAssembly.Memory): Promise<InitOutput>;

View File

@ -1,6 +1,21 @@
import { startWorkers } from './snippets/wasm-bindgen-rayon-3d2df09ebec17a22/src/workerHelpers.js';
let wasm;
let memory;
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
let heap_next = heap.length;
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
@ -18,21 +33,6 @@ function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().slice(ptr, ptr + len));
}
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
let heap_next = heap.length;
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
let WASM_VECTOR_LEN = 0;
function passArray8ToWasm0(arg, malloc) {
@ -56,22 +56,22 @@ function getArrayU8FromWasm0(ptr, len) {
/**
* @param {Uint8Array} data
* @param {number} level
* @param {boolean} interlace
* @returns {Uint8Array}
*/
export function optimise(data, level, interlace) {
export function optimise(data, level) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const retptr = wasm.__wbindgen_export_1.value - 16;
wasm.__wbindgen_export_1.value = retptr;
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
wasm.optimise(retptr, ptr0, len0, level, interlace);
wasm.optimise(retptr, ptr0, len0, level);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v1;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_export_1.value += 16;
}
}
@ -89,66 +89,29 @@ function takeObject(idx) {
return ret;
}
/**
* @param {number} num_threads
* @returns {Promise<any>}
* @param {number} num
* @returns {any}
*/
export function initThreadPool(num_threads) {
var ret = wasm.initThreadPool(num_threads);
export function worker_initializer(num) {
var ret = wasm.worker_initializer(num);
return takeObject(ret);
}
/**
* @param {number} receiver
*/
export function wbg_rayon_start_worker(receiver) {
wasm.wbg_rayon_start_worker(receiver);
export function start_main_thread() {
wasm.start_main_thread();
}
/**
*/
export class wbg_rayon_PoolBuilder {
static __wrap(ptr) {
const obj = Object.create(wbg_rayon_PoolBuilder.prototype);
obj.ptr = ptr;
return obj;
}
__destroy_into_raw() {
const ptr = this.ptr;
this.ptr = 0;
return ptr;
}
free() {
const ptr = this.__destroy_into_raw();
wasm.__wbg_wbg_rayon_poolbuilder_free(ptr);
}
/**
* @returns {number}
*/
numThreads() {
var ret = wasm.wbg_rayon_poolbuilder_numThreads(this.ptr);
return ret >>> 0;
}
/**
* @returns {number}
*/
receiver() {
var ret = wasm.wbg_rayon_poolbuilder_receiver(this.ptr);
return ret;
}
/**
*/
build() {
wasm.wbg_rayon_poolbuilder_build(this.ptr);
}
export function start_worker_thread() {
wasm.start_worker_thread();
}
async function load(module, imports) {
async function load(module, imports, maybe_memory) {
if (typeof Response === 'function' && module instanceof Response) {
memory = imports.wbg.memory = new WebAssembly.Memory({initial:17,maximum:16384,shared:true});
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
@ -167,6 +130,7 @@ async function load(module, 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) {
@ -180,13 +144,10 @@ async function load(module, imports) {
async function init(input, maybe_memory) {
if (typeof input === 'undefined') {
input = new URL('squoosh_oxipng_bg.wasm', import.meta.url);
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
}
const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
imports.wbg.__wbindgen_module = function() {
var ret = init.__wbindgen_wasm_module;
return addHeapObject(ret);
@ -195,18 +156,19 @@ async function init(input, maybe_memory) {
var ret = wasm.__wbindgen_export_0;
return addHeapObject(ret);
};
imports.wbg.__wbg_startWorkers_914655bb4d5bb5e1 = function(arg0, arg1, arg2) {
var ret = startWorkers(takeObject(arg0), takeObject(arg1), wbg_rayon_PoolBuilder.__wrap(arg2));
imports.wbg.__wbg_of_6510501edc06d65e = function(arg0, arg1) {
var ret = Array.of(takeObject(arg0), takeObject(arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
input = fetch(input);
}
imports.wbg.memory = maybe_memory || new WebAssembly.Memory({initial:17,maximum:16384,shared:true});
const { instance, module } = await load(await input, imports);
const { instance, module } = await load(await input, imports, maybe_memory);
wasm = instance.exports;
init.__wbindgen_wasm_module = module;

View File

@ -1,14 +1,10 @@
/* tslint:disable */
/* eslint-disable */
export function optimise(a: number, b: number, c: number, d: number, e: number): void;
export function __wbg_wbg_rayon_poolbuilder_free(a: number): void;
export function wbg_rayon_poolbuilder_numThreads(a: number): number;
export function wbg_rayon_poolbuilder_receiver(a: number): number;
export function wbg_rayon_poolbuilder_build(a: number): void;
export function initThreadPool(a: number): number;
export function wbg_rayon_start_worker(a: number): void;
export function optimise(a: number, b: number, c: number, d: number): void;
export function worker_initializer(a: number): number;
export function start_main_thread(): void;
export function start_worker_thread(): void;
export const __wbindgen_export_0: WebAssembly.Memory;
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;
export function __wbindgen_start(): void;

View File

@ -3,17 +3,15 @@
/**
* @param {Uint8Array} data
* @param {number} level
* @param {boolean} interlace
* @returns {Uint8Array}
*/
export function optimise(data: Uint8Array, level: number, interlace: boolean): Uint8Array;
export function optimise(data: Uint8Array, level: number): Uint8Array;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput {
readonly memory: WebAssembly.Memory;
readonly optimise: (a: number, b: number, c: number, d: number, e: number) => void;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly optimise: (a: number, b: number, c: number, d: number) => void;
readonly __wbindgen_malloc: (a: number) => number;
readonly __wbindgen_free: (a: number, b: number) => void;
}
@ -27,3 +25,4 @@ export interface InitOutput {
* @returns {Promise<InitOutput>}
*/
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;

View File

@ -40,27 +40,28 @@ function getArrayU8FromWasm0(ptr, len) {
/**
* @param {Uint8Array} data
* @param {number} level
* @param {boolean} interlace
* @returns {Uint8Array}
*/
export function optimise(data, level, interlace) {
export function optimise(data, level) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const retptr = wasm.__wbindgen_export_0.value - 16;
wasm.__wbindgen_export_0.value = retptr;
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
wasm.optimise(retptr, ptr0, len0, level, interlace);
wasm.optimise(retptr, ptr0, len0, level);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v1;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
wasm.__wbindgen_export_0.value += 16;
}
}
async function load(module, imports) {
if (typeof Response === 'function' && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === 'function') {
try {
return await WebAssembly.instantiateStreaming(module, imports);
@ -79,6 +80,7 @@ async function load(module, imports) {
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
@ -92,7 +94,7 @@ async function load(module, imports) {
async function init(input) {
if (typeof input === 'undefined') {
input = new URL('squoosh_oxipng_bg.wasm', import.meta.url);
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
}
const imports = {};
imports.wbg = {};
@ -104,8 +106,6 @@ async function init(input) {
input = fetch(input);
}
const { instance, module } = await load(await input, imports);
wasm = instance.exports;

View File

@ -1,7 +1,6 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function optimise(a: number, b: number, c: number, d: number, e: number): void;
export function __wbindgen_add_to_stack_pointer(a: number): number;
export function optimise(a: number, b: number, c: number, d: number): void;
export function __wbindgen_malloc(a: number): number;
export function __wbindgen_free(a: number, b: number): void;

View File

@ -1,11 +1,11 @@
#[cfg(feature = "parallel")]
pub use wasm_bindgen_rayon::init_thread_pool;
use oxipng::AlphaOptim;
use wasm_bindgen::prelude::*;
#[cfg(feature = "parallel")]
pub mod parallel;
#[wasm_bindgen]
pub fn optimise(data: &[u8], level: u8, interlace: bool) -> Vec<u8> {
pub fn optimise(data: &[u8], level: u8) -> Vec<u8> {
let mut options = oxipng::Options::from_preset(level);
options.alphas.insert(AlphaOptim::Black);
options.alphas.insert(AlphaOptim::White);
@ -13,7 +13,6 @@ pub fn optimise(data: &[u8], level: u8, interlace: bool) -> Vec<u8> {
options.alphas.insert(AlphaOptim::Down);
options.alphas.insert(AlphaOptim::Left);
options.alphas.insert(AlphaOptim::Right);
options.interlace = Some(if interlace { 1 } else { 0 });
options.deflate = oxipng::Deflaters::Libdeflater;
oxipng::optimize_from_memory(data, &options).unwrap_throw()

View File

@ -0,0 +1,62 @@
use crossbeam_channel::{bounded, Receiver, Sender};
use once_cell::sync::OnceCell;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsValue;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = Array, js_name = of)]
fn array_of_2(a: JsValue, b: JsValue) -> JsValue;
}
// This is one of the parts that work around Chromium incorrectly implementing postMessage:
// https://bugs.chromium.org/p/chromium/issues/detail?id=1075645
//
// rayon::ThreadPoolBuilder (used below) executes spawn handler to populate the worker pool,
// and then blocks the current thread until each worker unblocks its (opaque) lock.
//
// Normally, we could use postMessage directly inside the spawn handler to
// post module + memory + threadPtr to each worker, and the block the current thread.
//
// However, that bug means that postMessage is currently delayed until the next event loop,
// which will never spin since we block the current thread, and so the other workers will
// never be able to unblock us.
//
// To work around this problem, we:
// 1) Expose `worker_initializer` that returns module + memory pair (without threadPtr)
// that workers can be initialised with to become native threads.
// JavaScript can postMessage this pair in advance, and asynchronously wait for workers
// to acknowledge the receipt.
// 2) Create a global communication channel on the Rust side using crossbeam.
// It will be used to send threadPtr to the pre-initialised workers
// instead of postMessage.
// 3) Provide a separate `start_main_thread` that expects all workers to be ready,
// and just uses the provided channel to send `threadPtr`s using the
// 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,
// reads one `threadPtr` from the shared channel and starts running it.
static CHANNEL: OnceCell<(Sender<rayon::ThreadBuilder>, Receiver<rayon::ThreadBuilder>)> =
OnceCell::new();
#[wasm_bindgen]
pub fn worker_initializer(num: usize) -> JsValue {
CHANNEL.get_or_init(|| bounded(num));
array_of_2(wasm_bindgen::module(), wasm_bindgen::memory())
}
#[wasm_bindgen]
pub fn start_main_thread() {
let (sender, _) = CHANNEL.get().unwrap();
rayon::ThreadPoolBuilder::new()
.num_threads(sender.capacity().unwrap())
.spawn_handler(|thread| Ok(sender.send(thread).unwrap_throw()))
.build_global()
.unwrap_throw()
}
#[wasm_bindgen]
pub fn start_worker_thread() {
let (_, receiver) = CHANNEL.get().unwrap();
receiver.recv().unwrap_throw().run()
}

View File

@ -0,0 +1,15 @@
FROM ubuntu:20.10
RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config curl build-essential
ENV WASI_SDK_VERSION "12"
ENV WASI_SDK_PREFIX "/opt/wasi-sdk"
RUN mkdir -p ${WASI_SDK_PREFIX} && \
curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION}/wasi-sdk-${WASI_SDK_VERSION}.0-linux.tar.gz | tar -xz --strip 1 -C /opt/wasi-sdk
ENV BINARYEN_PREFIX "/opt/binaryen"
RUN mkdir -p ${BINARYEN_PREFIX} && \
curl -L https://github.com/WebAssembly/binaryen/releases/download/version_101/binaryen-version_101-x86_64-linux.tar.gz | tar -xz --strip 1 -C ${BINARYEN_PREFIX}
# Maybe we need it later. Leaving it here for now.
# ENV WABT_PREFIX "/opt/wabt"
# RUN mkdir -p ${WABT_PREFIX} && \
# curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.23/wabt-1.0.23-ubuntu.tar.gz | tar -xz --strip 1 -C ${WABT_PREFIX}
WORKDIR /src
CMD ["sh", "-c", "make -j`nproc`"]

View File

@ -137,24 +137,10 @@ export default function (inputOptions, outputOptions, resolveFileUrl) {
const dependencies = getDependencies(clientOutput, clientEntry);
if (property.startsWith(allSrcPlaceholder)) {
const allModules = [
clientEntry,
...dependencies.map((name) =>
clientOutput.find((item) => item.fileName === name),
),
];
const inlineDefines = [
...allModules.map(
(item) =>
`self.nextDefineUri=location.origin+${resolveFileUrl(item)};${
item.code
}`,
),
'self.nextDefineUri=""',
];
return JSON.stringify(inlineDefines.join(''));
const depCodes = dependencies.map(
(name) => clientOutput.find((item) => item.fileName === name).code,
);
return JSON.stringify([clientEntry.code, ...depCodes].join(';'));
}
return (

View File

@ -48,7 +48,7 @@ const appendCssSource = `
}
`;
export default function () {
export default function (resolveFileUrl) {
/** @type {string[]} */
let emittedCSSIds;
/** @type {Map<string, string>} */

View File

@ -1,5 +1,5 @@
/**
* Copyright 2021 Google Inc. All Rights Reserved.
* 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
@ -13,63 +13,80 @@
// If the loader is already loaded, just stop.
if (!self.<%- amdFunctionName %>) {
let registry = {};
const singleRequire = async name => {
if (name === 'require') return require;
let url;
if (name.startsWith(location.origin)) {
url = name.slice(location.origin.length);
} else {
url = name.slice(1) + '.js';
}
if (!url.startsWith('/c/')) {
url = '/c' + url;
}
name = './static' + url;
if (registry[name]) return registry[name];
const singleRequire = (uri, parentUri) => {
uri = uri.startsWith(location.origin) ? uri : new URL(uri + ".js", parentUri).href;
return registry[uri] || (
if (!registry[name]) {
<% if (useEval) { %>
fetch(uri)
.then(resp => resp.text())
.then(code => {
self.nextDefineUri = uri;
eval(code);
})
const text = await fetch(url).then(resp => resp.text());
eval(text);
<% } else { %>
new Promise(resolve => {
if ("document" in self) {
if ("document" in self) {
await new Promise(resolve => {
const script = document.createElement("script");
script.src = uri;
script.onload = resolve;
script.src = url;
document.head.appendChild(script);
} else {
self.nextDefineUri = uri;
importScripts(uri);
resolve();
}
})
<% } %>
.then(() => {
let promise = registry[uri];
if (!promise) {
throw new Error(`Module ${uri} didnt register its module`);
script.onload = resolve;
});
} else {
importScripts(url);
}
return promise;
})
);
<% } %>
}
if (!registry[name]) {
throw new Error(`Module ${name} didnt register its module`);
}
return registry[name];
};
self.<%- amdFunctionName %> = (depsNames, factory) => {
const uri = self.nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
if (registry[uri]) {
const require = (names, resolve) => {
Promise.all(names.map(singleRequire))
.then(modules => resolve(modules.length === 1 ? modules[0] : modules));
};
const registry = {
require: Promise.resolve(require)
};
self.<%- amdFunctionName %> = (moduleName, depsNames, factory) => {
if (registry[moduleName]) {
// Module is already loading or loaded.
return;
}
let exports = {};
const require = depUri => singleRequire(depUri, uri);
const specialDeps = {
module: { uri },
exports,
require
};
// Note: Promise.resolve() is necessary to delay loading until all the
// `define`s on the current page had a chance to execute first.
// This allows to inline some deps on the main page.
registry[uri] = Promise.resolve().then(() => Promise.all(depsNames.map(
depName => specialDeps[depName] || require(depName)
))).then(deps => {
factory(...deps);
return exports;
registry[moduleName] = Promise.resolve().then(() => {
let exports = {};
const module = {
uri: location.origin + moduleName.slice(1)
};
return Promise.all(
depsNames.map(depName => {
switch(depName) {
case "exports":
return exports;
case "module":
return module;
default:
return singleRequire(depName);
}
})
).then(deps => {
const facValue = factory(...deps);
if (!exports.default) {
exports.default = facValue;
}
return exports;
});
});
};
}

View File

@ -1,3 +0,0 @@
node_modules
build
.DS_Store

View File

@ -1 +0,0 @@
node_modules

View File

View File

@ -1,163 +0,0 @@
# libSquoosh
libSquoosh is an _experimental_ way to run all the codecs you know from the [Squoosh] web app directly inside your own JavaScript program. libSquoosh uses a worker pool to parallelize processing images. This way you can apply the same codec to many images at once.
libSquoosh is currently not the fastest image compression tool in town and doesnt aim to be. It is, however, fast enough to compress many images sufficiently quick at once.
## Installation
libSquoosh can be installed to your local project with the following command:
```
$ npm install @squoosh/lib
```
You can start using the libSquoosh by adding these lines to the top of your JS program:
```js
import { ImagePool } from '@squoosh/lib';
const imagePool = new ImagePool();
```
This will create an image pool with an underlying processing pipeline that you can use to ingest and encode images. The ImagePool constructor takes one argument that defines how many parallel operations it is allowed to run at any given time. By default, this number is set to the amount of CPU cores available in the system it is running on.
## Ingesting images
You can ingest a new image like so:
```js
const imagePath = 'path/to/image.png';
const image = imagePool.ingestImage(imagePath);
```
The `ingestImage` function can take anything the node [`readFile`][readfile] function can take, uncluding a buffer and `FileHandle`.
The returned `image` object is a representation of the original image, that you can now preprocess, encode, and extract information about.
## Preprocessing and encoding images
When an image has been ingested, you can start preprocessing it and encoding it to other formats. This example will resize the image and then encode it to a `.jpg` and `.jxl` image:
```js
await image.decoded; //Wait until the image is decoded before running preprocessors
const preprocessOptions: {
resize: {
enabled: true,
width: 100,
height: 50,
}
}
await image.preprocess(preprocessOptions);
const encodeOptions: {
mozjpeg: {}, //an empty object means 'use default settings'
jxl: {
quality: 90,
},
}
await image.encode(encodeOptions);
```
The default values for each option can be found in the [`codecs.js`][codecs.js] file under `defaultEncoderOptions`. Every unspecified value will use the default value specified there. _Better documentation is needed here._
You can run your own code inbetween the different steps, if, for example, you want to change how much the image should be resized based on its original height. (See [Extracting image information](#extracting-image-information) to learn how to get the image dimensions).
## Closing the ImagePool
When you have encoded everything you need, it is recommended to close the processing pipeline in the ImagePool. This will not delete the images you have already encoded, but it will prevent you from ingesting and encoding new images.
Close the ImagePool pipeline with this line:
```js
await imagePool.close();
```
## Writing encoded images to the file system
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:
```js
const rawEncodedImage = (await image.encodedWidth.mozjpeg).binary;
fs.writeFile('/path/to/new/image.jpg', rawEncodedImage);
```
This example iterates through all encoded versions of the image and writes them to a specific path:
```js
const newImagePath = '/path/to/image.'; //extension is added automatically
for (const encodedImage of Object.values(image.encodedWith)) {
fs.writeFile(
newImagePath + (await encodedImage).extension,
(await encodedImage).binary,
);
}
```
## Extracting image information
Information about a decoded image is available at `Image.decoded`. It looks something like this:
```js
console.log(await image.decoded);
// Returns:
{
bitmap: {
data: Uint8ClampedArray(47736584) [
225, 228, 237, 255, 225, 228, 237, 255, 225, 228, 237, 255,
225, 228, 237, 255, 225, 228, 237, 255, 225, 228, 237, 255,
225, 228, 237, 255,
... //the entire raw image
],
width: 4606, //pixels
height: 2591 //pixels
},
size: 2467795 //bytes
}
```
Information about an encoded image can be found at `Image.encodedWith[encoderName]`. It looks something like this:
```js
console.log(await image.encodedWith.jxl);
// Returns:
{
optionsUsed: {
quality: 75,
baseline: false,
arithmetic: false,
progressive: true,
... //all the possible options for this encoder
},
binary: Uint8Array(1266975) [
1, 0, 0, 1, 0, 1, 0, 0, 255, 219, 0, 132,
113, 119, 156, 156, 209, 1, 8, 8, 8, 8, 9, 8,
9, 10, 10, 9,
... //the entire raw encoded image
],
extension: 'jxl',
size: 1266975 //bytes
}
```
## Auto optimizer
libSquoosh has an _experimental_ auto optimizer that compresses an image as much as possible, trying to hit a specific [Butteraugli] target value. The higher the Butteraugli target value, the more artifacts can be introduced.
You can make use of the auto optimizer by using “auto” as the config object.
```js
const encodeOptions: {
mozjpeg: 'auto',
}
```
[squoosh]: https://squoosh.app
[codecs.js]: https://github.com/GoogleChromeLabs/squoosh/blob/dev/libsquoosh/src/codecs.js
[butteraugli]: https://github.com/google/butteraugli
[readfile]: https://nodejs.org/api/fs.html#fs_fspromises_readfile_path_options

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +0,0 @@
{
"name": "@squoosh/lib",
"version": "0.2.1",
"description": "A Node library for Squoosh",
"public": true,
"main": "/build/index.js",
"files": [
"/build/*"
],
"scripts": {
"build": "rollup -c"
},
"keywords": [],
"author": "Google Chrome Developers <chromium-dev@google.com>",
"license": "Apache-2.0",
"dependencies": {
"web-streams-polyfill": "^3.0.3"
},
"devDependencies": {
"@babel/core": "^7.14.0",
"@babel/preset-env": "^7.14.0",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"rollup": "^2.46.0",
"rollup-plugin-terser": "^7.0.2"
}
}

View File

@ -1,209 +0,0 @@
import { isMainThread } from 'worker_threads';
import { cpus } from 'os';
import { promises as fsp } from 'fs';
import { codecs as encoders, preprocessors } from './codecs.js';
import WorkerPool from './worker_pool.js';
import { autoOptimize } from './auto-optimizer.js';
export { ImagePool, encoders, preprocessors };
async function decodeFile({ file }) {
const buffer = await fsp.readFile(file);
const firstChunk = buffer.slice(0, 16);
const firstChunkString = Array.from(firstChunk)
.map((v) => String.fromCodePoint(v))
.join('');
const key = Object.entries(encoders).find(([name, { detectors }]) =>
detectors.some((detector) => detector.exec(firstChunkString)),
)?.[0];
if (!key) {
throw Error(`${file} has an unsupported format`);
}
const rgba = (await encoders[key].dec()).decode(new Uint8Array(buffer));
return {
bitmap: rgba,
size: buffer.length,
};
}
async function preprocessImage({ preprocessorName, options, image }) {
const preprocessor = await preprocessors[preprocessorName].instantiate();
image.bitmap = await preprocessor(
image.bitmap.data,
image.bitmap.width,
image.bitmap.height,
options,
);
return image;
}
async function encodeImage({
bitmap: bitmapIn,
encName,
encConfig,
optimizerButteraugliTarget,
maxOptimizerRounds,
}) {
let binary;
let optionsUsed = encConfig;
const encoder = await encoders[encName].enc();
if (encConfig === 'auto') {
const optionToOptimize = encoders[encName].autoOptimize.option;
const decoder = await encoders[encName].dec();
const encode = (bitmapIn, quality) =>
encoder.encode(
bitmapIn.data,
bitmapIn.width,
bitmapIn.height,
Object.assign({}, encoders[encName].defaultEncoderOptions, {
[optionToOptimize]: quality,
}),
);
const decode = (binary) => decoder.decode(binary);
const { binary: optimizedBinary, quality } = await autoOptimize(
bitmapIn,
encode,
decode,
{
min: encoders[encName].autoOptimize.min,
max: encoders[encName].autoOptimize.max,
butteraugliDistanceGoal: optimizerButteraugliTarget,
maxRounds: maxOptimizerRounds,
},
);
binary = optimizedBinary;
optionsUsed = {
// 5 significant digits is enough
[optionToOptimize]: Math.round(quality * 10000) / 10000,
};
} else {
binary = encoder.encode(
bitmapIn.data.buffer,
bitmapIn.width,
bitmapIn.height,
encConfig,
);
}
return {
optionsUsed,
binary,
extension: encoders[encName].extension,
size: binary.length,
};
}
// both decoding and encoding go through the worker pool
function handleJob(params) {
const { operation } = params;
switch (operation) {
case 'encode':
return encodeImage(params);
case 'decode':
return decodeFile(params);
case 'preprocess':
return preprocessImage(params);
default:
throw Error(`Invalid job "${operation}"`);
}
}
/**
* Represents an ingested image.
*/
class Image {
constructor(workerPool, file) {
this.workerPool = workerPool;
this.decoded = workerPool.dispatchJob({ operation: 'decode', file });
this.encodedWith = {};
}
/**
* Define one or several preprocessors to use on the image.
* @param {object} preprocessOptions - An object with preprocessors to use, and their settings.
* @returns {Promise<undefined>} - A promise that resolves when all preprocessors have completed their work.
*/
async preprocess(preprocessOptions = {}) {
for (const [name, options] of Object.entries(preprocessOptions)) {
if (!Object.keys(preprocessors).includes(name)) {
throw Error(`Invalid preprocessor "${name}"`);
}
const preprocessorOptions = Object.assign(
{},
preprocessors[name].defaultOptions,
options,
);
this.decoded = this.workerPool.dispatchJob({
operation: 'preprocess',
preprocessorName: name,
image: await this.decoded,
options: preprocessorOptions,
});
await this.decoded;
}
}
/**
* Define one or several encoders to use on the image.
* @param {object} encodeOptions - An object with encoders to use, and their settings.
* @returns {Promise<undefined>} - A promise that resolves when the image has been encoded with all the specified encoders.
*/
async encode(encodeOptions = {}) {
const { bitmap } = await this.decoded;
for (const [encName, options] of Object.entries(encodeOptions)) {
if (!Object.keys(encoders).includes(encName)) {
continue;
}
const encRef = encoders[encName];
const encConfig =
typeof options === 'string'
? options
: Object.assign({}, encRef.defaultEncoderOptions, options);
this.encodedWith[encName] = this.workerPool.dispatchJob({
operation: 'encode',
bitmap,
encName,
encConfig,
optimizerButteraugliTarget: Number(
encodeOptions.optimizerButteraugliTarget,
),
maxOptimizerRounds: Number(encodeOptions.maxOptimizerRounds),
});
}
await Promise.all(Object.values(this.encodedWith));
}
}
/**
* A pool where images can be ingested and squooshed.
*/
class ImagePool {
/**
* Create a new pool.
* @param {number} [threads] - Number of concurrent image processes to run in the pool. Defaults to the number of CPU cores in the system.
*/
constructor(threads) {
this.workerPool = new WorkerPool(threads || cpus().length, __filename);
}
/**
* Ingest an image into the image pool.
* @param {string | Buffer | URL | object} image - The image or path to the image that should be ingested and decoded.
* @returns {Image} - A custom class reference to the decoded image.
*/
ingestImage(image) {
return new Image(this.workerPool, image);
}
/**
* Closes the underlying image processing pipeline. The already processed images will still be there, but no new processing can start.
* @returns {Promise<undefined>} - A promise that resolves when the underlying pipeline has closed.
*/
async close() {
await this.workerPool.join();
}
}
if (!isMainThread) {
WorkerPool.useThisThreadAsWorker(handleJob);
}

110
package-lock.json generated
View File

@ -179,25 +179,13 @@
}
},
"@surma/rollup-plugin-off-main-thread": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.1.tgz",
"integrity": "sha512-7OU8wfyv18YPWVmecg2/0Jh+pm3lQbvPhIWHd1YQpoxPKPW/vsDNGBaCnMKsZbz29RjgCoXKugAjyagPncgdEw==",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz",
"integrity": "sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A==",
"dev": true,
"requires": {
"ejs": "^3.1.6",
"json5": "^2.2.0",
"ejs": "^2.6.1",
"magic-string": "^0.25.0"
},
"dependencies": {
"json5": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
}
}
},
"@types/color-name": {
@ -417,12 +405,6 @@
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"dev": true
},
"async": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@ -1615,13 +1597,10 @@
}
},
"ejs": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
"integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
"dev": true,
"requires": {
"jake": "^10.6.1"
}
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
"dev": true
},
"electron-to-chromium": {
"version": "1.3.538",
@ -1818,15 +1797,6 @@
"integrity": "sha512-na2cwntTVgMsR+BZ2YBr/XQk941DKDw2LJKbV7g6TRdGBQ3rx8V53oEviG8zPWoBOySwK9w/SlZ/gb/F/48I8A==",
"dev": true
},
"filelist": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
"integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
"dev": true,
"requires": {
"minimatch": "^3.0.4"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@ -2336,70 +2306,6 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"jake": {
"version": "10.8.2",
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
"dev": true,
"requires": {
"async": "0.9.x",
"chalk": "^2.4.2",
"filelist": "^1.0.1",
"minimatch": "^3.0.4"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"jest-worker": {
"version": "26.3.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz",

View File

@ -14,7 +14,7 @@
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.1.0",
"@rollup/plugin-replace": "^2.3.4",
"@surma/rollup-plugin-off-main-thread": "^2.2.1",
"@surma/rollup-plugin-off-main-thread": "^1.4.2",
"@types/dedent": "^0.7.0",
"@types/mime-types": "^2.1.0",
"@types/node": "^14.14.7",

View File

@ -37,6 +37,13 @@ function resolveFileUrl({ fileName }) {
return JSON.stringify(fileName.replace(/^static\//, '/'));
}
// With AMD output, Rollup always uses document.baseURI, which breaks in workers.
// This fixes it:
function resolveImportMeta(property, { chunkId }) {
if (property !== 'url') return;
return `new URL(${resolveFileUrl({ fileName: chunkId })}, location).href`;
}
const dir = '.tmp/build';
const staticPath = 'static/c/[name]-[hash][extname]';
const jsPath = staticPath.replace('[extname]', '.js');
@ -55,7 +62,6 @@ export default async function ({ watch }) {
path.join(__dirname, 'lib', 'omt.ejs'),
'utf-8',
);
await del('.tmp/build');
const isProduction = !watch;
@ -77,7 +83,7 @@ export default async function ({ watch }) {
]),
urlPlugin(),
dataURLPlugin(),
cssPlugin(),
cssPlugin(resolveFileUrl),
];
return {
@ -99,12 +105,12 @@ export default async function ({ watch }) {
},
preserveModules: true,
plugins: [
{ resolveFileUrl },
{ resolveFileUrl, resolveImportMeta },
clientBundlePlugin(
{
external: ['worker_threads'],
plugins: [
{ resolveFileUrl },
{ resolveFileUrl, resolveImportMeta },
OMT({ loader: await omtLoaderPromise }),
serviceWorkerPlugin({
output: 'static/serviceworker.js',

View File

@ -32,6 +32,7 @@ import Results from './Results';
import WorkerBridge from '../worker-bridge';
import { resize } from 'features/processors/resize/client';
import type SnackBarElement from 'shared/custom-els/snack-bar';
import { Arrow, ExpandIcon } from '../icons';
import { generateCliInvocation } from '../util/cli';
export type OutputType = EncoderType | 'identity';
@ -69,6 +70,7 @@ interface State {
sides: [Side, Side];
/** Source image load */
loading: boolean;
error?: string;
mobileView: boolean;
preprocessorState: PreprocessorState;
encodedPreprocessorState?: PreprocessorState;
@ -107,9 +109,9 @@ async function decodeImage(
if (mimeType === 'image/webp2') {
return await workerBridge.wp2Decode(signal, blob);
}
// If it's not one of those types, fall through and try built-in decoding for a laugh.
}
// Otherwise fall through and try built-in decoding for a laugh.
return await builtinDecode(signal, blob, mimeType);
return await abortable(signal, builtinDecode(blob));
} catch (err) {
if (err.name === 'AbortError') throw err;
console.log(err);
@ -257,6 +259,11 @@ function processorStateEquivalent(a: ProcessorState, b: ProcessorState) {
return true;
}
// These are only used in the mobile view
const resultTitles = ['Top', 'Bottom'] as const;
// These are only used in the desktop view
const buttonPositions = ['download-left', 'download-right'] as const;
const originalDocumentTitle = document.title;
function updateDocumentTitle(filename: string = ''): void {

View File

@ -10,9 +10,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import * as WebCodecs from '../util/web-codecs';
/**
* Compare two objects, returning a boolean indicating if
* they have the same properties and strictly equal values.
@ -195,35 +192,17 @@ interface DrawableToImageDataOptions {
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,
drawable: ImageBitmap | HTMLImageElement,
opts: DrawableToImageDataOptions = {},
): ImageData {
const {
width = getWidth(drawable),
height = getHeight(drawable),
width = drawable.width,
height = drawable.height,
sx = 0,
sy = 0,
sw = getWidth(drawable),
sh = getHeight(drawable),
sw = drawable.width,
sh = drawable.height,
} = opts;
// Make canvas same size as image
@ -237,25 +216,13 @@ export function drawableToImageData(
return ctx.getImageData(0, 0, width, height);
}
export async function builtinDecode(
signal: AbortSignal,
blob: Blob,
mimeType: string,
): Promise<ImageData> {
// If WebCodecs are supported, use that.
if (await WebCodecs.isTypeSupported(mimeType)) {
assertSignal(signal);
try {
return await abortable(signal, WebCodecs.decode(blob, mimeType));
} catch (e) {}
}
assertSignal(signal);
export async function builtinDecode(blob: Blob): Promise<ImageData> {
// Prefer createImageBitmap as it's the off-thread option for Firefox.
const drawable = await abortable<HTMLImageElement | ImageBitmap>(
signal,
'createImageBitmap' in self ? createImageBitmap(blob) : blobToImg(blob),
);
const drawable =
'createImageBitmap' in self
? await createImageBitmap(blob)
: await blobToImg(blob);
return drawableToImageData(drawable);
}

View File

@ -1,26 +0,0 @@
import { drawableToImageData } from 'client/lazy-app/util';
const hasImageDecoder = typeof ImageDecoder !== 'undefined';
export async function isTypeSupported(mimeType: string): Promise<boolean> {
if (!hasImageDecoder) {
return false;
}
return ImageDecoder.isTypeSupported(mimeType);
}
export async function decode(
blob: Blob | File,
mimeType: string,
): Promise<ImageData> {
if (!hasImageDecoder) {
throw Error(
`This browser does not support ImageDecoder. This function should not have been called.`,
);
}
const decoder = new ImageDecoder({
type: mimeType,
// Non-obvious way to turn an Blob into a ReadableStream
data: new Response(blob).body!,
});
const { image } = await decoder.decode();
return drawableToImageData(image);
}

View File

@ -1,60 +0,0 @@
interface ImageDecoderInit {
type: string;
data: BufferSource | ReadableStream;
premultiplyAlpha?: PremultiplyAlpha;
colorSpaceConversion?: ColorSpaceConversion;
desiredWidth?: number;
desiredHeight?: number;
preferAnimation?: boolean;
}
interface ImageDecodeOptions {
frameIndex: number;
completeFramesOnly: boolean;
}
interface ImageDecodeResult {
image: VideoFrame;
complete: boolean;
}
// I didnt do all the types because the class is kinda complex.
// I focused on what we need.
// See https://w3c.github.io/webcodecs/#videoframe
declare class VideoFrame {
displayWidth: number;
displayHeight: number;
}
// Add VideoFrame to canvas drawImage()
interface CanvasDrawImage {
drawImage(
image: CanvasImageSource | VideoFrame,
dx: number,
dy: number,
): void;
drawImage(
image: CanvasImageSource | VideoFrame,
dx: number,
dy: number,
dw: number,
dh: number,
): void;
drawImage(
image: CanvasImageSource | VideoFrame,
sx: number,
sy: number,
sw: number,
sh: number,
dx: number,
dy: number,
dw: number,
dh: number,
): void;
}
declare class ImageDecoder {
static isTypeSupported(type: string): Promise<boolean>;
constructor(desc: ImageDecoderInit);
decode(opts?: Partial<ImageDecodeOptions>): Promise<ImageDecodeResult>;
}

View File

@ -1,4 +1,4 @@
import { EncodeOptions, defaultOptions, AVIFTune } from '../shared/meta';
import { EncodeOptions, defaultOptions } from '../shared/meta';
import type WorkerBridge from 'client/lazy-app/worker-bridge';
import { h, Component } from 'preact';
import { preventDefault, shallowEqual } from 'client/lazy-app/util';
@ -37,7 +37,7 @@ interface State {
sharpness: number;
denoiseLevel: number;
aqMode: number;
tune: AVIFTune;
tune: 'ssim' | 'psnr';
}
const maxQuant = 63;
@ -82,7 +82,7 @@ export class Options extends Component<Props, State> {
chromaDeltaQ: options.chromaDeltaQ,
sharpness: options.sharpness,
denoiseLevel: options.denoiseLevel,
tune: options.tune,
tune: options.targetSsim ? 'ssim' : 'psnr',
};
}
@ -133,7 +133,7 @@ export class Options extends Component<Props, State> {
chromaDeltaQ: optionState.chromaDeltaQ,
sharpness: optionState.sharpness,
denoiseLevel: optionState.denoiseLevel,
tune: optionState.tune,
targetSsim: optionState.tune === 'ssim',
};
// Updating options, so we don't recalculate in getDerivedStateFromProps.
@ -268,14 +268,13 @@ export class Options extends Component<Props, State> {
</Range>
</div>
<label class={style.optionTextFirst}>
Tuning:
Tune for:
<Select
value={tune}
onChange={this._inputChange('tune', 'number')}
onChange={this._inputChange('tune', 'string')}
>
<option value={AVIFTune.auto}>Auto</option>
<option value={AVIFTune.psnr}>PSNR</option>
<option value={AVIFTune.ssim}>SSIM</option>
<option value="psnr">PSNR</option>
<option value="ssim">SSIM</option>
</Select>
</label>
</div>

View File

@ -10,9 +10,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { EncodeOptions, AVIFTune } from 'codecs/avif/enc/avif_enc';
import type { EncodeOptions } from 'codecs/avif/enc/avif_enc';
export { EncodeOptions, AVIFTune };
export { EncodeOptions };
export const label = 'AVIF';
export const mimeType = 'image/avif';
@ -27,5 +27,5 @@ export const defaultOptions: EncodeOptions = {
subsample: 1,
chromaDeltaQ: false,
sharpness: 0,
tune: AVIFTune.auto,
targetSsim: false,
};

View File

@ -28,7 +28,6 @@ interface State {
lossless: boolean;
slightLoss: boolean;
autoEdgePreservingFilter: boolean;
decodingSpeedTier: number;
}
const maxSpeed = 7;
@ -54,7 +53,6 @@ export class Options extends Component<Props, State> {
lossless: options.quality === 100,
slightLoss: options.lossyPalette,
autoEdgePreservingFilter: options.epf === -1,
decodingSpeedTier: options.decodingSpeedTier,
};
}
@ -95,7 +93,6 @@ export class Options extends Component<Props, State> {
: optionState.edgePreservingFilter,
nearLossless: 0,
lossyPalette: optionState.lossless ? optionState.slightLoss : false,
decodingSpeedTier: optionState.decodingSpeedTier,
};
// Updating options, so we don't recalculate in getDerivedStateFromProps.
@ -120,7 +117,6 @@ export class Options extends Component<Props, State> {
lossless,
slightLoss,
autoEdgePreservingFilter,
decodingSpeedTier,
}: State,
) {
// I'm rendering both lossy and lossless forms, as it becomes much easier when
@ -189,16 +185,6 @@ export class Options extends Component<Props, State> {
</div>
)}
</Expander>
<div class={style.optionOneCell}>
<Range
min="0"
max="4"
value={decodingSpeedTier}
onInput={this._inputChange('decodingSpeedTier', 'number')}
>
Optimise for decoding speed (worse compression):
</Range>
</div>
</div>
)}
</Expander>

View File

@ -24,5 +24,4 @@ export const defaultOptions: EncodeOptions = {
epf: -1,
nearLossless: 0,
lossyPalette: false,
decodingSpeedTier: 0,
};

View File

@ -14,17 +14,28 @@ import type { JXLModule } from 'codecs/jxl/enc/jxl_enc';
import type { EncodeOptions } from '../shared/meta';
import { initEmscriptenModule } from 'features/worker-utils';
import { threads } from 'wasm-feature-detect';
import { threads, simd } from 'wasm-feature-detect';
import wasmUrl from 'url:codecs/jxl/enc/jxl_enc.wasm';
import wasmUrlWithMT from 'url:codecs/jxl/enc/jxl_enc_mt.wasm';
import workerUrl from 'omt:codecs/jxl/enc/jxl_enc_mt.worker.js';
import wasmUrlWithMTAndSIMD from 'url:codecs/jxl/enc/jxl_enc_mt_simd.wasm';
import workerUrlWithSIMD from 'omt:codecs/jxl/enc/jxl_enc_mt_simd.worker.js';
let emscriptenModule: Promise<JXLModule>;
async function init() {
if (await threads()) {
if (await simd()) {
const jxlEncoder = await import('codecs/jxl/enc/jxl_enc_mt_simd');
return initEmscriptenModule(
jxlEncoder.default,
wasmUrlWithMTAndSIMD,
workerUrlWithSIMD,
);
}
const jxlEncoder = await import('codecs/jxl/enc/jxl_enc_mt');
return initEmscriptenModule(jxlEncoder.default, wasmUrlWithMT, workerUrl);
}

View File

@ -13,8 +13,9 @@
import {
EncodeOptions,
MozJpegColorSpace,
MozJPEGModuleExports,
} from 'codecs/mozjpeg/enc/mozjpeg_enc';
export { EncodeOptions, MozJpegColorSpace };
export { EncodeOptions, MozJpegColorSpace, MozJPEGModuleExports };
export const label = 'MozJPEG';
export const mimeType = 'image/jpeg';

View File

@ -10,23 +10,44 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mozjpeg_enc, { MozJPEGModule } from 'codecs/mozjpeg/enc/mozjpeg_enc';
import { EncodeOptions } from '../shared/meta';
import { MozJPEGModuleExports, EncodeOptions } from '../shared/meta';
import wasmUrl from 'url:codecs/mozjpeg/enc/mozjpeg_enc.wasm';
import { initEmscriptenModule } from 'features/worker-utils';
import { instantiateStreaming } from 'features/worker-utils';
import {
makeEverythingElseThrow,
makeWasiEnv,
} from 'features/worker-utils/wasi-utils';
let emscriptenModule: Promise<MozJPEGModule>;
const instancePromise: Promise<WebAssembly.Instance> = instantiateStreaming(
fetch(wasmUrl),
{
wasi_snapshot_preview1: makeEverythingElseThrow(makeWasiEnv()),
},
).then(({ instance }) => instance);
export default async function encode(
data: ImageData,
options: EncodeOptions,
): Promise<ArrayBuffer> {
if (!emscriptenModule) {
emscriptenModule = initEmscriptenModule(mozjpeg_enc, wasmUrl);
}
const instance = await instancePromise;
const exports: MozJPEGModuleExports = (instance.exports as unknown) as MozJPEGModuleExports;
const module = await emscriptenModule;
const resultView = module.encode(data.data, data.width, data.height, options);
for (const [opt, value] of Object.entries(options)) {
// @ts-ignore Cant be bothered to make these typings works
exports[`set_opts_${opt}`](value);
}
const inPtr = exports.alloc(data.data.byteLength);
new Uint8ClampedArray(exports.memory.buffer, inPtr, data.data.length).set(
data.data,
);
const resultPtr = exports.encode(inPtr, data.width, data.height);
const dv = new DataView(exports.memory.buffer);
const length = dv.getUint32(resultPtr, true);
const outPtr = dv.getUint32(resultPtr + 4, true);
const result = new Uint8Array(exports.memory.buffer, outPtr, length).slice();
exports.dealloc(inPtr);
exports.dealloc(outPtr);
exports.dealloc(resultPtr);
// wasm cant run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
return resultView.buffer as ArrayBuffer;
return result.buffer;
}

View File

@ -2,7 +2,6 @@ import {
canvasEncode,
abortable,
blobToArrayBuffer,
inputFieldChecked,
} from 'client/lazy-app/util';
import { EncodeOptions } from '../shared/meta';
import type WorkerBridge from 'client/lazy-app/worker-bridge';
@ -10,7 +9,6 @@ import { h, Component } from 'preact';
import { inputFieldValueAsNumber, preventDefault } from 'client/lazy-app/util';
import * as style from 'client/lazy-app/Compress/Options/style.css';
import Range from 'client/lazy-app/Compress/Options/Range';
import Checkbox from 'client/lazy-app/Compress/Options/Checkbox';
export async function encode(
signal: AbortSignal,
@ -36,7 +34,6 @@ export class Options extends Component<Props, {}> {
const options: EncodeOptions = {
level: inputFieldValueAsNumber(form.level),
interlace: inputFieldChecked(form.interlace),
};
this.props.onChange(options);
};
@ -44,14 +41,6 @@ export class Options extends Component<Props, {}> {
render({ options }: Props) {
return (
<form class={style.optionsSection} onSubmit={preventDefault}>
<label class={style.optionToggle}>
Interlace
<Checkbox
name="interlace"
checked={options.interlace}
onChange={this.onChange}
/>
</label>
<div class={style.optionOneCell}>
<Range
name="level"

View File

@ -12,7 +12,6 @@
*/
export interface EncodeOptions {
level: number;
interlace: boolean;
}
export const label = 'OxiPNG';
@ -21,5 +20,4 @@ export const extension = 'png';
export const defaultOptions: EncodeOptions = {
level: 2,
interlace: false,
};

View File

@ -14,17 +14,54 @@ import initOxiWasmST, {
optimise as optimiseST,
} from 'codecs/oxipng/pkg/squoosh_oxipng';
import initOxiWasmMT, {
initThreadPool,
worker_initializer,
start_main_thread,
optimise as optimiseMT,
} from 'codecs/oxipng/pkg-parallel/squoosh_oxipng';
import oxiWasmUrlST from 'url:codecs/oxipng/pkg/squoosh_oxipng_bg.wasm';
import oxiWasmUrlMT from 'url:codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm';
import { EncodeOptions } from '../shared/meta';
import { threads } from 'wasm-feature-detect';
import workerURL from 'omt:./sub-worker';
import type { WorkerInit } from './sub-worker';
function initWorker(worker: Worker, workerInit: WorkerInit) {
return new Promise<void>((resolve) => {
worker.postMessage(workerInit);
worker.addEventListener('message', () => resolve(), { once: true });
});
}
async function initMT() {
const num = navigator.hardwareConcurrency;
// First, let browser fetch and spawn Workers for our pool in the background.
// This is fairly expensive, so we want to start it as early as possible.
const workers = Array.from({ length: num }, () => new Worker(workerURL));
// Meanwhile, asynchronously compile, instantiate and initialise Wasm on our main thread.
await initOxiWasmMT(oxiWasmUrlMT);
await initThreadPool(navigator.hardwareConcurrency);
// Get module+memory from the Wasm instance.
//
// Ideally we wouldn't go via Wasm bindings here, since both are just JS variables, but memory is
// currently not exposed on the Wasm instance correctly by wasm-bindgen.
const workerInit: WorkerInit = worker_initializer(num);
// Once done, we want to send module+memory to each Worker so that they instantiate Wasm too.
// While doing so, we need to wait for Workers to acknowledge that they have received our message.
// Ideally this shouldn't be necessary, but Chromium currently doesn't conform to the spec:
// https://bugs.chromium.org/p/chromium/issues/detail?id=1075645
//
// If we didn't do this ping-pong game, the `start_main_thread` below would block the current
// thread on an atomic before even *sending* the `postMessage` containing memory,
// so Workers would never be able to unblock us back.
await Promise.all(workers.map((worker) => initWorker(worker, workerInit)));
// Finally, instantiate rayon pool - this will use shared Wasm memory to send tasks to the
// Workers and then block until they're all ready.
start_main_thread();
return optimiseMT;
}
@ -40,12 +77,9 @@ export default async function encode(
options: EncodeOptions,
): Promise<ArrayBuffer> {
if (!wasmReady) {
wasmReady = threads().then((hasThreads: boolean) =>
hasThreads ? initMT() : initST(),
);
wasmReady = (await threads()) ? initMT() : initST();
}
const optimise = await wasmReady;
return optimise(new Uint8Array(data), options.level, options.interlace)
.buffer;
return optimise(new Uint8Array(data), options.level).buffer;
}

View File

@ -0,0 +1,25 @@
import initOxiPNG, {
start_worker_thread,
} from 'codecs/oxipng/pkg-parallel/squoosh_oxipng';
export type WorkerInit = [WebAssembly.Module, WebAssembly.Memory];
addEventListener(
'message',
async (event) => {
// Tell the "main" thread that we've received the message.
//
// At this point, the "main" thread can run Wasm that
// will synchronously block waiting on other atomics.
//
// Note that we don't need to wait for Wasm instantiation here - it's
// better to start main thread as early as possible, and then it blocks
// on a shared atomic anyway until Worker is fully ready.
// @ts-ignore
postMessage(null);
await initOxiPNG(...(event.data as WorkerInit));
start_worker_thread();
},
{ once: true },
);

View File

@ -14,12 +14,18 @@ import type { WebPModule } from 'codecs/webp/enc/webp_enc';
import type { EncodeOptions } from '../shared/meta';
import { initEmscriptenModule } from 'features/worker-utils';
import { simd } from 'wasm-feature-detect';
import wasmUrl from 'url:codecs/webp/enc/webp_enc.wasm';
import wasmUrlWithSIMD from 'url:codecs/webp/enc/webp_enc_simd.wasm';
let emscriptenModule: Promise<WebPModule>;
async function init() {
if (await simd()) {
const webpEncoder = await import('codecs/webp/enc/webp_enc_simd');
return initEmscriptenModule(webpEncoder.default, wasmUrlWithSIMD);
}
const webpEncoder = await import('codecs/webp/enc/webp_enc');
return initEmscriptenModule(webpEncoder.default, wasmUrl);
}

View File

@ -14,17 +14,28 @@ import type { WP2Module } from 'codecs/wp2/enc/wp2_enc';
import type { EncodeOptions } from '../shared/meta';
import { initEmscriptenModule } from 'features/worker-utils';
import { threads } from 'wasm-feature-detect';
import { threads, simd } from 'wasm-feature-detect';
import wasmUrl from 'url:codecs/wp2/enc/wp2_enc.wasm';
import wasmUrlWithMT from 'url:codecs/wp2/enc/wp2_enc_mt.wasm';
import workerUrl from 'omt:codecs/wp2/enc/wp2_enc_mt.worker.js';
import wasmUrlWithMTAndSIMD from 'url:codecs/wp2/enc/wp2_enc_mt_simd.wasm';
import workerUrlWithSIMD from 'omt:codecs/wp2/enc/wp2_enc_mt_simd.worker.js';
let emscriptenModule: Promise<WP2Module>;
async function init() {
if (await threads()) {
if (await simd()) {
const wp2Encoder = await import('codecs/wp2/enc/wp2_enc_mt_simd');
return initEmscriptenModule(
wp2Encoder.default,
wasmUrlWithMTAndSIMD,
workerUrlWithSIMD,
);
}
const wp2Encoder = await import('codecs/wp2/enc/wp2_enc_mt');
return initEmscriptenModule(wp2Encoder.default, wasmUrlWithMT, workerUrl);
}

View File

@ -29,3 +29,16 @@ export function initEmscriptenModule<T extends EmscriptenWasm.Module>(
export function blobToArrayBuffer(blob: Blob): Promise<ArrayBuffer> {
return new Response(blob).arrayBuffer();
}
export async function instantiateStreaming(
resp: Response | PromiseLike<Response>,
importObj?: WebAssembly.Imports,
): Promise<WebAssembly.WebAssemblyInstantiatedSource> {
if (WebAssembly.instantiateStreaming) {
return WebAssembly.instantiateStreaming(resp, importObj);
}
return WebAssembly.instantiate(
await Promise.resolve(resp).then((r) => r.arrayBuffer()),
importObj,
);
}

View File

@ -0,0 +1,32 @@
/**
* Copyright 2021 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.
*/
export function makeEverythingElseThrow(obj: { [x: string]: {} }): {} {
return new Proxy(obj, {
get(target, prop: string) {
if (prop in target) {
return target[prop];
}
return () => {
throw Error(`${prop} not implemented`);
};
},
});
}
export function makeWasiEnv() {
return {
environ_sizes_get: () => 0,
environ_get: () => 0,
};
}

View File

@ -1,4 +1,4 @@
import { threads } from 'wasm-feature-detect';
import { threads, simd } from 'wasm-feature-detect';
import webpDataUrl from 'data-url:./tiny.webp';
import avifDataUrl from 'data-url:./tiny.avif';
@ -75,6 +75,9 @@ import avifEncWasm from 'url:codecs/avif/enc/avif_enc.wasm';
import * as avifEnc from 'entry-data:codecs/avif/enc/avif_enc.js';
// JXL
import * as jxlEncMtSimdWorker from 'entry-data:codecs/jxl/enc/jxl_enc_mt_simd.worker.js';
import * as jxlEncMtSimd from 'entry-data:codecs/jxl/enc/jxl_enc_mt_simd';
import jxlEncMtSimdWasm from 'url:codecs/jxl/enc/jxl_enc_mt_simd.wasm';
import * as jxlEncMtWorker from 'entry-data:codecs/jxl/enc/jxl_enc_mt.worker.js';
import * as jxlEncMt from 'entry-data:codecs/jxl/enc/jxl_enc_mt';
import jxlEncMtWasm from 'url:codecs/jxl/enc/jxl_enc_mt.wasm';
@ -82,14 +85,20 @@ import jxlEncWasm from 'url:codecs/jxl/enc/jxl_enc.wasm';
import * as jxlEnc from 'entry-data:codecs/jxl/enc/jxl_enc';
// OXI
import * as oxiMtWorker from 'entry-data:features/encoders/oxiPNG/worker/sub-worker';
import oxiMtWasm from 'url:codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm';
import oxiWasm from 'url:codecs/oxipng/pkg/squoosh_oxipng_bg.wasm';
// WebP
import * as webpEncSimd from 'entry-data:codecs/webp/enc/webp_enc_simd';
import webpEncSimdWasm from 'url:codecs/webp/enc/webp_enc_simd.wasm';
import * as webpEnc from 'entry-data:codecs/webp/enc/webp_enc';
import webpEncWasm from 'url:codecs/webp/enc/webp_enc.wasm';
// WP2
import * as wp2EncMtSimdWorker from 'entry-data:codecs/wp2/enc/wp2_enc_mt_simd.worker.js';
import * as wp2EncMtSimd from 'entry-data:codecs/wp2/enc/wp2_enc_mt_simd';
import wp2EncMtSimdWasm from 'url:codecs/wp2/enc/wp2_enc_mt_simd.wasm';
import * as wp2EncMtWorker from 'entry-data:codecs/wp2/enc/wp2_enc_mt.worker.js';
import * as wp2EncMt from 'entry-data:codecs/wp2/enc/wp2_enc_mt';
import wp2EncMtWasm from 'url:codecs/wp2/enc/wp2_enc_mt.wasm';
@ -97,8 +106,14 @@ import * as wp2Enc from 'entry-data:codecs/wp2/enc/wp2_enc';
import wp2EncWasm from 'url:codecs/wp2/enc/wp2_enc.wasm';
export const theRest = (async () => {
const [supportsThreads, supportsWebP, supportsAvif] = await Promise.all([
const [
supportsThreads,
supportsSimd,
supportsWebP,
supportsAvif,
] = await Promise.all([
threads(),
simd(),
...[webpDataUrl, avifDataUrl].map(async (dataUrl) => {
if (!self.createImageBitmap) return false;
const response = await fetch(dataUrl);
@ -139,7 +154,15 @@ export const theRest = (async () => {
}
// JXL
if (supportsThreads) {
if (supportsThreads && supportsSimd) {
items.push(
jxlEncMtSimdWorker.main,
...jxlEncMtSimdWorker.deps,
jxlEncMtSimd.main,
...jxlEncMtSimd.deps,
jxlEncMtSimdWasm,
);
} else if (supportsThreads) {
items.push(
jxlEncMtWorker.main,
...jxlEncMtWorker.deps,
@ -153,16 +176,28 @@ export const theRest = (async () => {
// OXI
if (supportsThreads) {
items.push(oxiMtWasm);
items.push(oxiMtWorker.main, ...oxiMtWorker.deps, oxiMtWasm);
} else {
items.push(oxiWasm);
}
// WebP
items.push(webpEnc.main, ...webpEnc.deps, webpEncWasm);
if (supportsSimd) {
items.push(webpEncSimd.main, ...webpEncSimd.deps, webpEncSimdWasm);
} else {
items.push(webpEnc.main, ...webpEnc.deps, webpEncWasm);
}
// WP2
if (supportsThreads) {
if (supportsThreads && supportsSimd) {
items.push(
wp2EncMtSimdWorker.main,
...wp2EncMtSimdWorker.deps,
wp2EncMtSimd.main,
...wp2EncMtSimd.deps,
wp2EncMtSimdWasm,
);
} else if (supportsThreads) {
items.push(
wp2EncMtWorker.main,
...wp2EncMtWorker.deps,

View File

@ -5,6 +5,7 @@
},
"include": [
"src/features/**/worker/**/*",
"src/features/**/sub-worker/**/*",
"src/features/**/shared/**/*",
"src/features/worker-utils/**/*",
"src/features-worker/**/*",