Compare commits

...

326 Commits

Author SHA1 Message Date
57418034c4 1.11.2 2020-07-07 16:08:26 +01:00
3892490023 Update size report branch 2020-07-07 16:08:13 +01:00
5bedff583b Update privacy link (#771)
The link doesn't work, as the default branch has been renamed
2020-07-07 16:06:33 +01:00
d94835402f 1.11.1 2020-07-02 14:29:00 +01:00
b7e45ab843 Bringing live back in sync 2020-07-02 14:28:40 +01:00
8313246fd1 Fix typo for "spatial" (#768) 2020-07-02 14:25:51 +01:00
2b3cafb1f4 1.11.0 2020-06-24 16:22:06 +01:00
d52698f005 Merge remote-tracking branch 'origin/dev' into live 2020-06-24 16:21:49 +01:00
6ad28c0b5c Merge pull request #765 from petele/dimension 2020-06-24 16:15:16 +01:00
c76dabf063 Merge branch 'dev' into dimension 2020-06-24 16:12:59 +01:00
e6d8bac9c5 Merge pull request #764 from petele/install-prompt 2020-06-24 16:12:48 +01:00
42e43730c8 Naming changes 2020-06-24 15:16:38 +01:00
5c17fba349 Minor tweaks 2020-06-24 15:12:48 +01:00
85eb94b725 Set the dimension value 2020-06-24 09:54:54 -04:00
4fa73be842 Apply suggestions from code review
Co-authored-by: Surma <surma@surma.dev>
2020-06-24 09:40:56 -04:00
7c89d09139 Add missing prop to navigator 2020-06-24 14:08:52 +01:00
079e56f1e1 Use a dimension to note how the user opened squoosh 2020-06-23 16:34:47 -04:00
6065ceabfe update readme 2020-06-23 16:16:32 -04:00
265e6db2bd Adds install button to Squoosh 2020-06-23 16:10:40 -04:00
3a5c0aa30c Merge pull request #757 from GoogleChromeLabs/fixup-clang-format 2020-05-14 17:02:50 +01:00
f0c3ec9d51 Fixup clang-format
I've actually comitted files formatted with column limit of 100, but forgot to include updated .clang-format 🤦🏻‍♂️
2020-05-14 16:30:12 +01:00
1ae93b527c Revert docker run --rm change 2020-05-13 19:39:27 +01:00
a95cb740bf Format C / C++ with Chromium style 2020-05-13 19:39:27 +01:00
de543b3206 Further speed improvements
- Store Emscripten cache inside node_modules/.em_cache. Docker image ships without LTO libs, so Emscripten has to rebuild stdlibs on every build otherwise.
 - Merge webp_enc + webp_dec build scripts. Core libwebp library is same in both cases, so there's no point in storing and building two copies of it.
2020-05-13 19:39:27 +01:00
1542bfb7fd Tweak up compile flags
- Remove unnecessary `-x c++`.
 - Improve rebuild speed by caching:
   - Remove `-f` from `autoreconf` to reuse generated configure scripts.
   - Remove `--rm` from `docker run` to avoid rebuilding Emscripten stdlib.
   - Add `-C` to `./configure` to reuse stored information about `emcc`.
   - Remove `rm -rf build` from WebP encoder/decoder.
2020-05-13 19:39:27 +01:00
bc8d75128f Remove libpng-dev dependency from WebP (#752)
It's unnecessary as we disable PNG support via ./configure anyway.

Co-authored-by: Surma <surma@surma.dev>
2020-05-05 13:23:12 +01:00
d3252bb1bb Add LTO for C++ builds (#755)
* Add LTO for C++ builds

This didn't have much effect on fastcomp builds, but provides further size savings with new LLVM backend we switched to in #750 (and fixes the MozJPEG size regression from the same PR).

In the future we won't need to pass `--llvm-lto 1` explicitly, but latest Emscripten Docker image doesn't contain the Emscripten version with the necessary fixes for this.

* Delete build.log

Co-authored-by: Jake Archibald <jaffathecake@gmail.com>
2020-05-05 11:54:28 +01:00
83d9d2c764 Disable renovate 2020-05-05 11:19:40 +01:00
476268fe19 Merge pull request #748 from GoogleChromeLabs/cleanup 2020-05-01 17:21:37 +01:00
74492af675 Merge branch 'master' into cleanup 2020-05-01 17:08:08 +01:00
bd4179aff2 Merge pull request #751 from GoogleChromeLabs/make-j 2020-05-01 16:48:45 +01:00
27ae47117e Leverage make -j to parallelise C++ builds
We've been running each Make command in a single thread, resulting in fairly slow builds for C++ codecs.

This change instead runs all `make` invocations with `-j` defaulting to number of cores (retrieved via `nproc`).

On my machine Docker uses a VM configured to 4 cores out of 8 available. This change brings total build time for C++ codecs down from 10m28s to 7m5s (~3.5 minutes difference).

Note (1): I've converted imagequant builds to use built-in `make` as well to leverage this parallelisation and future-proof build script.
Note (2): we don't need to do the same for Rust, since Cargo parallelises builds by default.
2020-05-01 16:42:41 +01:00
7da3f07333 Switch to Emscripten upstream
Looks like we've been stuck on Emscripten fastcomp backend, misssing out on all new optimisations between LLVM 6 and LLVM 11 and going via slow asm.js pipeline when building.

This changes Docker images for Emscripten projects to point to emscripten-upstream instead and commits the updated artifacts.
2020-05-01 15:00:10 +01:00
eeb3d3562a 1.10.3 2020-04-22 17:35:39 +01:00
2d73c24e09 Merge remote-tracking branch 'origin/master' into live 2020-04-22 17:34:10 +01:00
ed666dd381 Merge pull request #749 from GoogleChromeLabs/oxipng-update
Limit OxiPNG levels
2020-04-21 00:21:28 +01:00
6f18f08a8e Disable logging statically in OxiPNG
This was a no-op in Wasm anyway. Now that I've added ability to control logging upstream, let's use it to disable it from compiled unit altogether for a slight win in size and perf.
2020-04-20 13:54:21 +01:00
eae808cb6f Limit max level
With libdeflate, any OxiPNG level above 3 is equivalent to 3, so don't show them anymore.
2020-04-20 13:48:56 +01:00
0ae99c9228 Remove obsolete worker termination
I switched build process to proper ES modules back in #672, so, if the TODO is correct, this is no longer necessary.
2020-04-17 14:41:04 +01:00
f4a16022ef 1.10.2 2020-04-16 20:07:42 +01:00
12153c72dc Merge remote-tracking branch 'origin/master' into live 2020-04-16 20:07:08 +01:00
ae7782031d Merge pull request #746 from GoogleChromeLabs/fix-oxipng-free
Fix and document allocation shim for OxiPNG
2020-04-16 20:06:46 +01:00
7cd6487a28 Fix and document allocation shim for OxiPNG 2020-04-16 19:34:28 +01:00
62c53c9fed 1.10.1 2020-04-16 11:52:59 +01:00
53a38b2ba1 Merge remote-tracking branch 'origin/master' into live 2020-04-16 11:52:34 +01:00
f3dfcae3f0 Merge pull request #730 from kripken/closure2
Closure all the things
2020-04-16 11:11:15 +01:00
3f7274a6ac update builds using docker 2020-04-15 13:38:09 -07:00
f5bc715bc0 Merge remote-tracking branch 'upstream/master' into closure2 2020-04-15 13:25:00 -07:00
22b7e36c01 1.10.0 2020-04-14 13:29:05 +01:00
a0e6a377cd Merge remote-tracking branch 'origin/master' into live 2020-04-14 13:28:27 +01:00
22b04c159d Merge pull request #689 from GoogleChromeLabs/oxipng
Swap OptiPNG with OxiPNG
2020-04-14 12:45:18 +01:00
92249ac711 Whole new world
Updated to use new libdeflate integration that I implemented upstream in https://github.com/shssoichiro/oxipng/pull/203.
2020-04-09 14:11:04 +01:00
629d64326d Swap OptiPNG with OxiPNG
This makes building simpler and allows us to potentially use multithreading version in the future.

For now points to a custom fork of OxiPNG that enables WebAssembly support, as PR is still pending review.
2020-04-09 14:10:50 +01:00
4621cbcae9 Add encoding/decoding times to console
This intentionally excludes time of loading corresponding modules, and only measures actual processing.

While this is not perfect as it's not integrated in the UI (cc @jakearchibald), it gives at least some way to measure performance of different codecs and their integrations on particular files.
2020-04-09 14:09:27 +01:00
164191d746 Upgrade node-sass (#742)
4.13 is the minimum version that works with Node.js 13.
2020-04-09 08:45:09 +01:00
b22adc9957 Merge pull request #737 from GoogleChromeLabs/fix-process-syntaxerror
Fix SyntaxError for `{}.nextTick`
2020-04-01 17:14:46 +01:00
6b0a675469 Fix SyntaxError for {}.nextTick 2020-04-01 12:09:57 -04:00
d7fb0d9b40 Remove unneeded compile flags from imagequant 2020-02-28 13:03:51 -08:00
309947a08f Merge branch 'master' into closure2 2020-02-27 09:45:46 -08:00
6aeaae6160 Closure all the things 2020-02-27 09:44:28 -08:00
71b3c7dda2 Merge pull request #728 from kripken/closure
Use closure in optipng build, which shrinks the JS to less than half
2020-02-27 18:36:37 +01:00
48c06e86fa Use closure in optpng build, which shrinks the JS to less than half. 2020-02-27 09:16:43 -08:00
1b7d3fa394 1.9.1 2020-02-27 11:37:53 +00:00
650db99818 Package-json update 2020-02-27 11:37:32 +00:00
7638bb795e Merge pull request #727 from GoogleChromeLabs/optipng
optipng build improvements
2020-02-27 12:19:22 +01:00
570e604be0 optipng: switch to bundled zlib and libpng
Benefits:
 - newer versions of the libraries
    - zlib: 1.2.8 -> 1.2.11
	- libpng: 1.6.18beta04 -> 1.6.34
 - much fewer dependencies to install (as libs are already in optipng archive and we don't need napa)
 - much smaller build thanks to customised versions of zlib and libpng containing only APIs necessary for optipng itself: 238950 -> 177359 bytes
 - much faster build thanks to preconfigured libpng and stripped APIs: 2m15s -> 40s
 - much simpler build script: 77 -> 46 lines
2020-02-25 18:45:47 +00:00
a056d1c363 Switch to make to build optipng
Mostly a build config simplification for now, no noticeable changes in time or output size.
2020-02-25 18:20:05 +00:00
fce61c8c89 Switch to emscripten-upstream
Before: 255184 bytes, 2m15s
After: 238270 bytes, 2m6s
2020-02-25 17:14:16 +00:00
d60d0ae47d Update Emscripten (1.39.4) 2020-02-25 16:53:27 +00:00
8bf741ed4e 1.9.0 2019-10-30 13:20:33 +00:00
9f660e5178 add maskable icon (#709)
add maskable icon
2019-10-30 12:25:41 +00:00
ef2318bcc1 support maskable icon
add a new entry to the icons member referring the maskable icon file added in 364a5db
2019-10-30 19:47:45 +09:00
364a5db5d5 add maskable icon file 2019-10-30 19:44:49 +09:00
4a01d0d548 Update dependency sass-loader to v7.3.1 (#685)
Update dependency sass-loader to v7.3.1
2019-08-22 11:40:24 +01:00
4a9c28f89f Update dependency sass-loader to v7.3.1 2019-08-21 16:19:16 +00:00
3aed873467 Update dependency tslint to v5.19.0 (#686)
Update dependency tslint to v5.19.0
2019-08-21 17:15:47 +01:00
2b7f059b8f Update dependency tslint to v5.19.0 2019-08-20 19:54:25 +00:00
33726e9c68 Update dependency husky to v3.0.4 (#683)
Update dependency husky to v3.0.4
2019-08-17 22:35:54 +01:00
3d29f486e7 Update dependency husky to v3.0.4 2019-08-17 13:28:25 +00:00
79e8a26f06 Update dependency readdirp to v3.1.2 (#681)
Update dependency readdirp to v3.1.2
2019-08-14 15:12:06 +01:00
e8efd54766 Update dependency readdirp to v3.1.2 2019-08-14 14:06:24 +00:00
edcc774c16 Update dependency webpack-dev-server to v3.8.0 (#679)
Update dependency webpack-dev-server to v3.8.0
2019-08-10 00:42:52 +01:00
746b33a590 Update dependency webpack-dev-server to v3.8.0 2019-08-09 17:20:25 +00:00
8a264efc67 Update dependency sass-loader to v7.2.0 (#678)
Update dependency sass-loader to v7.2.0
2019-08-09 14:35:29 +01:00
f0af6e97a0 Update dependency sass-loader to v7.2.0 2019-08-09 10:31:33 +00:00
043107c101 Update dependency file-loader to v4.2.0 (#675)
Update dependency file-loader to v4.2.0
2019-08-09 10:22:19 +01:00
e9e3b923e0 Update dependency file-loader to v4.2.0 2019-08-08 12:48:13 +00:00
aea6e91b1d Update dependency husky to v3.0.3 (#677)
Update dependency husky to v3.0.3
2019-08-08 13:46:49 +01:00
9c4717a13d Update dependency husky to v3.0.3 2019-08-08 12:43:05 +00:00
559cabce9e Update dependency @types/node to v10.14.15 (#676)
Update dependency @types/node to v10.14.15
2019-08-08 09:59:35 +01:00
7f6a3de7ca Update dependency @types/node to v10.14.15 2019-08-07 21:33:12 +00:00
f3adc87f52 Update Node.js to v10.16.2 (#674)
Update Node.js to v10.16.2
2019-08-07 14:34:18 +01:00
6499e9f63d Update Node.js to v10.16.2 2019-08-06 22:41:02 +00:00
ac1f104e49 Update dependency style-loader to v1 (#673)
Update dependency style-loader to v1
2019-08-06 18:11:48 +01:00
87f89e6b2f Update dependency style-loader to v1 2019-08-06 10:41:31 +00:00
7f6404d5a8 Delete .gitignore in resize codec 2019-08-05 15:13:40 +01:00
8e857cd393 Use native Wasm+Webpack support for Rust codecs
This delegates loading of Wasm modules to Webpack itself, making wrapper code simpler.

Emscripten-generated modules are still using custom loading glue as they're not compatible with Webpack.
2019-08-05 15:13:40 +01:00
b8f801333d Switch to prebuilt WABT and wasm-pack
Significantly speeds up `npm run build:image` commands (as they don't need to compile anything anymore) and slightly reduces size of Docker images:
 - `squoosh-rotate`: 1.87GB -> 1.84GB
 - `squoosh-resize`: 2.02GB -> 1.85GB
 - `squoosh-hqx`: 2.06GB -> 1.9GB
2019-08-02 17:23:09 +01:00
499956e216 Switch to stable Rust
Nightly is no longer necessary for wee_alloc, so we don't need to rely on unstable versions of Rust anymore.

As a bonus, this reduces size of each Rust-related Docker image by >1 GB:
 - `squoosh-rotate`: 2.94GB -> 1.87GB
 - `squoosh-resize`: 3.09GB -> 2.02GB
 - `squoosh-hqx`: 3.13GB -> 2.06GB
2019-08-02 16:14:44 +01:00
3932ee2c00 Rename resize package (#668)
Rename `resize` package
2019-08-02 15:21:41 +01:00
68177b7590 Rename resize package
Without this, it was creating files in `pkg` prefixed with `squooshresize`, which were ignored by Git.
2019-08-02 14:53:39 +01:00
0a2a4122dc Update build.sh 2019-08-02 12:47:12 +01:00
e6299569d0 Update dependency tslint to v5.18.0 (#633)
Update dependency tslint to v5.18.0
2019-08-01 09:27:35 +01:00
578ad8c291 Update dependency tslint to v5.18.0 2019-07-31 20:16:43 +00:00
eaa294b689 Merge pull request #667 from GoogleChromeLabs/renovate/node-10.x
Update Node.js to v10.16.1
2019-07-31 21:14:35 +01:00
6e97cfb8d5 Update Node.js to v10.16.1 2019-07-31 19:49:00 +00:00
80a68c48b2 Update dependency webpack-dev-server to v3.7.2 (#628)
Update dependency webpack-dev-server to v3.7.2
2019-07-31 15:16:17 +01:00
98865f8141 Update dependency webpack-dev-server to v3.7.2 2019-07-31 13:59:11 +00:00
78da9fd144 Fix build on Windows (#666)
* Use `require` for reading JSON

JSON is natively supported by Node.js, so no point in using a custom helper here.

* Fix build on Windows

Fixes #465.
2019-07-31 14:32:26 +01:00
94c50a989b Update dependency terser-webpack-plugin to v1.4.0 (#665)
Update dependency terser-webpack-plugin to v1.4.0
2019-07-31 14:08:09 +01:00
3e525e767c Update dependency terser-webpack-plugin to v1.4.1 2019-07-31 12:18:23 +00:00
dfcc1e24e4 Update dependency url-loader to v2.1.0 (#656)
Update dependency url-loader to v2.1.0
2019-07-30 19:12:05 +01:00
f3aa8edfca Update dependency url-loader to v2.1.0 2019-07-30 11:00:32 +00:00
ffd7ee6013 Update dependency webpack-bundle-analyzer to v3.4.1 (#664)
Update dependency webpack-bundle-analyzer to v3.4.1
2019-07-30 11:57:30 +01:00
64bb09dbc5 Update dependency webpack-bundle-analyzer to v3.4.1 2019-07-30 06:57:22 +00:00
35fcbc40ed Update dependency husky to v3.0.2 (#663)
Update dependency husky to v3.0.2
2019-07-29 18:35:05 +01:00
1b55a48680 Update dependency husky to v3.0.2 2019-07-29 17:32:53 +00:00
88fbb19d29 Update dependency @types/node to v10.14.13 (#654)
Update dependency @types/node to v10.14.13
2019-07-29 15:35:38 +01:00
3dc1501ff7 Update dependency @types/node to v10.14.13 2019-07-27 13:47:47 +00:00
b7576c559a Update dependency pretty-bytes to v5.3.0 (#662)
Update dependency pretty-bytes to v5.3.0
2019-07-27 14:46:39 +01:00
69ed2e1d56 Update dependency pretty-bytes to v5.3.0 2019-07-26 20:28:22 +00:00
55f7f3d72a Update dependency copy-webpack-plugin to v5.0.4 (#661)
Update dependency copy-webpack-plugin to v5.0.4
2019-07-26 12:05:12 +01:00
055d0b4ea1 Update dependency copy-webpack-plugin to v5.0.4 2019-07-26 10:42:39 +00:00
7735346ed0 Update dependency critters-webpack-plugin to v2.4.0 (#660)
Update dependency critters-webpack-plugin to v2.4.0
2019-07-23 19:47:12 +01:00
2a06fdbbe0 Update dependency critters-webpack-plugin to v2.4.0 2019-07-23 14:37:32 +00:00
19169199e9 Update dependency raw-loader to v3.1.0 (#657)
Update dependency raw-loader to v3.1.0
2019-07-19 12:02:05 +01:00
76f3c39b78 Update dependency raw-loader to v3.1.0 2019-07-18 23:26:24 +00:00
8da52acc4c Update dependency husky to v3.0.1 (#658)
Update dependency husky to v3.0.1
2019-07-19 00:23:39 +01:00
9253522a3a Update dependency husky to v3.0.1 2019-07-18 21:54:45 +00:00
cf39a3e5a5 Update dependency file-loader to v4.1.0 (#655)
Update dependency file-loader to v4.1.0
2019-07-18 22:52:27 +01:00
a08877f0ac Update dependency file-loader to v4.1.0 2019-07-18 11:14:26 +00:00
2f0dc1c067 Update dependency mini-css-extract-plugin to v0.8.0 (#653)
Update dependency mini-css-extract-plugin to v0.8.0
2019-07-17 16:37:17 +01:00
535d8c9142 Update dependency mini-css-extract-plugin to v0.8.0 2019-07-16 20:52:34 +00:00
6dc2ba3bef Update dependency @types/node to v10.14.12 (#646)
Update dependency @types/node to v10.14.12
2019-07-15 15:56:29 +01:00
93cfdc8f98 Update dependency @types/node to v10.14.12 2019-07-14 18:48:32 +00:00
671544349e Merge pull request #652 from GoogleChromeLabs/renovate/script-ext-html-webpack-plugin-2.x
Update dependency script-ext-html-webpack-plugin to v2.1.4
2019-07-14 19:47:18 +01:00
d3c1939692 Update dependency script-ext-html-webpack-plugin to v2.1.4 2019-07-12 20:36:17 +00:00
99642aef96 Update dependency typescript to v3.5.3 (#650)
Update dependency typescript to v3.5.3
2019-07-09 17:56:25 +01:00
ac4942b640 Update dependency typescript to v3.5.3 2019-07-08 22:36:40 +00:00
23cb004a86 Update dependency chokidar to v3.0.2 (#649)
Update dependency chokidar to v3.0.2
2019-07-08 11:49:13 +01:00
4b6de60978 Update dependency chokidar to v3.0.2 2019-07-08 10:33:35 +00:00
de204aa56a Update dependency readdirp to v3.1.1 (#648)
Update dependency readdirp to v3.1.1
2019-07-08 11:31:31 +01:00
976f811b36 Update dependency readdirp to v3.1.1 2019-07-06 23:55:06 +00:00
855fc9e602 Update dependency @types/node to v10.14.10 (#634)
Update dependency @types/node to v10.14.10
2019-07-03 10:34:32 +01:00
a8848e717c Update dependency @types/node to v10.14.10 2019-07-02 15:57:11 +00:00
90b99faf8b Update dependency travis-size-report to v1.1.0 (#625)
Update dependency travis-size-report to v1.1.0
2019-07-02 16:55:37 +01:00
d3cfffbbcf Update dependency travis-size-report to v1.1.0 2019-07-02 14:27:10 +00:00
fade7f9be8 Update dependency url-loader to v2.0.1 (#638)
Update dependency url-loader to v2.0.1
2019-07-02 15:24:31 +01:00
b10dd055d3 Update dependency url-loader to v2.0.1 2019-07-02 09:19:05 +00:00
7532f01222 Update dependency husky to v3 (#645)
Update dependency husky to v3
2019-07-02 12:12:33 +03:00
2df09efdee Update dependency husky to v3 2019-07-01 21:30:38 +00:00
bed4f49a12 Merge pull request #640 from GoogleChromeLabs/renovate/husky-2.x
Update dependency husky to v2.7.0
2019-06-27 18:44:45 +03:00
2b7fefff8b Update dependency husky to v2.7.0 2019-06-27 15:40:39 +00:00
bdcf2519ce Merge pull request #630 from GoogleChromeLabs/the-nittest-of-nits
Fix nit
2019-06-19 14:04:34 +01:00
3f8afb72a6 Fix nit 2019-06-19 14:44:23 +02:00
2f834db224 Quick doc fix 2019-06-19 13:02:59 +01:00
3541ce7492 1.8.1 2019-06-19 12:25:18 +01:00
b6fae0eb4c Hqx fix (#629)
* Optimising wasm so it doesn't break Chrome

* Simpler dockerfile (thanks surma!)
2019-06-19 12:24:24 +01:00
fbaa282f07 Update dependency ts-loader to v6.0.3 (#627)
Update dependency ts-loader to v6.0.3
2019-06-18 12:56:24 +01:00
6136ae7411 Update dependency ts-loader to v6.0.3 2019-06-18 11:30:57 +00:00
f024747299 1.8.0 2019-06-18 12:24:41 +01:00
66feffcc49 Add Hq{2,3,4}x (#624)
* Scaling works on native

* It works in wasm

* Integrate with UI

* Remove benchmark

* Integrate Hqx into Resizer module

* Link against repo for hqx

* Remove unused defaultOpts

* Re-add test file

* Adding size dropdown

* Chrome: go and sit on the naughty step

* Better docs

* Review

* Add link to crbug

* Update src/codecs/processor-worker/index.ts

Co-Authored-By: Jake Archibald <jaffathecake@gmail.com>

* Terminate worker inbetween resize jobs
2019-06-18 12:23:22 +01:00
24254df7db 1.7.0 2019-06-17 09:43:02 +01:00
cae73f1f1b Add share target (#469)
* Quick test

* More testing

* More testing

* Removing transfer for now

* Changing name so it's easier to tell them apart when installed

* Disable minification to ease debugging

* Adding navigate lock

* lol oops

* Add minifying back

* Removing minification again, for debugging

* Removing broadcast channel bits, to simplify the code

* Revert "Removing broadcast channel bits, to simplify the code"

This reverts commit 0b2a3ecf2986aae0dd65fdd1ddda2bd9e4e1eac7.

* I think this fixes it

* Refactor

* Suppress flash of home screen during share target

* Almost ready, so switching to real name

* Removing log

* Ahh yes the trailing comma thing

* Removing use of BroadcastChannel

* Reducing ternary
2019-06-17 09:42:10 +01:00
073a52213e Update dependency ejs to v2.6.2 (#623)
Update dependency ejs to v2.6.2
2019-06-16 11:33:13 +01:00
0d34485a00 Update dependency ejs to v2.6.2 2019-06-15 15:29:04 +00:00
65519d539e Update dependency tslint-config-semistandard to v8.0.1 (#621)
Update dependency tslint-config-semistandard to v8.0.1
2019-06-14 16:37:05 +01:00
ec44a8e817 Update dependency tslint-config-semistandard to v8.0.1 2019-06-14 11:19:50 +00:00
920f225cb0 Update Node.js to v10.16.0 (#602)
Update Node.js to v10.16.0
2019-06-14 12:18:13 +01:00
d5d4bd61ff Update Node.js to v10.16.0 2019-06-13 22:32:04 +00:00
5656d10b67 Update dependency typescript to v3.5.2 (#620)
Update dependency typescript to v3.5.2
2019-06-13 23:30:52 +01:00
adb4b6468b Update dependency typescript to v3.5.2 2019-06-13 17:50:44 +00:00
0a293d7f63 Update dependency webpack-dev-server to v3.7.1 (#607)
Update dependency webpack-dev-server to v3.7.1
2019-06-13 16:23:36 +01:00
27cb5afd5b Update dependency webpack-dev-server to v3.7.1 2019-06-12 09:52:59 +00:00
5e58fc6b04 Update dependency webpack-cli to v3.3.4 (#616)
Update dependency webpack-cli to v3.3.4
2019-06-12 10:49:55 +01:00
e820adfc96 Update dependency webpack-cli to v3.3.4 2019-06-12 09:17:55 +00:00
5a8a114dcb Update dependency husky to v2.4.1 (#618)
Update dependency husky to v2.4.1
2019-06-12 10:15:05 +01:00
a1c685e820 Update dependency husky to v2.4.1 2019-06-12 09:03:46 +00:00
377dcfcc1b Update dependency @webpack-cli/serve to v0.1.8 (#615)
Update dependency @webpack-cli/serve to v0.1.8
2019-06-12 10:01:36 +01:00
913e67ca93 Update dependency @webpack-cli/serve to v0.1.8 2019-06-07 11:40:52 +00:00
fb1a97c7d4 Update dependency readdirp to v3.0.2 (#609)
Update dependency readdirp to v3.0.2
2019-06-06 17:43:12 +02:00
42eef6945d Update dependency readdirp to v3.0.2 2019-06-06 15:32:57 +00:00
d04b08d640 Update dependency chokidar to v3.0.1 (#610)
Update dependency chokidar to v3.0.1
2019-06-06 17:30:35 +02:00
c547dd10d3 Update dependency chokidar to v3.0.1 2019-06-06 15:08:02 +00:00
f4579da9c9 Update dependency husky to v2.4.0 (#614)
Update dependency husky to v2.4.0
2019-06-06 17:05:49 +02:00
37dc585d80 Update dependency husky to v2.4.0 2019-06-06 13:22:43 +00:00
bc0a425a0f Merge pull request #613 from GoogleChromeLabs/renovate/url-loader-2.x
Update dependency url-loader to v2
2019-06-06 15:19:57 +02:00
b696f246a1 Update dependency url-loader to v2 2019-06-06 12:54:19 +00:00
e6e197e140 Merge pull request #612 from GoogleChromeLabs/renovate/file-loader-4.x
Update dependency file-loader to v4
2019-06-06 14:48:13 +02:00
1c0e8a1fd3 Update dependency file-loader to v4 2019-06-06 11:51:55 +00:00
e3e154fa1a Update dependency raw-loader to v3 (#611)
Update dependency raw-loader to v3
2019-06-06 13:46:28 +02:00
73b7c437f9 Update dependency raw-loader to v3 2019-06-05 10:18:17 +00:00
719168be77 Merge pull request #606 from GoogleChromeLabs/renovate/ts-loader-6.x
Update dependency ts-loader to v6.0.2
2019-05-31 08:31:41 +01:00
a2021b175c Update dependency ts-loader to v6.0.2 2019-05-31 04:42:55 +00:00
9a388fbd13 Update dependency tslint to v5.17.0 (#605)
Update dependency tslint to v5.17.0
2019-05-30 22:58:11 +01:00
1ba0452540 Update dependency tslint to v5.17.0 2019-05-30 20:14:45 +00:00
73df9f18f0 Update dependency typescript to v3.5.1 (#603)
Update dependency typescript to v3.5.1
2019-05-29 17:40:23 +01:00
0e7521877b Update dependency typescript to v3.5.1 2019-05-29 16:35:42 +00:00
120b37c192 Merge pull request #601 from GoogleChromeLabs/renovate/mini-css-extract-plugin-0.x
Update dependency mini-css-extract-plugin to v0.7.0
2019-05-27 17:56:42 +01:00
5f3502b838 Update dependency mini-css-extract-plugin to v0.7.0 2019-05-27 16:17:10 +00:00
33f99432c5 Update dependency terser-webpack-plugin to v1.3.0 (#600)
Update dependency terser-webpack-plugin to v1.3.0
2019-05-24 17:00:36 +01:00
85756ff5df Update dependency terser-webpack-plugin to v1.3.0 2019-05-24 13:30:05 +00:00
84e567ad6a Update dependency gzip-size to v5.1.1 (#598)
Update dependency gzip-size to v5.1.1
2019-05-22 10:25:46 +01:00
39281331fa Update dependency gzip-size to v5.1.1 2019-05-21 04:42:37 +00:00
438ce2ce63 Pin dependency travis-size-report to 1.0.1 (#597)
Pin dependency travis-size-report to 1.0.1
2019-05-20 12:43:52 +01:00
a13e17e256 Pin dependency travis-size-report to 1.0.1 2019-05-20 10:31:09 +00:00
cd6db2d776 Using travis-size-report (#596)
* Using travis-size-report

* No maps in size report
2019-05-20 11:29:43 +01:00
a08662b617 Further optimize logo.svg (#584) 2019-05-20 10:57:24 +01:00
003ec9de35 Update dependency ts-loader to v6.0.1 (#595)
Update dependency ts-loader to v6.0.1
2019-05-19 16:45:55 +01:00
e7f76ca0b8 Update dependency ts-loader to v6.0.1 2019-05-19 02:21:11 +00:00
21111e2927 Update dependency @types/node to v10.14.7 (#592)
Update dependency @types/node to v10.14.7
2019-05-17 23:44:21 +01:00
445c3ef32c Update dependency @types/node to v10.14.7 2019-05-17 21:29:24 +00:00
9df5542ee1 Update dependency webpack-dev-server to v3.4.1 (#591)
Update dependency webpack-dev-server to v3.4.1
2019-05-17 18:05:38 +01:00
fffc4a0cd1 Update dependency webpack-dev-server to v3.4.1 2019-05-17 17:00:55 +00:00
50a8743be3 Update dependency node-fetch to v2.6.0 (#589)
Update dependency node-fetch to v2.6.0
2019-05-17 14:54:38 +01:00
8480bc7dbd Update dependency node-fetch to v2.6.0 2019-05-17 13:51:46 +00:00
72e4546922 Update dependency ts-loader to v6 (#582)
Update dependency ts-loader to v6
2019-05-17 14:50:49 +01:00
11be5babca Update dependency ts-loader to v6 2019-05-17 13:36:00 +00:00
17e5db2427 Update dependency webpack-dev-server to v3.4.0 (#590)
Update dependency webpack-dev-server to v3.4.0
2019-05-17 14:34:01 +01:00
465093eb07 Update dependency webpack-dev-server to v3.4.0 2019-05-17 12:46:02 +00:00
b430ac1041 Update dependency terser-webpack-plugin to v1.2.4 (#588)
Update dependency terser-webpack-plugin to v1.2.4
2019-05-15 13:45:55 +01:00
ea96847c1e Update dependency terser-webpack-plugin to v1.2.4 2019-05-15 08:20:25 +00:00
3b5106a61d Update dependency husky to v2.3.0 (#587)
Update dependency husky to v2.3.0
2019-05-14 17:55:04 +01:00
9f611b0b52 Update dependency husky to v2.3.0 2019-05-14 16:47:41 +00:00
18a6b3c3e5 Update dependency husky to v2 (#567)
Update dependency husky to v2
2019-05-05 13:09:06 -07:00
d9ed4e18ea Update dependency husky to v2 2019-05-05 19:59:35 +00:00
9e757aa896 Update dependency chokidar to v3 (#575)
Update dependency chokidar to v3
2019-05-05 12:57:03 -07:00
89b58bb446 Update dependency chokidar to v3 2019-05-05 19:50:09 +00:00
e80ca583cc Update dependency ts-loader to v5.4.5 (#570)
Update dependency ts-loader to v5.4.5
2019-05-05 12:48:15 -07:00
2ecc81b34f Update dependency ts-loader to v5.4.5 2019-05-05 19:37:22 +00:00
60e98ee34f Update dependency readdirp to v3.0.1 (#568)
Update dependency readdirp to v3.0.1
2019-05-05 12:36:14 -07:00
538ea89ea9 Update dependency readdirp to v3.0.1 2019-05-05 19:25:37 +00:00
3990e11e0a Update dependency node-fetch to v2.5.0 (#569)
Update dependency node-fetch to v2.5.0
2019-05-05 12:23:29 -07:00
0251f88fe5 Update dependency node-fetch to v2.5.0 2019-05-05 19:15:45 +00:00
bbcb959b11 Update dependency webpack-dev-server to v3.3.1 (#539)
Update dependency webpack-dev-server to v3.3.1
2019-05-05 12:14:34 -07:00
b5e928bac9 Update dependency webpack-dev-server to v3.3.1 2019-05-05 13:46:57 +00:00
6592dee4a9 Update dependency webpack-cli to v3.3.2 (#578)
Update dependency webpack-cli to v3.3.2
2019-05-05 06:43:42 -07:00
9b3d72191e Update dependency webpack-cli to v3.3.2 2019-05-04 20:21:13 +00:00
a92e5b48ff Update dependency node-sass to v4.12.0 (#572)
Update dependency node-sass to v4.12.0
2019-04-30 20:08:58 +01:00
e355764ab0 Update dependency node-sass to v4.12.0 2019-04-30 09:20:29 +00:00
c5efd5a8bf Update dependency @types/node to v10.14.6 (#571)
Update dependency @types/node to v10.14.6
2019-04-30 10:18:47 +01:00
385461944b Update dependency @types/node to v10.14.6 2019-04-26 19:48:01 +00:00
8385ba3274 Update dependency copy-webpack-plugin to v5.0.3 (#566)
Update dependency copy-webpack-plugin to v5.0.3
2019-04-24 16:24:54 +01:00
6ca6a77595 Update dependency copy-webpack-plugin to v5.0.3 2019-04-24 15:22:25 +00:00
14c837e894 Update dependency webpack-cli to v3.3.1 (#558)
Update dependency webpack-cli to v3.3.1
2019-04-24 15:32:24 +01:00
33346d7cb6 Update dependency webpack-cli to v3.3.1 2019-04-24 10:09:19 +00:00
05d4f531e2 Update dependency pretty-bytes to v5.2.0 (#565)
Update dependency pretty-bytes to v5.2.0
2019-04-24 11:07:25 +01:00
ede2c49b12 Update dependency pretty-bytes to v5.2.0 2019-04-24 03:30:07 +00:00
16acd32c68 Update dependency typescript to v3.4.5 (#562)
Update dependency typescript to v3.4.5
2019-04-23 23:29:37 +01:00
cc90192860 Update dependency typescript to v3.4.5 2019-04-23 22:22:19 +00:00
3607005fa8 Update dependency ts-loader to v5.4.3 (#561)
Update dependency ts-loader to v5.4.3
2019-04-23 23:21:05 +01:00
7646a64f94 Update dependency ts-loader to v5.4.3 2019-04-22 20:40:38 +00:00
c8ce6ce27b Merge pull request #556 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.14.5
2019-04-19 22:18:51 +01:00
1240474c4b Update dependency @types/node to v10.14.5 2019-04-19 20:50:39 +00:00
f5e84441c0 Merge pull request #555 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.4.4
2019-04-19 12:24:46 +01:00
6bc19d78bc Update dependency typescript to v3.4.4 2019-04-18 23:28:35 +00:00
a4437d2873 Merge pull request #554 from GoogleChromeLabs/renovate/webcomponents-custom-elements-1.x
Update dependency @webcomponents/custom-elements to v1.2.4
2019-04-19 00:26:44 +01:00
cd19650748 Update dependency @webcomponents/custom-elements to v1.2.4 2019-04-18 21:26:08 +00:00
253315b3b1 Merge pull request #552 from GoogleChromeLabs/renovate/readdirp-3.x
Update dependency readdirp to v3
2019-04-17 23:11:50 +01:00
4203ad9a13 Update dependency readdirp to v3 2019-04-17 17:52:20 +00:00
6958202f9d Merge pull request #551 from GoogleChromeLabs/renovate/escape-string-regexp-2.x
Update dependency escape-string-regexp to v2
2019-04-17 12:44:59 +01:00
386fef063f Update dependency escape-string-regexp to v2 2019-04-17 07:51:24 +00:00
d7246ca427 Merge pull request #549 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.16.0
2019-04-16 23:57:41 +01:00
fd024853b6 Update dependency tslint to v5.16.0 2019-04-16 22:24:34 +00:00
bd53d17876 Merge pull request #548 from GoogleChromeLabs/renovate/webcomponents-custom-elements-1.x
Update dependency @webcomponents/custom-elements to v1.2.3
2019-04-16 08:47:51 +01:00
3f87f571f4 Update dependency @webcomponents/custom-elements to v1.2.3 2019-04-16 04:18:42 +00:00
1c69a6f1b7 Merge pull request #547 from GoogleChromeLabs/renovate/gzip-size-5.x
Update dependency gzip-size to v5.1.0
2019-04-15 10:01:59 +01:00
82419cbb6e Update dependency gzip-size to v5.1.0 2019-04-15 03:27:15 +00:00
db65630c8d Merge pull request #546 from GoogleChromeLabs/renovate/webpack-bundle-analyzer-3.x
Update dependency webpack-bundle-analyzer to v3.3.2
2019-04-12 04:24:49 -04:00
b8e54b947f Update dependency webpack-bundle-analyzer to v3.3.2 2019-04-11 14:33:46 +00:00
f23897108d Merge pull request #545 from GoogleChromeLabs/renovate/webpack-bundle-analyzer-3.x
Update dependency webpack-bundle-analyzer to v3.3.0
2019-04-10 09:31:01 -04:00
1efe5b21f0 Update dependency webpack-bundle-analyzer to v3.3.0 2019-04-10 13:08:07 +00:00
fc71b4d249 Merge pull request #544 from GoogleChromeLabs/renovate/tslint-config-semistandard-8.x
Update dependency tslint-config-semistandard to v8
2019-04-10 09:06:26 -04:00
dc81d46556 Update dependency tslint-config-semistandard to v8 2019-04-10 12:47:55 +00:00
56c2080f43 Merge pull request #543 from GoogleChromeLabs/renovate/mini-css-extract-plugin-0.x
Update dependency mini-css-extract-plugin to v0.6.0
2019-04-10 08:44:19 -04:00
4cc50fcaa5 Update dependency mini-css-extract-plugin to v0.6.0 2019-04-10 10:41:06 +00:00
2d67562576 Merge pull request #542 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.4.3
2019-04-09 22:57:59 -04:00
76f2d7afa7 Update dependency typescript to v3.4.3 2019-04-09 23:34:01 +00:00
80fa9c4f21 Fixing quote type 2019-04-08 12:35:05 -04:00
8f215a5b4b fix select the same file bug (#538) 2019-04-08 12:33:07 -04:00
bffd9cb52a Merge pull request #536 from GoogleChromeLabs/renovate/webpack-bundle-analyzer-3.x
Update dependency webpack-bundle-analyzer to v3.2.0
2019-04-06 13:21:28 +01:00
74b1ff5b10 Update dependency webpack-bundle-analyzer to v3.2.0 2019-04-06 11:32:43 +00:00
3c0079fea0 Merge pull request #534 from GoogleChromeLabs/renovate/webassembly-js-api-0.x
Update dependency @types/webassembly-js-api to v0.0.3
2019-04-06 12:31:03 +01:00
c0a9723d20 Update dependency @types/webassembly-js-api to v0.0.3 2019-04-06 10:54:58 +00:00
a4f0a76200 Merge pull request #535 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.4.2
2019-04-06 11:54:14 +01:00
eb57b0130b Update dependency typescript to v3.4.2 2019-04-05 21:16:13 +00:00
f8c37c7abc Merge pull request #528 from GoogleChromeLabs/renovate/tslint-react-4.x
Update dependency tslint-react to v4
2019-04-02 11:06:56 +01:00
72373f8812 Update dependency tslint-react to v4 2019-04-02 09:53:36 +00:00
b285e99e7d Merge pull request #533 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.15.0
2019-04-02 10:51:06 +01:00
f9a6b88bb6 Update dependency tslint to v5.15.0 2019-04-01 23:03:59 +00:00
4a65d506f2 Merge pull request #529 from GoogleChromeLabs/renovate/webcomponents-custom-elements-1.x
Update dependency @webcomponents/custom-elements to v1.2.2
2019-04-01 16:11:35 +01:00
3bc03c90fd Update dependency @webcomponents/custom-elements to v1.2.2 2019-04-01 14:48:19 +00:00
c35dfa4ac5 Merge pull request #532 from GoogleChromeLabs/renovate/idb-keyval-3.x
Update dependency idb-keyval to v3.2.0
2019-04-01 15:47:14 +01:00
1d2a9a9dde Update dependency idb-keyval to v3.2.0 2019-04-01 13:41:10 +00:00
925220bb13 Merge pull request #531 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.4.1
2019-03-31 19:21:09 +01:00
16d088bfe3 Update dependency typescript to v3.4.1 2019-03-29 17:49:28 +00:00
b8e22ee435 Merge pull request #527 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.14.4
2019-03-25 23:05:18 +00:00
60dea4b932 Update dependency @types/node to v10.14.4 2019-03-25 20:47:44 +00:00
8ae1a42e4b Merge pull request #525 from GoogleChromeLabs/renovate/chokidar-2.x
Update dependency chokidar to v2.1.5
2019-03-23 10:21:50 +00:00
cfdc7a46e6 Update dependency chokidar to v2.1.5 2019-03-22 21:21:55 +00:00
afb23adcbf Merge pull request #524 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.14.3
2019-03-22 19:24:36 +00:00
3b84a474b8 Update dependency @types/node to v10.14.3 2019-03-22 19:20:48 +00:00
e96bb04e88 Merge pull request #523 from GoogleChromeLabs/renovate/copy-webpack-plugin-5.x
Update dependency copy-webpack-plugin to v5.0.2
2019-03-22 16:34:45 +00:00
2e3b8507b2 Update dependency copy-webpack-plugin to v5.0.2 2019-03-22 15:56:33 +00:00
e12c69f1a6 Merge pull request #522 from GoogleChromeLabs/renovate/chokidar-2.x
Update dependency chokidar to v2.1.4
2019-03-22 10:51:12 +00:00
d049a23469 Update dependency chokidar to v2.1.4 2019-03-22 10:15:07 +00:00
2633f427c8 Merge pull request #521 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.14.2
2019-03-22 00:08:32 +00:00
ff920f1d7b Update dependency @types/node to v10.14.2 2019-03-21 23:02:17 +00:00
fd69560025 Merge pull request #515 from GoogleChromeLabs/renovate/webpack-cli-serve-0.x
Update dependency @webpack-cli/serve to v0.1.5
2019-03-20 18:02:40 +00:00
ba51e47e05 Update dependency @webpack-cli/serve to v0.1.5 2019-03-20 17:56:47 +00:00
409f552274 Merge pull request #519 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.3.4000
2019-03-20 17:55:12 +00:00
69a7c184bd Update dependency typescript to v3.3.4000 2019-03-20 17:10:39 +00:00
3039c84738 Merge pull request #514 from GoogleChromeLabs/renovate/webpack-cli-3.x
Update dependency webpack-cli to v3.3.0
2019-03-20 17:08:22 +00:00
bfa5cd085d Update dependency webpack-cli to v3.3.0 2019-03-20 10:49:10 +00:00
7c282b30b1 Merge pull request #518 from GoogleChromeLabs/renovate/raw-loader-2.x
Update dependency raw-loader to v2
2019-03-18 15:11:32 +00:00
06fa3c541e Update dependency raw-loader to v2 2019-03-18 13:26:03 +00:00
c9e31ac1f7 Merge pull request #512 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.14.1
2019-03-13 11:38:42 +00:00
e248486d3d Update dependency @types/node to v10.14.1 2019-03-13 09:16:26 +00:00
b32a52d236 Merge pull request #513 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.14.0
2019-03-13 09:15:28 +00:00
a24b4d6d4d Update dependency tslint to v5.14.0 2019-03-13 04:24:01 +00:00
b831aa0075 1.6.0 2019-03-12 14:10:19 +00:00
bf4d4b78cb Implement sRGB color conversion (#510)
* Add sRGB -> RGB conversion before resize

* Add clamping for color space conversions

* Clip for demultiplication as well

* Fixing linear <-> srgb conversion

* Update benchmark

* Decouple srgb calculations

* Generate lookup tables

* Update src/codecs/resize/options.tsx

* Defaulting on, renaming, removing redundant state
2019-03-12 14:09:35 +00:00
496896e36e Merge pull request #511 from GoogleChromeLabs/renovate/copy-webpack-plugin-5.x
Update dependency copy-webpack-plugin to v5.0.1
2019-03-11 18:22:51 +00:00
6b88ec1f8a Update dependency copy-webpack-plugin to v5.0.1 2019-03-11 13:24:05 +00:00
3af5f3a96d Merge pull request #508 from GoogleChromeLabs/renovate/typed-css-modules-0.x
Update dependency typed-css-modules to v0.4.2
2019-03-09 18:21:29 +00:00
ddc5564515 Update dependency typed-css-modules to v0.4.2 2019-03-08 11:22:51 +00:00
126 changed files with 7673 additions and 9628 deletions

2
.clang-format Normal file
View File

@ -0,0 +1,2 @@
BasedOnStyle: Chromium
ColumnLimit: 100

2
.nvmrc
View File

@ -1 +1 @@
10.15.3
10.16.2

View File

@ -10,6 +10,7 @@ Google Analytics is used to record the following:
* [Basic visit data](https://support.google.com/analytics/answer/6004245?ref_topic=2919631).
* Before and after image size once an image is downloaded. These values are rounded to the nearest
kilobyte.
* If install is available, when Squoosh is installed, and what method was used to install Squoosh.
Image compression is handled locally; no additional data is sent to the server.

5
codecs/hqx/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
**/*.rs.bk
target
Cargo.lock
bin/
pkg/README.md

37
codecs/hqx/Cargo.toml Normal file
View File

@ -0,0 +1,37 @@
[package]
name = "squooshhqx"
version = "0.1.0"
authors = ["Surma <surma@surma.link>"]
[lib]
crate-type = ["cdylib"]
[features]
default = ["console_error_panic_hook", "wee_alloc"]
[dependencies]
cfg-if = "0.1.2"
wasm-bindgen = "0.2.38"
# lazy_static = "1.0.0"
hqx = {git = "https://github.com/CryZe/wasmboy-rs", tag="v0.1.2"}
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.1", optional = true }
# `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size
# compared to the default allocator's ~10K. It is slower than the default
# allocator, however.
#
# Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now.
wee_alloc = { version = "0.4.2", optional = true }
[dev-dependencies]
wasm-bindgen-test = "0.2"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"
lto = true

12
codecs/hqx/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM rust
RUN rustup target add wasm32-unknown-unknown
RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
RUN mkdir /opt/binaryen && \
curl -L https://github.com/WebAssembly/binaryen/releases/download/1.38.32/binaryen-1.38.32-x86-linux.tar.gz | tar -xzf - -C /opt/binaryen --strip 1
RUN mkdir /opt/wabt && \
curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.11/wabt-1.0.11-linux.tar.gz | tar -xzf - -C /opt/wabt --strip 1
ENV PATH="/opt/binaryen:/opt/wabt:${PATH}"
WORKDIR /src

25
codecs/hqx/build.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
set -e
echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
wasm-pack build
wasm-strip pkg/squooshhqx_bg.wasm
echo "Optimising Wasm so it doesn't break Chrome (this takes like 10-15mins. get a cup of tea)"
echo "Once https://crbug.com/974804 is fixed, we can remove this step"
wasm-opt -Os --no-validation -o pkg/squooshhqx_bg.wasm pkg/squooshhqx_bg.wasm
rm pkg/.gitignore
)
echo "============================================="
echo "Compiling wasm done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull ubuntu\`"
echo "Run \`docker pull rust\`"
echo "Run \`docker build -t squoosh-hqx .\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

4
codecs/hqx/package-lock.json generated Normal file
View File

@ -0,0 +1,4 @@
{
"name": "hqx",
"lockfileVersion": 1
}

7
codecs/hqx/package.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "hqx",
"scripts": {
"build:image": "docker build -t squoosh-hqx .",
"build": "docker run --rm -v $(pwd):/src squoosh-hqx ./build.sh"
}
}

View File

@ -0,0 +1,15 @@
{
"name": "squooshhqx",
"collaborators": [
"Surma <surma@surma.link>"
],
"version": "0.1.0",
"files": [
"squooshhqx_bg.wasm",
"squooshhqx.js",
"squooshhqx.d.ts"
],
"module": "squooshhqx.js",
"types": "squooshhqx.d.ts",
"sideEffects": "false"
}

9
codecs/hqx/pkg/squooshhqx.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
/* tslint:disable */
/**
* @param {Uint32Array} input_image
* @param {number} input_width
* @param {number} input_height
* @param {number} factor
* @returns {Uint32Array}
*/
export function resize(input_image: Uint32Array, input_width: number, input_height: number, factor: number): Uint32Array;

View File

@ -0,0 +1,46 @@
import * as wasm from './squooshhqx_bg.wasm';
let cachegetUint32Memory = null;
function getUint32Memory() {
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
}
return cachegetUint32Memory;
}
let WASM_VECTOR_LEN = 0;
function passArray32ToWasm(arg) {
const ptr = wasm.__wbindgen_malloc(arg.length * 4);
getUint32Memory().set(arg, ptr / 4);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
let cachegetInt32Memory = null;
function getInt32Memory() {
if (cachegetInt32Memory === null || cachegetInt32Memory.buffer !== wasm.memory.buffer) {
cachegetInt32Memory = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory;
}
function getArrayU32FromWasm(ptr, len) {
return getUint32Memory().subarray(ptr / 4, ptr / 4 + len);
}
/**
* @param {Uint32Array} input_image
* @param {number} input_width
* @param {number} input_height
* @param {number} factor
* @returns {Uint32Array}
*/
export function resize(input_image, input_width, input_height, factor) {
const retptr = 8;
const ret = wasm.resize(retptr, passArray32ToWasm(input_image), WASM_VECTOR_LEN, input_width, input_height, factor);
const memi32 = getInt32Memory();
const v0 = getArrayU32FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 4);
return v0;
}

5
codecs/hqx/pkg/squooshhqx_bg.d.ts vendored Normal file
View File

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

Binary file not shown.

55
codecs/hqx/src/lib.rs Normal file
View File

@ -0,0 +1,55 @@
extern crate cfg_if;
extern crate hqx;
extern crate wasm_bindgen;
mod utils;
use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;
cfg_if! {
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
if #[cfg(feature = "wee_alloc")] {
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}
}
#[wasm_bindgen]
#[no_mangle]
pub fn resize(
input_image: Vec<u32>,
input_width: usize,
input_height: usize,
factor: usize,
) -> Vec<u32> {
let num_output_pixels = input_width * input_height * factor * factor;
let mut output_image = Vec::<u32>::with_capacity(num_output_pixels * 4);
output_image.resize(num_output_pixels, 0);
match factor {
2 => hqx::hq2x(
input_image.as_slice(),
output_image.as_mut_slice(),
input_width,
input_height,
),
3 => hqx::hq3x(
input_image.as_slice(),
output_image.as_mut_slice(),
input_width,
input_height,
),
4 => hqx::hq4x(
input_image.as_slice(),
output_image.as_mut_slice(),
input_width,
input_height,
),
_ => unreachable!(),
};
return output_image;
}

17
codecs/hqx/src/utils.rs Normal file
View File

@ -0,0 +1,17 @@
use cfg_if::cfg_if;
cfg_if! {
// When the `console_error_panic_hook` feature is enabled, we can call the
// `set_panic_hook` function at least once during initialization, and then
// we will get better error messages if our code ever panics.
//
// For more details see
// https://github.com/rustwasm/console_error_panic_hook#readme
if #[cfg(feature = "console_error_panic_hook")] {
extern crate console_error_panic_hook;
pub use self::console_error_panic_hook::set_once as set_panic_hook;
} else {
#[inline]
pub fn set_panic_hook() {}
}
}

View File

@ -2,7 +2,8 @@
set -e
export OPTIMIZE="-Os"
export EM_CACHE="${PWD}/node_modules/.em_cache"
export OPTIMIZE="-Os -flto --llvm-lto 1"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
@ -11,16 +12,9 @@ echo "============================================="
echo "Compiling libimagequant"
echo "============================================="
(
emcc \
--bind \
${OPTIMIZE} \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="imagequant"' \
-I node_modules/libimagequant \
--std=c99 \
-c \
node_modules/libimagequant/{libimagequant,pam,mediancut,blur,mempool,kmeans,nearest}.c
cd node_modules/libimagequant
emconfigure ./configure --disable-sse
emmake make static -j`nproc`
)
echo "============================================="
echo "Compiling wasm module"
@ -29,14 +23,15 @@ echo "============================================="
emcc \
--bind \
${OPTIMIZE} \
--closure 1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="imagequant"' \
-I node_modules/libimagequant \
-o ./imagequant.js \
--std=c++11 *.o \
-x c++ \
imagequant.cpp
--std=c++11 \
imagequant.cpp \
node_modules/libimagequant/libimagequant.a
)
echo "============================================="
echo "Compiling wasm module done"
@ -44,5 +39,5 @@ echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "Run \`docker pull trzeci/emscripten-upstream\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -1,36 +1,37 @@
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include <stdlib.h>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include "libimagequant.h"
using namespace emscripten;
int version() {
return (((LIQ_VERSION/10000) % 100) << 16) |
(((LIQ_VERSION/100 ) % 100) << 8) |
(((LIQ_VERSION/1 ) % 100) << 0);
return (((LIQ_VERSION / 10000) % 100) << 16) | (((LIQ_VERSION / 100) % 100) << 8) |
(((LIQ_VERSION / 1) % 100) << 0);
}
class RawImage {
public:
public:
val buffer;
int width;
int height;
RawImage(val b, int w, int h)
: buffer(b), width(w), height(h) {}
RawImage(val b, int w, int h) : buffer(b), width(w), height(h) {}
};
liq_attr *attr;
liq_image *image;
liq_result *res;
liq_attr* attr;
liq_image* image;
liq_result* res;
uint8_t* result;
RawImage quantize(std::string rawimage, int image_width, int image_height, int num_colors, float dithering) {
RawImage quantize(std::string rawimage,
int image_width,
int image_height,
int num_colors,
float dithering) {
const uint8_t* image_buffer = (uint8_t*)rawimage.c_str();
int size = image_width * image_height;
attr = liq_attr_create();
@ -38,12 +39,12 @@ RawImage quantize(std::string rawimage, int image_width, int image_height, int n
liq_set_max_colors(attr, num_colors);
liq_image_quantize(image, attr, &res);
liq_set_dithering_level(res, dithering);
uint8_t* image8bit = (uint8_t*) malloc(size);
result = (uint8_t*) malloc(size * 4);
uint8_t* image8bit = (uint8_t*)malloc(size);
result = (uint8_t*)malloc(size * 4);
liq_write_remapped_image(res, image, image8bit, size);
const liq_palette *pal = liq_get_palette(res);
const liq_palette* pal = liq_get_palette(res);
// Turn palletted image back into an RGBA image
for(int i = 0; i < size; i++) {
for (int i = 0; i < size; i++) {
result[i * 4 + 0] = pal->entries[image8bit[i]].r;
result[i * 4 + 1] = pal->entries[image8bit[i]].g;
result[i * 4 + 2] = pal->entries[image8bit[i]].b;
@ -53,43 +54,41 @@ RawImage quantize(std::string rawimage, int image_width, int image_height, int n
liq_result_destroy(res);
liq_image_destroy(image);
liq_attr_destroy(attr);
return {
val(typed_memory_view(image_width*image_height*4, result)),
image_width,
image_height
};
return {val(typed_memory_view(image_width * image_height * 4, result)), image_width,
image_height};
}
const liq_color zx_colors[] = {
{.a = 255, .r = 0, .g = 0, .b = 0}, // regular black
{.a = 255, .r = 0, .g = 0, .b = 215}, // regular blue
{.a = 255, .r = 215, .g = 0, .b = 0}, // regular red
{.a = 255, .r = 215, .g = 0, .b = 215}, // regular magenta
{.a = 255, .r = 0, .g = 215, .b = 0}, // regular green
{.a = 255, .r = 0, .g = 215, .b = 215}, // regular cyan
{.a = 255, .r = 215, .g = 215, .b = 0}, // regular yellow
{.a = 255, .r = 215, .g = 215, .b = 215}, // regular white
{.a = 255, .r = 0, .g = 0, .b = 255}, // bright blue
{.a = 255, .r = 255, .g = 0, .b = 0}, // bright red
{.a = 255, .r = 255, .g = 0, .b = 255}, // bright magenta
{.a = 255, .r = 0, .g = 255, .b = 0}, // bright green
{.a = 255, .r = 0, .g = 255, .b = 255}, // bright cyan
{.a = 255, .r = 255, .g = 255, .b = 0}, // bright yellow
{.a = 255, .r = 255, .g = 255, .b = 255} // bright white
{.r = 0, .g = 0, .b = 0, .a = 255}, // regular black
{.r = 0, .g = 0, .b = 215, .a = 255}, // regular blue
{.r = 215, .g = 0, .b = 0, .a = 255}, // regular red
{.r = 215, .g = 0, .b = 215, .a = 255}, // regular magenta
{.r = 0, .g = 215, .b = 0, .a = 255}, // regular green
{.r = 0, .g = 215, .b = 215, .a = 255}, // regular cyan
{.r = 215, .g = 215, .b = 0, .a = 255}, // regular yellow
{.r = 215, .g = 215, .b = 215, .a = 255}, // regular white
{.r = 0, .g = 0, .b = 255, .a = 255}, // bright blue
{.r = 255, .g = 0, .b = 0, .a = 255}, // bright red
{.r = 255, .g = 0, .b = 255, .a = 255}, // bright magenta
{.r = 0, .g = 255, .b = 0, .a = 255}, // bright green
{.r = 0, .g = 255, .b = 255, .a = 255}, // bright cyan
{.r = 255, .g = 255, .b = 0, .a = 255}, // bright yellow
{.r = 255, .g = 255, .b = 255, .a = 255} // bright white
};
uint8_t block[8 * 8 * 4];
/**
* The ZX has one bit per pixel, but can assign two colours to an 8x8 block. The two colours must
* both be 'regular' or 'bright'. Black exists as both regular and bright.
* The ZX has one bit per pixel, but can assign two colours to an 8x8 block. The
* two colours must both be 'regular' or 'bright'. Black exists as both regular
* and bright.
*/
RawImage zx_quantize(std::string rawimage, int image_width, int image_height, float dithering) {
const uint8_t* image_buffer = (uint8_t*) rawimage.c_str();
const uint8_t* image_buffer = (uint8_t*)rawimage.c_str();
int size = image_width * image_height;
int bytes_per_pixel = 4;
result = (uint8_t*) malloc(size * bytes_per_pixel);
uint8_t* image8bit = (uint8_t*) malloc(8 * 8);
result = (uint8_t*)malloc(size * bytes_per_pixel);
uint8_t* image8bit = (uint8_t*)malloc(8 * 8);
// For each 8x8 grid
for (int block_start_y = 0; block_start_y < image_height; block_start_y += 8) {
@ -99,7 +98,8 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
int block_width = 8;
int block_height = 8;
// If the block hangs off the right/bottom of the image dimensions, make it smaller to fit.
// If the block hangs off the right/bottom of the image dimensions, make
// it smaller to fit.
if (block_start_y + block_height > image_height) {
block_height = image_height - block_start_y;
}
@ -125,12 +125,11 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
for (int color_index = 0; color_index < 15; color_index++) {
liq_color color = zx_colors[color_index];
// Using Euclidean distance. LibQuant has better methods, but it requires conversion to
// LAB, so I don't think it's worth it.
int distance =
pow(color.r - image_buffer[pixel_start + 0], 2) +
pow(color.g - image_buffer[pixel_start + 1], 2) +
pow(color.b - image_buffer[pixel_start + 2], 2);
// Using Euclidean distance. LibQuant has better methods, but it
// requires conversion to LAB, so I don't think it's worth it.
int distance = pow(color.r - image_buffer[pixel_start + 0], 2) +
pow(color.g - image_buffer[pixel_start + 1], 2) +
pow(color.b - image_buffer[pixel_start + 2], 2);
if (distance < smallest_distance) {
winning_index = color_index;
@ -151,7 +150,8 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
for (int color_index = 0; color_index < 15; color_index++) {
if (color_popularity[color_index] > highest_popularity) {
// Store this as the most popular pixel, and demote the current values:
// Store this as the most popular pixel, and demote the current
// values:
third_color_index = second_color_index;
third_highest_popularity = second_highest_popularity;
second_color_index = first_color_index;
@ -169,8 +169,8 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
}
}
// ZX images can't mix bright and regular colours, except black which appears in both.
// Resolve any conflict:
// ZX images can't mix bright and regular colours, except black which
// appears in both. Resolve any conflict:
while (1) {
// If either colour is black, there's no conflict to resolve.
if (first_color_index != 0 && second_color_index != 0) {
@ -183,12 +183,13 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
}
}
// If, during conflict resolving, we now have two of the same colour (because we initially
// selected the bright & regular version of the same colour), retry again with the third
// most popular colour.
// If, during conflict resolving, we now have two of the same colour
// (because we initially selected the bright & regular version of the
// same colour), retry again with the third most popular colour.
if (first_color_index == second_color_index) {
second_color_index = third_color_index;
} else break;
} else
break;
}
// Quantize
@ -200,13 +201,15 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
liq_image_quantize(image, attr, &res);
liq_set_dithering_level(res, dithering);
liq_write_remapped_image(res, image, image8bit, size);
const liq_palette *pal = liq_get_palette(res);
const liq_palette* pal = liq_get_palette(res);
// Turn palletted image back into an RGBA image, and write it into the full size result image.
for(int y = 0; y < block_height; y++) {
for(int x = 0; x < block_width; x++) {
// Turn palletted image back into an RGBA image, and write it into the
// full size result image.
for (int y = 0; y < block_height; y++) {
for (int x = 0; x < block_width; x++) {
int image8BitPos = y * block_width + x;
int resultStartPos = ((block_start_y + y) * bytes_per_pixel * image_width) + ((block_start_x + x) * bytes_per_pixel);
int resultStartPos = ((block_start_y + y) * bytes_per_pixel * image_width) +
((block_start_x + x) * bytes_per_pixel);
result[resultStartPos + 0] = pal->entries[image8bit[image8BitPos]].r;
result[resultStartPos + 1] = pal->entries[image8bit[image8BitPos]].g;
result[resultStartPos + 2] = pal->entries[image8bit[image8BitPos]].b;
@ -221,11 +224,8 @@ RawImage zx_quantize(std::string rawimage, int image_width, int image_height, fl
}
free(image8bit);
return {
val(typed_memory_view(image_width*image_height*4, result)),
image_width,
image_height
};
return {val(typed_memory_view(image_width * image_height * 4, result)), image_width,
image_height};
}
void free_result() {
@ -234,9 +234,9 @@ void free_result() {
EMSCRIPTEN_BINDINGS(my_module) {
class_<RawImage>("RawImage")
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
function("quantize", &quantize);
function("zx_quantize", &zx_quantize);

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -2,7 +2,7 @@
"name": "imagequant",
"scripts": {
"install": "napa",
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten-upstream ./build.sh"
},
"napa": {
"libimagequant": "ImageOptim/libimagequant#2.12.1"

View File

@ -2,7 +2,8 @@
set -e
export OPTIMIZE="-Os"
export EM_CACHE="${PWD}/node_modules/.em_cache"
export OPTIMIZE="-Os -flto --llvm-lto 1"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
@ -15,9 +16,9 @@ echo "Compiling mozjpeg"
echo "============================================="
(
cd node_modules/mozjpeg
autoreconf -fiv
emconfigure ./configure --without-simd
emmake make libjpeg.la
autoreconf -iv
emconfigure ./configure -C --without-simd
emmake make libjpeg.la rdswitch.o -j`nproc`
)
echo "============================================="
echo "Compiling mozjpeg done"
@ -30,18 +31,16 @@ echo "============================================="
emcc \
--bind \
${OPTIMIZE} \
-s WASM=1 \
--closure 1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="mozjpeg_enc"' \
-I node_modules/mozjpeg \
-o ./mozjpeg_enc.js \
-Wno-deprecated-register \
-Wno-writable-strings \
node_modules/mozjpeg/rdswitch.c \
-x c++ -std=c++11 \
-std=c++11 \
mozjpeg_enc.cpp \
node_modules/mozjpeg/.libs/libjpeg.a
node_modules/mozjpeg/.libs/libjpeg.a \
node_modules/mozjpeg/rdswitch.o
)
echo "============================================="
echo "Compiling wasm bindings done"
@ -49,5 +48,5 @@ echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "Run \`docker pull trzeci/emscripten-upstream\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -1,18 +1,22 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "jpeglib.h"
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
// 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
@ -39,8 +43,8 @@ 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] == '.') {
for (int i = 0; i < strlen(buffer); i++) {
if (buffer[i] == '.') {
buffer[i] = '\0';
version = version << 8 | atoi(&buffer[last_index]);
buffer[i] = '.';
@ -55,13 +59,12 @@ uint8_t* last_result;
struct jpeg_compress_struct cinfo;
val encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts) {
uint8_t* image_buffer = (uint8_t*) image_in.c_str();
uint8_t* image_buffer = (uint8_t*)image_in.c_str();
// The code below is basically the `write_JPEG_file` function from
// https://github.com/mozilla/mozjpeg/blob/master/example.c
// I just write to memory instead of a file.
/* This struct contains the JPEG compression parameters and pointers to
* working space (which is allocated as needed by the JPEG library).
* It is possible to have several such structures, representing multiple
@ -78,8 +81,8 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
*/
struct jpeg_error_mgr jerr;
/* More stuff */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
uint8_t* output;
unsigned long size;
@ -113,17 +116,17 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
/* First we supply a description of the input image.
* Four fields of the cinfo struct must be filled in:
*/
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 4; /* # of color components per pixel */
cinfo.in_color_space = JCS_EXT_RGBA; /* colorspace of input image */
cinfo.input_components = 4; /* # of color components per pixel */
cinfo.in_color_space = JCS_EXT_RGBA; /* colorspace of input image */
/* Now use the library's routine to set default compression parameters.
* (You must set at least cinfo.in_color_space before calling this,
* since the defaults depend on the source color space.)
*/
jpeg_set_defaults(&cinfo);
jpeg_set_colorspace(&cinfo, (J_COLOR_SPACE) opts.color_space);
jpeg_set_colorspace(&cinfo, (J_COLOR_SPACE)opts.color_space);
if (opts.quant_table != -1) {
jpeg_c_set_int_param(&cinfo, JINT_BASE_QUANT_TBL_IDX, opts.quant_table);
@ -143,17 +146,17 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
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);
// A little hacky to build a string for this, but it means we can use set_quality_ratings which
// does some useful heuristic stuff.
// A little hacky to build a string for this, but it means we can use
// set_quality_ratings which does some useful heuristic stuff.
std::string quality_str = std::to_string(opts.quality);
if (opts.separate_chroma_quality && opts.color_space == JCS_YCbCr) {
quality_str += "," + std::to_string(opts.chroma_quality);
}
char const *pqual = quality_str.c_str();
char const* pqual = quality_str.c_str();
set_quality_ratings(&cinfo, (char*) pqual, opts.baseline);
set_quality_ratings(&cinfo, (char*)pqual, opts.baseline);
if (!opts.auto_subsample && opts.color_space == JCS_YCbCr) {
cinfo.comp_info[0].h_samp_factor = opts.chroma_subsample;
@ -188,8 +191,8 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
* Here the array is only one element long, but you could pass
* more than one scanline at a time if that's more convenient.
*/
row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
row_pointer[0] = &image_buffer[cinfo.next_scanline * row_stride];
(void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
/* Step 6: Finish compression */
@ -210,23 +213,22 @@ void free_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)
;
.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);

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -2,7 +2,7 @@
"name": "mozjpeg_enc",
"scripts": {
"install": "napa",
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten-upstream ./build.sh"
},
"napa": {
"mozjpeg": "mozilla/mozjpeg#v3.3.1"

View File

@ -1,2 +0,0 @@
build/
*.o

View File

@ -1,26 +0,0 @@
# OptiPNG
- Source: <http://optipng.sourceforge.net/>
- Version: v0.7.7
## Dependencies
- Docker
## Example
See `example.html`
## API
### `int version()`
Returns the version of optipng as a number. va.b.c is encoded as 0x0a0b0c
### `ArrayBuffer compress(std::string buffer, {level})`;
`compress` will re-compress the given PNG image via `buffer`. `level` is a number between 0 and 7.
### `void free_result()`
Frees the result created by `compress()`.

View File

@ -1,87 +0,0 @@
#!/bin/bash
set -e
export OPTIMIZE="-Os"
export PREFIX="/src/build"
export CFLAGS="${OPTIMIZE} -I${PREFIX}/include/"
export CPPFLAGS="${OPTIMIZE} -I${PREFIX}/include/"
export LDFLAGS="${OPTIMIZE} -L${PREFIX}/lib/"
apt-get update
apt-get install -qqy autoconf libtool
echo "============================================="
echo "Compiling zlib"
echo "============================================="
test -n "$SKIP_ZLIB" || (
cd node_modules/zlib
emconfigure ./configure --prefix=${PREFIX}/
emmake make
emmake make install
)
echo "============================================="
echo "Compiling zlib done"
echo "============================================="
echo "============================================="
echo "Compiling libpng"
echo "============================================="
test -n "$SKIP_LIBPNG" || (
cd node_modules/libpng
autoreconf -i
emconfigure ./configure --with-zlib-prefix=${PREFIX}/ --prefix=${PREFIX}/
emmake make
emmake make install
)
echo "============================================="
echo "Compiling libpng done"
echo "============================================="
echo "============================================="
echo "Compiling optipng"
echo "============================================="
(
emcc \
${OPTIMIZE} \
-Wno-implicit-function-declaration \
-I ${PREFIX}/include \
-I node_modules/optipng/src/opngreduc \
-I node_modules/optipng/src/pngxtern \
-I node_modules/optipng/src/cexcept \
-I node_modules/optipng/src/gifread \
-I node_modules/optipng/src/pnmio \
-I node_modules/optipng/src/minitiff \
--std=c99 -c \
node_modules/optipng/src/opngreduc/*.c \
node_modules/optipng/src/pngxtern/*.c \
node_modules/optipng/src/gifread/*.c \
node_modules/optipng/src/minitiff/*.c \
node_modules/optipng/src/pnmio/*.c \
node_modules/optipng/src/optipng/*.c
emcc \
--bind \
${OPTIMIZE} \
-s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME="optipng"' \
-I ${PREFIX}/include \
-I node_modules/optipng/src/opngreduc \
-I node_modules/optipng/src/pngxtern \
-I node_modules/optipng/src/cexcept \
-I node_modules/optipng/src/gifread \
-I node_modules/optipng/src/pnmio \
-I node_modules/optipng/src/minitiff \
-o "optipng.js" \
--std=c++11 \
optipng.cpp \
*.o \
${PREFIX}/lib/libz.so ${PREFIX}/lib/libpng.a
)
echo "============================================="
echo "Compiling optipng done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -1,19 +0,0 @@
<!doctype html>
<script src='optipng.js'></script>
<script>
const Module = optipng();
Module.onRuntimeInitialized = async _ => {
console.log('Version:', Module.version().toString(16));
const image = await fetch('../example_palette.png').then(r => r.arrayBuffer());
const newImage = Module.compress(image, {level: 3});
console.log('done');
Module.free_result();
console.log(`Old size: ${image.byteLength}, new size: ${newImage.byteLength} (${newImage.byteLength/image.byteLength*100}%)`);
const blobURL = URL.createObjectURL(new Blob([newImage], {type: 'image/png'}));
const img = document.createElement('img');
img.src = blobURL;
document.body.appendChild(img);
};
</script>

View File

@ -1,53 +0,0 @@
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include <stdio.h>
using namespace emscripten;
extern "C" int main(int argc, char *argv[]);
int version() {
// FIXME (@surma): Havent found a version in optipng :(
return 0;
}
struct OptiPngOpts {
int level;
};
uint8_t* result;
val compress(std::string png, OptiPngOpts opts) {
remove("input.png");
remove("output.png");
FILE* infile = fopen("input.png", "wb");
fwrite(png.c_str(), png.length(), 1, infile);
fflush(infile);
fclose(infile);
char optlevel[8];
sprintf(&optlevel[0], "-o%d", opts.level);
char* args[] = {"optipng", optlevel, "-out", "output.png", "input.png"};
main(5, args);
FILE *outfile = fopen("output.png", "rb");
fseek(outfile, 0, SEEK_END);
int fsize = ftell(outfile);
result = (uint8_t*) malloc(fsize);
fseek(outfile, 0, SEEK_SET);
fread(result, fsize, 1, outfile);
return val(typed_memory_view(fsize, result));
}
void free_result() {
free(result);
}
EMSCRIPTEN_BINDINGS(my_module) {
value_object<OptiPngOpts>("OptiPngOpts")
.field("level", &OptiPngOpts::level);
function("version", &version);
function("compress", &compress);
function("free_result", &free_result);
}

View File

@ -1,10 +0,0 @@
import {EncodeOptions} from "src/codecs/optipng/encoder";
export interface OptiPngModule extends EmscriptenWasm.Module {
compress(data: BufferSource, opts: EncodeOptions): Uint8Array;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): OptiPngModule;

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
{
"name": "optipng",
"scripts": {
"install": "tar-dependency install && napa",
"build": "npm run build:wasm",
"build:wasm": "docker run --rm -v $(pwd):/src -e SKIP_ZLIB=\"${SKIP_ZLIB}\" -e SKIP_LIBPNG=\"${SKIP_LIBPNG}\" trzeci/emscripten ./build.sh"
},
"tarDependencies": {
"node_modules/optipng": {
"url": "https://netcologne.dl.sourceforge.net/project/optipng/OptiPNG/optipng-0.7.7/optipng-0.7.7.tar.gz",
"strip": 1
}
},
"napa": {
"libpng": "emscripten-ports/libpng",
"zlib": "emscripten-ports/zlib"
},
"dependencies": {
"napa": "3.0.0",
"tar-dependency": "0.0.3"
}
}

1
codecs/oxipng/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

502
codecs/oxipng/Cargo.lock generated Normal file
View File

@ -0,0 +1,502 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bit-vec"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "build_const"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bumpalo"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bytemuck"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudflare-zlib"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudflare-zlib-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cloudflare-zlib-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crc"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crc32fast"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-epoch"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-queue"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "deflate"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hermit-abi"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "image"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytemuck 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"png 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "indexmap"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "inflate"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libdeflater"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memoffset"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miniz_oxide"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-iter"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "oxipng"
version = "0.1.0"
dependencies = [
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"oxipng 2.3.0 (git+https://github.com/shssoichiro/oxipng.git)",
"wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "oxipng"
version = "2.3.0"
source = "git+https://github.com/shssoichiro/oxipng.git#ec8ecf5a800dfb41359d9cf41eed8a730062b9a8"
dependencies = [
"bit-vec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"cloudflare-zlib 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libdeflater 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rgb 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
"zopfli 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "png"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"deflate 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rgb"
version = "0.8.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typed-arena"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wasm-bindgen"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-macro 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-backend 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "zopfli"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[metadata]
"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum bit-vec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4523a10839ffae575fb08aa3423026c8cb4687eef43952afb956229d4f246f7"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
"checksum bumpalo 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187"
"checksum bytemuck 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431"
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum cloudflare-zlib 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ed63a019d55bacd15cadcbcb96bf41b16281417fff393bdb55fa84255fe4b9"
"checksum cloudflare-zlib-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e195cb274a0d6ee87e718838a09baecd7cbc9f6075dac256a84cb5842739c06"
"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
"checksum deflate 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "050ef6de42a33903b30a7497b76b40d3d58691d4d3eec355348c122444a388f0"
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
"checksum hermit-abi 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "725cf19794cf90aa94e65050cb4191ff5d8fa87a498383774c47b332e3af952e"
"checksum image 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9062b90712d25bc6bb165d110aa59c6b47c849246e341e7b86a98daff9d49f60"
"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.68 (registry+https://github.com/rust-lang/crates.io-index)" = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0"
"checksum libdeflater 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "66dca08b13369865b2f6dca1dd05f833985cbe6c12a676b04d55f78b85e80246"
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
"checksum memoffset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
"checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
"checksum num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6"
"checksum oxipng 2.3.0 (git+https://github.com/shssoichiro/oxipng.git)" = "<none>"
"checksum png 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46060468187c21c00ffa2a920690b29997d7fd543f5a4d400461e4a7d4fccde8"
"checksum proc-macro2 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "df246d292ff63439fea9bc8c0a270bed0e390d5ebd4db4ba15aba81111b5abe3"
"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f"
"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
"checksum rgb 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "a85b83fd629b0ce765f45316774fa6aaa95947fd74c8e4bbf3c6d1e349701d95"
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
"checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
"checksum wasm-bindgen 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f"
"checksum wasm-bindgen-backend 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd"
"checksum wasm-bindgen-macro 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4"
"checksum wasm-bindgen-macro-support 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931"
"checksum wasm-bindgen-shared 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639"
"checksum zopfli 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4079b79464426ade2a1b0177fb0ce8396ba6b4084267407e333573c666073964"

21
codecs/oxipng/Cargo.toml Normal file
View File

@ -0,0 +1,21 @@
[package]
name = "oxipng"
version = "0.1.0"
authors = ["Ingvar Stepanyan <me@rreverser.com>"]
edition = "2018"
publish = false
[lib]
crate-type = ["cdylib"]
[dependencies]
oxipng = { version = "2.3.0", default-features = false }
wasm-bindgen = "0.2.48"
log = { version = "0.4", features = ["release_max_level_off"] }
[profile.release]
lto = true
opt-level = "s"
[patch.crates-io]
oxipng = { git = "https://github.com/shssoichiro/oxipng.git", branch = "master" }

12
codecs/oxipng/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM rust
RUN rustup target add wasm32-unknown-unknown
RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
RUN mkdir /opt/wabt && \
curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.11/wabt-1.0.11-linux.tar.gz | tar -xzf - -C /opt/wabt --strip 1
RUN mkdir /opt/wasi-sdk && \
curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk-8.0-linux.tar.gz | tar -xzf - -C /opt/wasi-sdk --strip 1
ENV PATH="/opt/wabt:/opt/wasi-sdk/bin:${PATH}"
WORKDIR /src

22
codecs/oxipng/build.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/bash
set -e
echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
wasm-pack build
wasm-strip pkg/oxipng_bg.wasm
rm pkg/.gitignore
)
echo "============================================="
echo "Compiling wasm done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull ubuntu\`"
echo "Run \`docker pull rust\`"
echo "Run \`docker build -t squoosh-oxipng .\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

4
codecs/oxipng/package-lock.json generated Normal file
View File

@ -0,0 +1,4 @@
{
"name": "oxipng",
"lockfileVersion": 1
}

View File

@ -0,0 +1,7 @@
{
"name": "oxipng",
"scripts": {
"build:image": "docker build -t squoosh-oxipng .",
"build": "docker run --rm -v $(pwd):/src squoosh-oxipng ./build.sh"
}
}

8
codecs/oxipng/pkg/oxipng.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/* tslint:disable */
/* eslint-disable */
/**
* @param {Uint8Array} data
* @param {number} level
* @returns {Uint8Array}
*/
export function optimise(data: Uint8Array, level: number): Uint8Array;

View File

@ -0,0 +1,60 @@
import * as wasm from './oxipng_bg.wasm';
const lTextDecoder = typeof TextDecoder === 'undefined' ? require('util').TextDecoder : TextDecoder;
let cachedTextDecoder = new lTextDecoder('utf-8', { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
let cachegetUint8Memory0 = null;
function getUint8Memory0() {
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
let WASM_VECTOR_LEN = 0;
function passArray8ToWasm0(arg, malloc) {
const ptr = malloc(arg.length * 1);
getUint8Memory0().set(arg, ptr / 1);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
let cachegetInt32Memory0 = null;
function getInt32Memory0() {
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory0;
}
function getArrayU8FromWasm0(ptr, len) {
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
}
/**
* @param {Uint8Array} data
* @param {number} level
* @returns {Uint8Array}
*/
export function optimise(data, level) {
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
wasm.optimise(8, ptr0, len0, level);
var r0 = getInt32Memory0()[8 / 4 + 0];
var r1 = getInt32Memory0()[8 / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v1;
}
export const __wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};

8
codecs/oxipng/pkg/oxipng_bg.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function optimise(a: number, b: number, c: number, d: number): void;
export function malloc(a: number): number;
export function free(a: number): void;
export function __wbindgen_malloc(a: number): number;
export function __wbindgen_free(a: number, b: number): void;

Binary file not shown.

View File

@ -0,0 +1,15 @@
{
"name": "oxipng",
"collaborators": [
"Ingvar Stepanyan <me@rreverser.com>"
],
"version": "0.1.0",
"files": [
"oxipng_bg.wasm",
"oxipng.js",
"oxipng.d.ts"
],
"module": "oxipng.js",
"types": "oxipng.d.ts",
"sideEffects": false
}

10
codecs/oxipng/src/lib.rs Normal file
View File

@ -0,0 +1,10 @@
mod malloc_shim;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(catch)]
pub fn optimise(data: &[u8], level: u8) -> Vec<u8> {
let mut options = oxipng::Options::from_preset(level);
options.deflate = oxipng::Deflaters::Libdeflater;
oxipng::optimize_from_memory(data, &options).unwrap_throw()
}

View File

@ -0,0 +1,47 @@
//! This is a module that provides `malloc` and `free` for `libdeflate`.
//! These implementations are compatible with the standard signatures
//! but use Rust allocator instead of including libc one as well.
//!
//! Rust allocator APIs requires passing size and alignment to the
//! `dealloc` function. This is different from C API, which only
//! expects a pointer in `free` and expects allocators to take care of
//! storing any necessary information elsewhere.
//!
//! In order to simulate C API, we allocate a `size_and_data_ptr`
//! of size `sizeof(usize) + size` where `size` is the requested number
//! of bytes. Then, we store `size` at the beginning of the allocated
//! chunk (within those `sizeof(usize)` bytes) and return
//! `data_ptr = size_and_data_ptr + sizeof(usize)` to the calleer:
//!
//! [`size`][...actual data]
//! -^------------------ `size_and_data_ptr`
//! ---------^---------- `data_ptr`
//!
//! Then, in `free`, the caller gives us `data_ptr`. We can subtract
//! `sizeof(usize)` back and get the original `size_and_data_ptr`.
//! At this point we can read `size` back and call the Rust `dealloc`
//! for the whole allocated chunk.
//!
//! I've raised an upstream issue to hopefully make this easier in
//! future: https://github.com/ebiggers/libdeflate/issues/62
use std::alloc::*;
use std::mem::{align_of, size_of};
unsafe fn layout_for(size: usize) -> Layout {
Layout::from_size_align_unchecked(size_of::<usize>() + size, align_of::<usize>())
}
#[no_mangle]
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
let size_and_data_ptr = alloc(layout_for(size));
*(size_and_data_ptr as *mut usize) = size;
size_and_data_ptr.add(size_of::<usize>())
}
#[no_mangle]
pub unsafe extern "C" fn free(data_ptr: *mut u8) {
let size_and_data_ptr = data_ptr.sub(size_of::<usize>());
let size = *(size_and_data_ptr as *const usize);
dealloc(size_and_data_ptr, layout_for(size))
}

View File

@ -3,3 +3,4 @@ target
Cargo.lock
bin/
pkg/README.md
lut.inc

View File

@ -1,18 +1,9 @@
FROM ubuntu
RUN apt-get update && \
apt-get install -qqy git build-essential cmake python2.7
RUN git clone --recursive https://github.com/WebAssembly/wabt /usr/src/wabt
RUN mkdir -p /usr/src/wabt/build
WORKDIR /usr/src/wabt/build
RUN cmake .. -DCMAKE_INSTALL_PREFIX=/opt/wabt && \
make && \
make install
FROM rust
RUN rustup install nightly && \
rustup target add --toolchain nightly wasm32-unknown-unknown && \
cargo install wasm-pack
RUN rustup target add wasm32-unknown-unknown
RUN curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
COPY --from=0 /opt/wabt /opt/wabt
ENV PATH="/opt/wabt/bin:${PATH}"
RUN mkdir /opt/wabt && \
curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.11/wabt-1.0.11-linux.tar.gz | tar -xzf - -C /opt/wabt --strip 1
ENV PATH="/opt/wabt:${PATH}"
WORKDIR /src

View File

@ -1,41 +0,0 @@
// THIS IS NOT A NODE SCRIPT
// This is a d8 script. Please install jsvu[1] and install v8.
// Then run `npm run --silent benchmark`.
// [1]: https://github.com/GoogleChromeLabs/jsvu
self = global = this;
load('./pkg/resize.js');
async function init() {
// Adjustable constants.
const inputDimensions = 2000;
const outputDimensions = 1500;
const algorithm = 3; // Lanczos
const iterations = new Array(100);
// Constants. Dont change.
const imageByteSize = inputDimensions * inputDimensions * 4;
const imageBuffer = new Uint8ClampedArray(imageByteSize);
const module = await WebAssembly.compile(readbuffer("./pkg/resize_bg.wasm"));
await wasm_bindgen(module);
[false, true].forEach(premulti => {
print(`\npremultiplication: ${premulti}`);
print(`==============================`);
for (let i = 0; i < 100; i++) {
const start = Date.now();
wasm_bindgen.resize(imageBuffer, inputDimensions, inputDimensions, outputDimensions, outputDimensions, algorithm, premulti);
iterations[i] = Date.now() - start;
}
const average = iterations.reduce((sum, c) => sum + c) / iterations.length;
const stddev = Math.sqrt(
iterations
.map(i => Math.pow(i - average, 2))
.reduce((sum, c) => sum + c) / iterations.length
);
print(`n = ${iterations.length}`);
print(`Average: ${average}`);
print(`StdDev: ${stddev}`);
});
}
init().catch(e => console.error(e, e.stack));

23
codecs/resize/build.rs Normal file
View File

@ -0,0 +1,23 @@
include!("./src/srgb.rs");
use std::io::Write;
fn main() -> std::io::Result<()> {
let mut srgb_to_linear_lut = String::from("static SRGB_TO_LINEAR_LUT: [f32; 256] = [");
let mut linear_to_srgb_lut = String::from("static LINEAR_TO_SRGB_LUT: [f32; 256] = [");
for i in 0..256 {
srgb_to_linear_lut.push_str(&format!("{0:.7}", srgb_to_linear((i as f32) / 255.0)));
srgb_to_linear_lut.push_str(",");
linear_to_srgb_lut.push_str(&format!("{0:.7}", linear_to_srgb((i as f32) / 255.0)));
linear_to_srgb_lut.push_str(",");
}
srgb_to_linear_lut.pop().unwrap();
linear_to_srgb_lut.pop().unwrap();
srgb_to_linear_lut.push_str("];");
linear_to_srgb_lut.push_str("];");
let mut file = std::fs::File::create("src/lut.inc")?;
file.write_all(srgb_to_linear_lut.as_bytes())?;
file.write_all(linear_to_srgb_lut.as_bytes())?;
Ok(())
}

View File

@ -6,9 +6,9 @@ echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
rustup run nightly \
wasm-pack build --target no-modules
wasm-pack build
wasm-strip pkg/resize_bg.wasm
rm pkg/.gitignore
)
echo "============================================="
echo "Compiling wasm done"

View File

@ -2,7 +2,6 @@
"name": "resize",
"scripts": {
"build:image": "docker build -t squoosh-resize .",
"build": "docker run --rm -v $(pwd):/src squoosh-resize ./build.sh",
"benchmark": "v8 --no-liftoff --no-wasm-tier-up ./benchmark.js"
"build": "docker run --rm -v $(pwd):/src squoosh-resize ./build.sh"
}
}

View File

@ -0,0 +1,15 @@
{
"name": "resize",
"collaborators": [
"Surma <surma@surma.link>"
],
"version": "0.1.0",
"files": [
"resize_bg.wasm",
"resize.js",
"resize.d.ts"
],
"module": "resize.js",
"types": "resize.d.ts",
"sideEffects": "false"
}

View File

@ -1,12 +1,13 @@
/* tslint:disable */
/**
* @param {Uint8Array} arg0
* @param {number} arg1
* @param {number} arg2
* @param {number} arg3
* @param {number} arg4
* @param {number} arg5
* @param {boolean} arg6
* @param {Uint8Array} input_image
* @param {number} input_width
* @param {number} input_height
* @param {number} output_width
* @param {number} output_height
* @param {number} typ_idx
* @param {boolean} premultiply
* @param {boolean} color_space_conversion
* @returns {Uint8Array}
*/
export function resize(arg0: Uint8Array, arg1: number, arg2: number, arg3: number, arg4: number, arg5: number, arg6: boolean): Uint8Array;
export function resize(input_image: Uint8Array, input_width: number, input_height: number, output_width: number, output_height: number, typ_idx: number, premultiply: boolean, color_space_conversion: boolean): Uint8Array;

View File

@ -1,113 +1,50 @@
(function() {
var wasm;
const __exports = {};
import * as wasm from './resize_bg.wasm';
let cachegetUint8Memory = null;
function getUint8Memory() {
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory;
let cachegetUint8Memory = null;
function getUint8Memory() {
if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== wasm.memory.buffer) {
cachegetUint8Memory = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory;
}
let WASM_VECTOR_LEN = 0;
let WASM_VECTOR_LEN = 0;
function passArray8ToWasm(arg) {
const ptr = wasm.__wbindgen_malloc(arg.length * 1);
getUint8Memory().set(arg, ptr / 1);
WASM_VECTOR_LEN = arg.length;
return ptr;
function passArray8ToWasm(arg) {
const ptr = wasm.__wbindgen_malloc(arg.length * 1);
getUint8Memory().set(arg, ptr / 1);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
let cachegetInt32Memory = null;
function getInt32Memory() {
if (cachegetInt32Memory === null || cachegetInt32Memory.buffer !== wasm.memory.buffer) {
cachegetInt32Memory = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory;
}
function getArrayU8FromWasm(ptr, len) {
return getUint8Memory().subarray(ptr / 1, ptr / 1 + len);
}
function getArrayU8FromWasm(ptr, len) {
return getUint8Memory().subarray(ptr / 1, ptr / 1 + len);
}
/**
* @param {Uint8Array} input_image
* @param {number} input_width
* @param {number} input_height
* @param {number} output_width
* @param {number} output_height
* @param {number} typ_idx
* @param {boolean} premultiply
* @param {boolean} color_space_conversion
* @returns {Uint8Array}
*/
export function resize(input_image, input_width, input_height, output_width, output_height, typ_idx, premultiply, color_space_conversion) {
const retptr = 8;
const ret = wasm.resize(retptr, passArray8ToWasm(input_image), WASM_VECTOR_LEN, input_width, input_height, output_width, output_height, typ_idx, premultiply, color_space_conversion);
const memi32 = getInt32Memory();
const v0 = getArrayU8FromWasm(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1]).slice();
wasm.__wbindgen_free(memi32[retptr / 4 + 0], memi32[retptr / 4 + 1] * 1);
return v0;
}
let cachedGlobalArgumentPtr = null;
function globalArgumentPtr() {
if (cachedGlobalArgumentPtr === null) {
cachedGlobalArgumentPtr = wasm.__wbindgen_global_argument_ptr();
}
return cachedGlobalArgumentPtr;
}
let cachegetUint32Memory = null;
function getUint32Memory() {
if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== wasm.memory.buffer) {
cachegetUint32Memory = new Uint32Array(wasm.memory.buffer);
}
return cachegetUint32Memory;
}
/**
* @param {Uint8Array} arg0
* @param {number} arg1
* @param {number} arg2
* @param {number} arg3
* @param {number} arg4
* @param {number} arg5
* @param {boolean} arg6
* @returns {Uint8Array}
*/
__exports.resize = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
const ptr0 = passArray8ToWasm(arg0);
const len0 = WASM_VECTOR_LEN;
const retptr = globalArgumentPtr();
wasm.resize(retptr, ptr0, len0, arg1, arg2, arg3, arg4, arg5, arg6);
const mem = getUint32Memory();
const rustptr = mem[retptr / 4];
const rustlen = mem[retptr / 4 + 1];
const realRet = getArrayU8FromWasm(rustptr, rustlen).slice();
wasm.__wbindgen_free(rustptr, rustlen * 1);
return realRet;
};
const heap = new Array(32);
heap.fill(undefined);
heap.push(undefined, null, true, false);
let heap_next = heap.length;
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
heap_next = idx;
}
__exports.__wbindgen_object_drop_ref = function(i) { dropObject(i); };
function init(path_or_module) {
let instantiation;
const imports = { './resize': __exports };
if (path_or_module instanceof WebAssembly.Module) {
instantiation = WebAssembly.instantiate(path_or_module, imports)
.then(instance => {
return { instance, module: path_or_module }
});
} else {
const data = fetch(path_or_module);
if (typeof WebAssembly.instantiateStreaming === 'function') {
instantiation = WebAssembly.instantiateStreaming(data, imports)
.catch(e => {
console.warn("`WebAssembly.instantiateStreaming` failed. Assuming this is because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
return data
.then(r => r.arrayBuffer())
.then(bytes => WebAssembly.instantiate(bytes, imports));
});
} else {
instantiation = data
.then(response => response.arrayBuffer())
.then(buffer => WebAssembly.instantiate(buffer, imports));
}
}
return instantiation.then(({instance}) => {
wasm = init.wasm = instance.exports;
});
};
self.wasm_bindgen = Object.assign(init, __exports);
})();

View File

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

Binary file not shown.

View File

@ -9,6 +9,9 @@ use resize::Pixel::RGBA;
use resize::Type;
use wasm_bindgen::prelude::*;
mod srgb;
use srgb::Clamp;
cfg_if! {
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
// allocator.
@ -19,6 +22,39 @@ cfg_if! {
}
}
include!("./lut.inc");
// If `with_space_conversion` is true, this function returns 2 functions that
// convert from sRGB to linear RGB and vice versa. If `with_space_conversion` is
// false, the 2 functions returned do nothing.
fn converter_funcs(with_space_conversion: bool) -> ((fn(u8) -> f32), (fn(f32) -> u8)) {
if with_space_conversion {
(
|v| SRGB_TO_LINEAR_LUT[v as usize] * 255.0,
|v| (LINEAR_TO_SRGB_LUT[v as usize] * 255.0) as u8,
)
} else {
(|v| v as f32, |v| v as u8)
}
}
// If `with_alpha_premultiplication` is true, this function returns a function
// that premultiply the alpha channel with the given channel value and another
// function that reverses that process. If `with_alpha_premultiplication` is
// false, the functions just return the channel value.
fn alpha_multiplier_funcs(
with_alpha_premultiplication: bool,
) -> ((fn(f32, u8) -> u8), (fn(u8, u8) -> f32)) {
if with_alpha_premultiplication {
(
|v, a| (v * (a as f32) / 255.0) as u8,
|v, a| (v as f32) * 255.0 / (a as f32).clamp(0.0, 255.0),
)
} else {
(|v, _a| v as u8, |v, _a| v as f32)
}
}
#[wasm_bindgen]
#[no_mangle]
pub fn resize(
@ -29,6 +65,7 @@ pub fn resize(
output_height: usize,
typ_idx: usize,
premultiply: bool,
color_space_conversion: bool,
) -> Vec<u8> {
let typ = match typ_idx {
0 => Type::Triangle,
@ -40,12 +77,16 @@ pub fn resize(
let num_input_pixels = input_width * input_height;
let num_output_pixels = output_width * output_height;
if premultiply {
let (to_linear, to_color_space) = converter_funcs(color_space_conversion);
let (premultiplier, demultiplier) = alpha_multiplier_funcs(premultiply);
// If both options are false, there is no preprocessing on the pixel valus
// and we can skip the loop.
if premultiply || color_space_conversion {
for i in 0..num_input_pixels {
for j in 0..3 {
input_image[4 * i + j] = ((input_image[4 * i + j] as f32)
* (input_image[4 * i + 3] as f32)
/ 255.0) as u8;
input_image[4 * i + j] =
premultiplier(to_linear(input_image[4 * i + j]), input_image[4 * i + 3]);
}
}
}
@ -62,15 +103,16 @@ pub fn resize(
output_image.resize(num_output_pixels * 4, 0);
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
if premultiply {
if premultiply || color_space_conversion {
for i in 0..num_output_pixels {
for j in 0..3 {
// We dont need to worry about division by zero, as division by zero
// is well-defined on floats to return `±Inf`. ±Inf is converted to 0
// is well-defined on floats to return ±Inf. ±Inf is converted to 0
// when casting to integers.
output_image[4 * i + j] = ((output_image[4 * i + j] as f32) * 255.0
/ (output_image[4 * i + 3] as f32))
as u8;
output_image[4 * i + j] = to_color_space(demultiplier(
output_image[4 * i + j],
output_image[4 * i + 3],
));
}
}
}

29
codecs/resize/src/srgb.rs Normal file
View File

@ -0,0 +1,29 @@
pub trait Clamp: std::cmp::PartialOrd + Sized {
fn clamp(self, min: Self, max: Self) -> Self {
if self.lt(&min) {
min
} else if self.gt(&max) {
max
} else {
self
}
}
}
impl Clamp for f32 {}
pub fn srgb_to_linear(v: f32) -> f32 {
if v < 0.04045 {
v / 12.92
} else {
((v + 0.055) / 1.055).powf(2.4).clamp(0.0, 1.0)
}
}
pub fn linear_to_srgb(v: f32) -> f32 {
if v < 0.0031308 {
v * 12.92
} else {
(1.055 * v.powf(1.0 / 2.4) - 0.055).clamp(0.0, 1.0)
}
}

View File

@ -1,17 +1,8 @@
FROM ubuntu
RUN apt-get update && \
apt-get install -qqy git build-essential cmake python2.7
RUN git clone --recursive https://github.com/WebAssembly/wabt /usr/src/wabt
RUN mkdir -p /usr/src/wabt/build
WORKDIR /usr/src/wabt/build
RUN cmake .. -DCMAKE_INSTALL_PREFIX=/opt/wabt && \
make && \
make install
FROM rust
RUN rustup install nightly && \
rustup target add --toolchain nightly wasm32-unknown-unknown
RUN rustup target add wasm32-unknown-unknown
COPY --from=0 /opt/wabt /opt/wabt
ENV PATH="/opt/wabt/bin:${PATH}"
RUN mkdir /opt/wabt && \
curl -L https://github.com/WebAssembly/wabt/releases/download/1.0.11/wabt-1.0.11-linux.tar.gz | tar -xzf - -C /opt/wabt --strip 1
ENV PATH="/opt/wabt:${PATH}"
WORKDIR /src

View File

@ -6,8 +6,7 @@ echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
rustup run nightly \
cargo build \
cargo build \
--target wasm32-unknown-unknown \
--release
cp target/wasm32-unknown-unknown/release/rotate.wasm .

Binary file not shown.

38
codecs/webp_enc/build.sh → codecs/webp/build.sh Executable file → Normal file
View File

@ -2,23 +2,21 @@
set -e
export OPTIMIZE="-Os"
export EM_CACHE="${PWD}/node_modules/.em_cache"
export OPTIMIZE="-Os -flto --llvm-lto 1"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
apt-get update
apt-get install -qqy autoconf libtool libpng-dev pkg-config
apt-get install -qqy autoconf libtool pkg-config
echo "============================================="
echo "Compiling libwebp"
echo "============================================="
test -n "$SKIP_LIBWEBP" || (
cd node_modules/libwebp
autoreconf -fiv
rm -rf build || true
mkdir -p build && cd build
emconfigure ../configure \
autoreconf -iv
emconfigure ./configure -C \
--disable-libwebpdemux \
--disable-wic \
--disable-gif \
@ -32,7 +30,7 @@ test -n "$SKIP_LIBWEBP" || (
--disable-neon \
--disable-sse2 \
--disable-sse4.1
emmake make
emmake make -j`nproc`
)
echo "============================================="
echo "Compiling wasm bindings"
@ -40,16 +38,28 @@ echo "============================================="
(
emcc \
${OPTIMIZE} \
--closure 1 \
--bind \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="webp_dec"' \
-I node_modules/libwebp \
-o dec/webp_dec.js \
dec/webp_dec.cpp \
node_modules/libwebp/src/.libs/libwebp.a
)
(
emcc \
${OPTIMIZE} \
--closure 1 \
--bind \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="webp_enc"' \
--std=c++11 \
-I node_modules/libwebp \
-o ./webp_enc.js \
-x c++ \
webp_enc.cpp \
node_modules/libwebp/build/src/.libs/libwebp.a
-o enc/webp_enc.js \
enc/webp_enc.cpp \
node_modules/libwebp/src/.libs/libwebp.a
)
echo "============================================="
echo "Compiling wasm bindings done"
@ -57,5 +67,5 @@ echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "Run \`docker pull trzeci/emscripten-upstream\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -10,7 +10,7 @@
Module.onRuntimeInitialized = async _ => {
console.log('Version:', Module.version().toString(16));
const image = await loadFile('../example.webp');
const image = await loadFile('../../example.webp');
const result = Module.decode(image);
const imageData = new ImageData(new Uint8ClampedArray(result.buffer), result.width, result.height);
Module.free_result();

View File

@ -1,8 +1,8 @@
#include <string>
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include "src/webp/decode.h"
#include "src/webp/demux.h"
#include <string>
using namespace emscripten;
@ -11,24 +11,19 @@ int version() {
}
class RawImage {
public:
public:
val buffer;
int width;
int height;
RawImage(val b, int w, int h)
: buffer(b), width(w), height(h) {}
RawImage(val b, int w, int h) : buffer(b), width(w), height(h) {}
};
uint8_t* last_result;
RawImage decode(std::string buffer) {
int width, height;
last_result = WebPDecodeRGBA((const uint8_t*)buffer.c_str(), buffer.size(), &width, &height);
return RawImage(
val(typed_memory_view(width*height*4, last_result)),
width,
height
);
return RawImage(val(typed_memory_view(width * height * 4, last_result)), width, height);
}
void free_result() {
@ -37,9 +32,9 @@ void free_result() {
EMSCRIPTEN_BINDINGS(my_module) {
class_<RawImage>("RawImage")
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
function("decode", &decode);
function("version", &version);

View File

@ -0,0 +1,79 @@
var webp_dec = (function() {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
return (
function(webp_dec) {
webp_dec = webp_dec || {};
var e;e||(e=typeof webp_dec !== 'undefined' ? webp_dec : {});var r={},w;for(w in e)e.hasOwnProperty(w)&&(r[w]=e[w]);var aa=!1,z=!1,ba=!1,ca=!1;aa="object"===typeof window;z="function"===typeof importScripts;ba="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node;ca=!aa&&!ba&&!z;var A="",da,B,ea,ha;
if(ba)A=z?require("path").dirname(A)+"/":__dirname+"/",da=function(a,b){ea||(ea=require("fs"));ha||(ha=require("path"));a=ha.normalize(a);return ea.readFileSync(a,b?null:"utf8")},B=function(a){a=da(a,!0);a.buffer||(a=new Uint8Array(a));a.buffer||D("Assertion failed: undefined");return a},1<process.argv.length&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),process.on("uncaughtException",function(a){throw a;}),process.on("unhandledRejection",D),e.inspect=function(){return"[Emscripten Module object]"};
else if(ca)"undefined"!=typeof read&&(da=function(a){return read(a)}),B=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");"object"===typeof a||D("Assertion failed: undefined");return a},"undefined"!==typeof print&&("undefined"===typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!==typeof printErr?printErr:print);else if(aa||z)z?A=self.location.href:document.currentScript&&(A=document.currentScript.src),_scriptDir&&
(A=_scriptDir),0!==A.indexOf("blob:")?A=A.substr(0,A.lastIndexOf("/")+1):A="",da=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},z&&(B=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)});var ia=e.print||console.log.bind(console),E=e.printErr||console.warn.bind(console);for(w in r)r.hasOwnProperty(w)&&(e[w]=r[w]);r=null;var F;e.wasmBinary&&(F=e.wasmBinary);var noExitRuntime;
e.noExitRuntime&&(noExitRuntime=e.noExitRuntime);"object"!==typeof WebAssembly&&E("no native wasm support detected");var G,ja=new WebAssembly.Table({initial:138,maximum:138,element:"anyfunc"}),ka=!1,la="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;
function ma(a,b,c){var d=H;if(0<c){c=b+c-1;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var q=a.charCodeAt(++f);g=65536+((g&1023)<<10)|q&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 na="undefined"!==typeof TextDecoder?new TextDecoder("utf-16le"):void 0;
function oa(a){var b;for(b=a>>1;I[b];)++b;b<<=1;if(32<b-a&&na)return na.decode(H.subarray(a,b));b=0;for(var c="";;){var d=I[a+2*b>>1];if(0==d)return c;++b;c+=String.fromCharCode(d)}}function pa(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 f=0;f<c;++f)I[b>>1]=a.charCodeAt(f),b+=2;I[b>>1]=0;return b-d}function qa(a){return 2*a.length}
function ra(a){for(var b=0,c="";;){var d=J[a+4*b>>2];if(0==d)return c;++b;65536<=d?(d-=65536,c+=String.fromCharCode(55296|d>>10,56320|d&1023)):c+=String.fromCharCode(d)}}function sa(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var d=b;c=d+c-4;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var q=a.charCodeAt(++f);g=65536+((g&1023)<<10)|q&1023}J[b>>2]=g;b+=4;if(b+4>c)break}J[b>>2]=0;return b-d}
function ta(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 K,ua,H,I,va,J,L,wa,xa;function ya(a){K=a;e.HEAP8=ua=new Int8Array(a);e.HEAP16=I=new Int16Array(a);e.HEAP32=J=new Int32Array(a);e.HEAPU8=H=new Uint8Array(a);e.HEAPU16=va=new Uint16Array(a);e.HEAPU32=L=new Uint32Array(a);e.HEAPF32=wa=new Float32Array(a);e.HEAPF64=xa=new Float64Array(a)}var za=e.INITIAL_MEMORY||16777216;e.wasmMemory?G=e.wasmMemory:G=new WebAssembly.Memory({initial:za/65536});
G&&(K=G.buffer);za=K.byteLength;ya(K);J[3336]=5256384;function Aa(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b();else{var c=b.ka;"number"===typeof c?void 0===b.ba?e.dynCall_v(c):e.dynCall_vi(c,b.ba):c(void 0===b.ba?null:b.ba)}}}var Ba=[],Ca=[],Da=[],Ea=[];function Fa(){var a=e.preRun.shift();Ba.unshift(a)}var M=0,Ga=null,N=null;e.preloadedImages={};e.preloadedAudios={};
function D(a){if(e.onAbort)e.onAbort(a);ia(a);E(a);ka=!0;throw new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");}function Ha(){var a=O;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var O="webp_dec.wasm";if(!Ha()){var Ia=O;O=e.locateFile?e.locateFile(Ia,A):A+Ia}
function Ja(){try{if(F)return new Uint8Array(F);if(B)return B(O);throw"both async and sync fetching of the wasm failed";}catch(a){D(a)}}function Ka(){return F||!aa&&!z||"function"!==typeof fetch?new Promise(function(a){a(Ja())}):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 Ja()})}Ca.push({ka:function(){La()}});function Ma(){return 0<Ma.X}
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 P(a){for(var b="";H[a];)b+=Oa[H[a++]];return b}var Q={},R={},Pa={};function Qa(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 Ra(a,b){a=Qa(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}function Sa(a){var b=Error,c=Ra(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 Ta=void 0;function S(a){throw new Ta(a);}var Ua=void 0;function Va(a){throw new Ua(a);}function Wa(a,b,c){function d(h){h=c(h);h.length!==a.length&&Va("Mismatched type converter count");for(var l=0;l<a.length;++l)T(a[l],h[l])}a.forEach(function(h){Pa[h]=b});var f=Array(b.length),g=[],q=0;b.forEach(function(h,l){R.hasOwnProperty(h)?f[l]=R[h]:(g.push(h),Q.hasOwnProperty(h)||(Q[h]=[]),Q[h].push(function(){f[l]=R[h];++q;q===g.length&&d(f)}))});0===g.length&&d(f)}
function T(a,b,c){c=c||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var d=b.name;a||S('type "'+d+'" must have a positive integer typeid pointer');if(R.hasOwnProperty(a)){if(c.na)return;S("Cannot register type '"+d+"' twice")}R[a]=b;delete Pa[a];Q.hasOwnProperty(a)&&(b=Q[a],delete Q[a],b.forEach(function(f){f()}))}function Xa(a){return{count:a.count,W:a.W,Y:a.Y,L:a.L,N:a.N,O:a.O,P:a.P}}
function Ya(a){S(a.K.N.M.name+" instance already deleted")}var Za=!1;function $a(){}function ab(a){--a.count.value;0===a.count.value&&(a.O?a.P.V(a.O):a.N.M.V(a.L))}function bb(a){if("undefined"===typeof FinalizationGroup)return bb=function(b){return b},a;Za=new FinalizationGroup(function(b){for(var c=b.next();!c.done;c=b.next())c=c.value,c.L?ab(c):console.warn("object already deleted: "+c.L)});bb=function(b){Za.register(b,b.K,b.K);return b};$a=function(b){Za.unregister(b.K)};return bb(a)}
var cb=void 0,db=[];function eb(){for(;db.length;){var a=db.pop();a.K.W=!1;a["delete"]()}}function U(){}var fb={};function gb(a,b){var c=e;if(void 0===c[a].S){var d=c[a];c[a]=function(){c[a].S.hasOwnProperty(arguments.length)||S("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+c[a].S+")!");return c[a].S[arguments.length].apply(this,arguments)};c[a].S=[];c[a].S[d.ha]=d}}
function hb(a,b,c){e.hasOwnProperty(a)?((void 0===c||void 0!==e[a].S&&void 0!==e[a].S[c])&&S("Cannot register public name '"+a+"' twice"),gb(a,a),e.hasOwnProperty(c)&&S("Cannot register multiple overloads of a function with the same number of arguments ("+c+")!"),e[a].S[c]=b):(e[a]=b,void 0!==c&&(e[a].ta=c))}function ib(a,b,c,d,f,g,q,h){this.name=a;this.constructor=b;this.U=c;this.V=d;this.R=f;this.la=g;this.Z=q;this.ja=h}
function jb(a,b,c){for(;b!==c;)b.Z||S("Expected null or instance of "+c.name+", got an instance of "+b.name),a=b.Z(a),b=b.R;return a}function kb(a,b){if(null===b)return this.da&&S("null is not a valid "+this.name),0;b.K||S('Cannot pass "'+V(b)+'" as a '+this.name);b.K.L||S("Cannot pass deleted object as a pointer of type "+this.name);return jb(b.K.L,b.K.N.M,this.M)}
function lb(a,b){if(null===b){this.da&&S("null is not a valid "+this.name);if(this.aa){var c=this.pa();null!==a&&a.push(this.V,c);return c}return 0}b.K||S('Cannot pass "'+V(b)+'" as a '+this.name);b.K.L||S("Cannot pass deleted object as a pointer of type "+this.name);!this.$&&b.K.N.$&&S("Cannot convert argument of type "+(b.K.P?b.K.P.name:b.K.N.name)+" to parameter type "+this.name);c=jb(b.K.L,b.K.N.M,this.M);if(this.aa)switch(void 0===b.K.O&&S("Passing raw pointer to smart pointer is illegal"),this.ra){case 0:b.K.P===
this?c=b.K.O:S("Cannot convert argument of type "+(b.K.P?b.K.P.name:b.K.N.name)+" to parameter type "+this.name);break;case 1:c=b.K.O;break;case 2:if(b.K.P===this)c=b.K.O;else{var d=b.clone();c=this.qa(c,mb(function(){d["delete"]()}));null!==a&&a.push(this.V,c)}break;default:S("Unsupporting sharing policy")}return c}
function nb(a,b){if(null===b)return this.da&&S("null is not a valid "+this.name),0;b.K||S('Cannot pass "'+V(b)+'" as a '+this.name);b.K.L||S("Cannot pass deleted object as a pointer of type "+this.name);b.K.N.$&&S("Cannot convert argument of type "+b.K.N.name+" to parameter type "+this.name);return jb(b.K.L,b.K.N.M,this.M)}function pb(a){return this.fromWireType(L[a>>2])}function qb(a,b,c){if(b===c)return a;if(void 0===c.R)return null;a=qb(a,b,c.R);return null===a?null:c.ja(a)}var rb={};
function sb(a,b){for(void 0===b&&S("ptr should not be undefined");a.R;)b=a.Z(b),a=a.R;return rb[b]}function tb(a,b){b.N&&b.L||Va("makeClassHandle requires ptr and ptrType");!!b.P!==!!b.O&&Va("Both smartPtrType and smartPtr must be specified");b.count={value:1};return bb(Object.create(a,{K:{value:b}}))}function W(a,b,c,d){this.name=a;this.M=b;this.da=c;this.$=d;this.aa=!1;this.V=this.qa=this.pa=this.ga=this.ra=this.oa=void 0;void 0!==b.R?this.toWireType=lb:(this.toWireType=d?kb:nb,this.T=null)}
function ub(a,b,c){e.hasOwnProperty(a)||Va("Replacing nonexistant public symbol");void 0!==e[a].S&&void 0!==c?e[a].S[c]=b:(e[a]=b,e[a].ha=c)}
function X(a,b){a=P(a);var c=e["dynCall_"+a];for(var d=[],f=1;f<a.length;++f)d.push("a"+f);f="return function dynCall_"+(a+"_"+b)+"("+d.join(", ")+") {\n";f+=" return dynCall(rawFunction"+(d.length?", ":"")+d.join(", ")+");\n";c=(new Function("dynCall","rawFunction",f+"};\n"))(c,b);"function"!==typeof c&&S("unknown function pointer with signature "+a+": "+b);return c}var vb=void 0;function wb(a){a=xb(a);var b=P(a);Y(a);return b}
function yb(a,b){function c(g){f[g]||R[g]||(Pa[g]?Pa[g].forEach(c):(d.push(g),f[g]=!0))}var d=[],f={};b.forEach(c);throw new vb(a+": "+d.map(wb).join([", "]));}function zb(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function Ab(a,b,c){a instanceof Object||S(c+' with invalid "this": '+a);a instanceof b.M.constructor||S(c+' incompatible with "this" of type '+a.constructor.name);a.K.L||S("cannot call emscripten binding method "+c+" on deleted object");return jb(a.K.L,a.K.N.M,b.M)}
var Bb=[],Z=[{},{value:void 0},{value:null},{value:!0},{value:!1}];function Cb(a){4<a&&0===--Z[a].ea&&(Z[a]=void 0,Bb.push(a))}function mb(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=Bb.length?Bb.pop():Z.length;Z[b]={ea:1,value:a};return b}}function V(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}
function Db(a,b){switch(b){case 2:return function(c){return this.fromWireType(wa[c>>2])};case 3:return function(c){return this.fromWireType(xa[c>>3])};default:throw new TypeError("Unknown float type: "+a);}}function Eb(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=Ra(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c}
function Fb(a,b){for(var c=[],d=0;d<a;d++)c.push(J[(b>>2)+d]);return c}function Gb(a,b,c){switch(b){case 0:return c?function(d){return ua[d]}:function(d){return H[d]};case 1:return c?function(d){return I[d>>1]}:function(d){return va[d>>1]};case 2:return c?function(d){return J[d>>2]}:function(d){return L[d>>2]};default:throw new TypeError("Unknown integer type: "+a);}}for(var Hb=Array(256),Ib=0;256>Ib;++Ib)Hb[Ib]=String.fromCharCode(Ib);Oa=Hb;Ta=e.BindingError=Sa("BindingError");
Ua=e.InternalError=Sa("InternalError");U.prototype.isAliasOf=function(a){if(!(this instanceof U&&a instanceof U))return!1;var b=this.K.N.M,c=this.K.L,d=a.K.N.M;for(a=a.K.L;b.R;)c=b.Z(c),b=b.R;for(;d.R;)a=d.Z(a),d=d.R;return b===d&&c===a};U.prototype.clone=function(){this.K.L||Ya(this);if(this.K.Y)return this.K.count.value+=1,this;var a=bb(Object.create(Object.getPrototypeOf(this),{K:{value:Xa(this.K)}}));a.K.count.value+=1;a.K.W=!1;return a};
U.prototype["delete"]=function(){this.K.L||Ya(this);this.K.W&&!this.K.Y&&S("Object already scheduled for deletion");$a(this);ab(this.K);this.K.Y||(this.K.O=void 0,this.K.L=void 0)};U.prototype.isDeleted=function(){return!this.K.L};U.prototype.deleteLater=function(){this.K.L||Ya(this);this.K.W&&!this.K.Y&&S("Object already scheduled for deletion");db.push(this);1===db.length&&cb&&cb(eb);this.K.W=!0;return this};W.prototype.ma=function(a){this.ga&&(a=this.ga(a));return a};
W.prototype.fa=function(a){this.V&&this.V(a)};W.prototype.argPackAdvance=8;W.prototype.readValueFromPointer=pb;W.prototype.deleteObject=function(a){if(null!==a)a["delete"]()};
W.prototype.fromWireType=function(a){function b(){return this.aa?tb(this.M.U,{N:this.oa,L:c,P:this,O:a}):tb(this.M.U,{N:this,L:a})}var c=this.ma(a);if(!c)return this.fa(a),null;var d=sb(this.M,c);if(void 0!==d){if(0===d.K.count.value)return d.K.L=c,d.K.O=a,d.clone();d=d.clone();this.fa(a);return d}d=this.M.la(c);d=fb[d];if(!d)return b.call(this);d=this.$?d.ia:d.pointerType;var f=qb(c,this.M,d.M);return null===f?b.call(this):this.aa?tb(d.M.U,{N:d,L:f,P:this,O:a}):tb(d.M.U,{N:d,L:f})};
e.getInheritedInstanceCount=function(){return Object.keys(rb).length};e.getLiveInheritedInstances=function(){var a=[],b;for(b in rb)rb.hasOwnProperty(b)&&a.push(rb[b]);return a};e.flushPendingDeletes=eb;e.setDelayFunction=function(a){cb=a;db.length&&cb&&cb(eb)};vb=e.UnboundTypeError=Sa("UnboundTypeError");e.count_emval_handles=function(){for(var a=0,b=5;b<Z.length;++b)void 0!==Z[b]&&++a;return a};e.get_first_emval=function(){for(var a=5;a<Z.length;++a)if(void 0!==Z[a])return Z[a];return null};
var Kb={n:function(a){return Jb(a)},m:function(a){"uncaught_exception"in Ma?Ma.X++:Ma.X=1;throw a;},k:function(a,b,c,d,f){var g=Na(c);b=P(b);T(a,{name:b,fromWireType:function(q){return!!q},toWireType:function(q,h){return h?d:f},argPackAdvance:8,readValueFromPointer:function(q){if(1===c)var h=ua;else if(2===c)h=I;else if(4===c)h=J;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(h[q>>g])},T:null})},o:function(a,b,c,d,f,g,q,h,l,m,k,p,t){k=P(k);g=X(f,g);h&&(h=X(q,h));
m&&(m=X(l,m));t=X(p,t);var v=Qa(k);hb(v,function(){yb("Cannot construct "+k+" due to unbound types",[d])});Wa([a,b,c],d?[d]:[],function(n){n=n[0];if(d){var u=n.M;var x=u.U}else x=U.prototype;n=Ra(v,function(){if(Object.getPrototypeOf(this)!==y)throw new Ta("Use 'new' to construct "+k);if(void 0===C.X)throw new Ta(k+" has no accessible constructor");var ob=C.X[arguments.length];if(void 0===ob)throw new Ta("Tried to invoke ctor of "+k+" with invalid number of parameters ("+arguments.length+") - expected ("+
Object.keys(C.X).toString()+") parameters instead!");return ob.apply(this,arguments)});var y=Object.create(x,{constructor:{value:n}});n.prototype=y;var C=new ib(k,n,y,t,u,g,h,m);u=new W(k,C,!0,!1);x=new W(k+"*",C,!1,!1);var fa=new W(k+" const*",C,!1,!0);fb[a]={pointerType:x,ia:fa};ub(v,n);return[u,x,fa]})},e:function(a,b,c,d,f,g,q,h,l,m){b=P(b);f=X(d,f);Wa([],[a],function(k){k=k[0];var p=k.name+"."+b,t={get:function(){yb("Cannot access "+p+" due to unbound types",[c,q])},enumerable:!0,configurable:!0};
l?t.set=function(){yb("Cannot access "+p+" due to unbound types",[c,q])}:t.set=function(){S(p+" is a read-only property")};Object.defineProperty(k.M.U,b,t);Wa([],l?[c,q]:[c],function(v){var n=v[0],u={get:function(){var y=Ab(this,k,p+" getter");return n.fromWireType(f(g,y))},enumerable:!0};if(l){l=X(h,l);var x=v[1];u.set=function(y){var C=Ab(this,k,p+" setter"),fa=[];l(m,C,x.toWireType(fa,y));zb(fa)}}Object.defineProperty(k.M.U,b,u);return[]});return[]})},q:function(a,b){b=P(b);T(a,{name:b,fromWireType:function(c){var d=
Z[c].value;Cb(c);return d},toWireType:function(c,d){return mb(d)},argPackAdvance:8,readValueFromPointer:pb,T:null})},h:function(a,b,c){c=Na(c);b=P(b);T(a,{name:b,fromWireType:function(d){return d},toWireType:function(d,f){if("number"!==typeof f&&"boolean"!==typeof f)throw new TypeError('Cannot convert "'+V(f)+'" to '+this.name);return f},argPackAdvance:8,readValueFromPointer:Db(b,c),T:null})},d:function(a,b,c,d,f,g){var q=Fb(b,c);a=P(a);f=X(d,f);hb(a,function(){yb("Cannot call "+a+" due to unbound types",
q)},b-1);Wa([],q,function(h){var l=[h[0],null].concat(h.slice(1)),m=h=a,k=f,p=l.length;2>p&&S("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var t=null!==l[1]&&!1,v=!1,n=1;n<l.length;++n)if(null!==l[n]&&void 0===l[n].T){v=!0;break}var u="void"!==l[0].name,x="",y="";for(n=0;n<p-2;++n)x+=(0!==n?", ":"")+"arg"+n,y+=(0!==n?", ":"")+"arg"+n+"Wired";m="return function "+Qa(m)+"("+x+") {\nif (arguments.length !== "+(p-2)+") {\nthrowBindingError('function "+m+" called with ' + arguments.length + ' arguments, expected "+
(p-2)+" args!');\n}\n";v&&(m+="var destructors = [];\n");var C=v?"destructors":"null";x="throwBindingError invoker fn runDestructors retType classParam".split(" ");k=[S,k,g,zb,l[0],l[1]];t&&(m+="var thisWired = classParam.toWireType("+C+", this);\n");for(n=0;n<p-2;++n)m+="var arg"+n+"Wired = argType"+n+".toWireType("+C+", arg"+n+"); // "+l[n+2].name+"\n",x.push("argType"+n),k.push(l[n+2]);t&&(y="thisWired"+(0<y.length?", ":"")+y);m+=(u?"var rv = ":"")+"invoker(fn"+(0<y.length?", ":"")+y+");\n";if(v)m+=
"runDestructors(destructors);\n";else for(n=t?1:2;n<l.length;++n)p=1===n?"thisWired":"arg"+(n-2)+"Wired",null!==l[n].T&&(m+=p+"_dtor("+p+"); // "+l[n].name+"\n",x.push(p+"_dtor"),k.push(l[n].T));u&&(m+="var ret = retType.fromWireType(rv);\nreturn ret;\n");x.push(m+"}\n");l=Eb(x).apply(null,k);ub(h,l,b-1);return[]})},b:function(a,b,c,d,f){function g(m){return m}b=P(b);-1===f&&(f=4294967295);var q=Na(c);if(0===d){var h=32-8*c;g=function(m){return m<<h>>>h}}var l=-1!=b.indexOf("unsigned");T(a,{name:b,
fromWireType:g,toWireType:function(m,k){if("number"!==typeof k&&"boolean"!==typeof k)throw new TypeError('Cannot convert "'+V(k)+'" to '+this.name);if(k<d||k>f)throw new TypeError('Passing a number "'+V(k)+'" from JS side to C/C++ side to an argument of type "'+b+'", which is outside the valid range ['+d+", "+f+"]!");return l?k>>>0:k|0},argPackAdvance:8,readValueFromPointer:Gb(b,q,0!==d),T:null})},a:function(a,b,c){function d(g){g>>=2;var q=L;return new f(K,q[g+1],q[g])}var f=[Int8Array,Uint8Array,
Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=P(c);T(a,{name:c,fromWireType:d,argPackAdvance:8,readValueFromPointer:d},{na:!0})},i:function(a,b){b=P(b);var c="std::string"===b;T(a,{name:b,fromWireType:function(d){var f=L[d>>2];if(c){var g=H[d+4+f],q=0;0!=g&&(q=g,H[d+4+f]=0);var h=d+4;for(g=0;g<=f;++g){var l=d+4+g;if(0==H[l]){if(h){for(var m=H,k=h+NaN,p=h;m[p]&&!(p>=k);)++p;if(16<p-h&&m.subarray&&la)h=la.decode(m.subarray(h,p));else{for(k="";h<p;){var t=m[h++];if(t&
128){var v=m[h++]&63;if(192==(t&224))k+=String.fromCharCode((t&31)<<6|v);else{var n=m[h++]&63;t=224==(t&240)?(t&15)<<12|v<<6|n:(t&7)<<18|v<<12|n<<6|m[h++]&63;65536>t?k+=String.fromCharCode(t):(t-=65536,k+=String.fromCharCode(55296|t>>10,56320|t&1023))}}else k+=String.fromCharCode(t)}h=k}}else h="";if(void 0===u)var u=h;else u+=String.fromCharCode(0),u+=h;h=l+1}}0!=q&&(H[d+4+f]=q)}else{u=Array(f);for(g=0;g<f;++g)u[g]=String.fromCharCode(H[d+4+g]);u=u.join("")}Y(d);return u},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||S("Cannot pass non-string to std::string");var q=(c&&g?function(){for(var m=0,k=0;k<f.length;++k){var p=f.charCodeAt(k);55296<=p&&57343>=p&&(p=65536+((p&1023)<<10)|f.charCodeAt(++k)&1023);127>=p?++m:m=2047>=p?m+2:65535>=p?m+3:m+4}return m}:function(){return f.length})(),h=Jb(4+q+1);L[h>>2]=q;if(c&&g)ma(f,h+4,q+1);else if(g)for(g=0;g<q;++g){var l=f.charCodeAt(g);
255<l&&(Y(h),S("String has UTF-16 code units that do not fit in 8 bits"));H[h+4+g]=l}else for(g=0;g<q;++g)H[h+4+g]=f[g];null!==d&&d.push(Y,h);return h},argPackAdvance:8,readValueFromPointer:pb,T:function(d){Y(d)}})},f:function(a,b,c){c=P(c);if(2===b){var d=oa;var f=pa;var g=qa;var q=function(){return va};var h=1}else 4===b&&(d=ra,f=sa,g=ta,q=function(){return L},h=2);T(a,{name:c,fromWireType:function(l){var m=L[l>>2],k=q(),p=k[l+4+m*b>>h],t=0;0!=p&&(t=p,k[l+4+m*b>>h]=0);var v=l+4;for(p=0;p<=m;++p){var n=
l+4+p*b;if(0==k[n>>h]){v=d(v);if(void 0===u)var u=v;else u+=String.fromCharCode(0),u+=v;v=n+b}}0!=t&&(k[l+4+m*b>>h]=t);Y(l);return u},toWireType:function(l,m){"string"!==typeof m&&S("Cannot pass non-string to C++ string type "+c);var k=g(m),p=Jb(4+k+b);L[p>>2]=k>>h;f(m,p+4,k+b);null!==l&&l.push(Y,p);return p},argPackAdvance:8,readValueFromPointer:pb,T:function(l){Y(l)}})},l:function(a,b){b=P(b);T(a,{sa:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},g:Cb,r:function(a){4<
a&&(Z[a].ea+=1)},j:function(a,b){var c=R[a];void 0===c&&S("_emval_take_value has unknown type "+wb(a));a=c.readValueFromPointer(b);return mb(a)},p:function(a,b,c){H.copyWithin(a,b,b+c)},c:function(a){var b=H.length;if(2147418112<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{G.grow(Math.min(2147418112,d)-K.byteLength+65535>>16);ya(G.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},memory:G,
table:ja},Lb=function(){function a(f){e.asm=f.exports;M--;e.monitorRunDependencies&&e.monitorRunDependencies(M);0==M&&(null!==Ga&&(clearInterval(Ga),Ga=null),N&&(f=N,N=null,f()))}function b(f){a(f.instance)}function c(f){return Ka().then(function(g){return WebAssembly.instantiate(g,d)}).then(f,function(g){E("failed to asynchronously prepare wasm: "+g);D(g)})}var d={a:Kb};M++;e.monitorRunDependencies&&e.monitorRunDependencies(M);if(e.instantiateWasm)try{return e.instantiateWasm(d,a)}catch(f){return E("Module.instantiateWasm callback failed with error: "+
f),!1}(function(){if(F||"function"!==typeof WebAssembly.instantiateStreaming||Ha()||"function"!==typeof fetch)return c(b);fetch(O,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,d).then(b,function(g){E("wasm streaming compile failed: "+g);E("falling back to ArrayBuffer instantiation");c(b)})})})();return{}}();e.asm=Lb;
var La=e.___wasm_call_ctors=function(){return(La=e.___wasm_call_ctors=e.asm.s).apply(null,arguments)},Y=e._free=function(){return(Y=e._free=e.asm.t).apply(null,arguments)},Jb=e._malloc=function(){return(Jb=e._malloc=e.asm.u).apply(null,arguments)},xb=e.___getTypeName=function(){return(xb=e.___getTypeName=e.asm.v).apply(null,arguments)};e.___embind_register_native_and_builtin_types=function(){return(e.___embind_register_native_and_builtin_types=e.asm.w).apply(null,arguments)};
e.dynCall_ii=function(){return(e.dynCall_ii=e.asm.x).apply(null,arguments)};e.dynCall_vi=function(){return(e.dynCall_vi=e.asm.y).apply(null,arguments)};e.dynCall_iii=function(){return(e.dynCall_iii=e.asm.z).apply(null,arguments)};e.dynCall_viii=function(){return(e.dynCall_viii=e.asm.A).apply(null,arguments)};e.dynCall_vii=function(){return(e.dynCall_vii=e.asm.B).apply(null,arguments)};e.dynCall_i=function(){return(e.dynCall_i=e.asm.C).apply(null,arguments)};
e.dynCall_v=function(){return(e.dynCall_v=e.asm.D).apply(null,arguments)};e.dynCall_iiii=function(){return(e.dynCall_iiii=e.asm.E).apply(null,arguments)};e.dynCall_iiiiiii=function(){return(e.dynCall_iiiiiii=e.asm.F).apply(null,arguments)};e.dynCall_viiii=function(){return(e.dynCall_viiii=e.asm.G).apply(null,arguments)};e.dynCall_viiiii=function(){return(e.dynCall_viiiii=e.asm.H).apply(null,arguments)};e.dynCall_viiiiiiiii=function(){return(e.dynCall_viiiiiiiii=e.asm.I).apply(null,arguments)};
e.dynCall_viiiiii=function(){return(e.dynCall_viiiiii=e.asm.J).apply(null,arguments)};e.asm=Lb;var Mb;e.then=function(a){if(Mb)a(e);else{var b=e.onRuntimeInitialized;e.onRuntimeInitialized=function(){b&&b();a(e)}}return e};N=function Nb(){Mb||Ob();Mb||(N=Nb)};
function Ob(){function a(){if(!Mb&&(Mb=!0,e.calledRun=!0,!ka)){Aa(Ca);Aa(Da);if(e.onRuntimeInitialized)e.onRuntimeInitialized();if(e.postRun)for("function"==typeof e.postRun&&(e.postRun=[e.postRun]);e.postRun.length;){var b=e.postRun.shift();Ea.unshift(b)}Aa(Ea)}}if(!(0<M)){if(e.preRun)for("function"==typeof e.preRun&&(e.preRun=[e.preRun]);e.preRun.length;)Fa();Aa(Ba);0<M||(e.setStatus?(e.setStatus("Running..."),setTimeout(function(){setTimeout(function(){e.setStatus("")},1);a()},1)):a())}}
e.run=Ob;if(e.preInit)for("function"==typeof e.preInit&&(e.preInit=[e.preInit]);0<e.preInit.length;)e.preInit.pop()();noExitRuntime=!0;Ob();
return webp_dec
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = webp_dec;
else if (typeof define === 'function' && define['amd'])
define([], function() { return webp_dec; });
else if (typeof exports === 'object')
exports["webp_dec"] = webp_dec;

Binary file not shown.

View File

@ -19,7 +19,7 @@
module.onRuntimeInitialized = async _ => {
console.log('Version:', module.version().toString(16));
const image = await loadImage('../example.png');
const image = await loadImage('../../example.png');
const result = module.encode(image.data, image.width, image.height, {
quality: 75,
target_size: 0,

View File

@ -0,0 +1,93 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
#include "src/webp/encode.h"
using namespace emscripten;
int version() {
return WebPGetEncoderVersion();
}
uint8_t* last_result;
val encode(std::string img, int width, int height, WebPConfig config) {
uint8_t* img_in = (uint8_t*)img.c_str();
// A lot of this is duplicated from Encode in picture_enc.c
WebPPicture pic;
WebPMemoryWriter wrt;
int ok;
if (!WebPPictureInit(&pic)) {
// shouldn't happen, except if system installation is broken
throw std::runtime_error("Unexpected error");
}
// Only use use_argb if we really need it, as it's slower.
pic.use_argb = config.lossless || config.use_sharp_yuv || config.preprocessing > 0;
pic.width = width;
pic.height = height;
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &wrt;
WebPMemoryWriterInit(&wrt);
ok = WebPPictureImportRGBA(&pic, (uint8_t*)img_in, width * 4) && WebPEncode(&config, &pic);
WebPPictureFree(&pic);
if (!ok) {
WebPMemoryWriterClear(&wrt);
throw std::runtime_error("Encode failed");
}
last_result = wrt.mem;
return val(typed_memory_view(wrt.size, wrt.mem));
}
void free_result() {
WebPFree(last_result);
}
EMSCRIPTEN_BINDINGS(my_module) {
enum_<WebPImageHint>("WebPImageHint")
.value("WEBP_HINT_DEFAULT", WebPImageHint::WEBP_HINT_DEFAULT)
.value("WEBP_HINT_PICTURE", WebPImageHint::WEBP_HINT_PICTURE)
.value("WEBP_HINT_PHOTO", WebPImageHint::WEBP_HINT_PHOTO)
.value("WEBP_HINT_GRAPH", WebPImageHint::WEBP_HINT_GRAPH);
value_object<WebPConfig>("WebPConfig")
.field("lossless", &WebPConfig::lossless)
.field("quality", &WebPConfig::quality)
.field("method", &WebPConfig::method)
.field("image_hint", &WebPConfig::image_hint)
.field("target_size", &WebPConfig::target_size)
.field("target_PSNR", &WebPConfig::target_PSNR)
.field("segments", &WebPConfig::segments)
.field("sns_strength", &WebPConfig::sns_strength)
.field("filter_strength", &WebPConfig::filter_strength)
.field("filter_sharpness", &WebPConfig::filter_sharpness)
.field("filter_type", &WebPConfig::filter_type)
.field("autofilter", &WebPConfig::autofilter)
.field("alpha_compression", &WebPConfig::alpha_compression)
.field("alpha_filtering", &WebPConfig::alpha_filtering)
.field("alpha_quality", &WebPConfig::alpha_quality)
.field("pass", &WebPConfig::pass)
.field("show_compressed", &WebPConfig::show_compressed)
.field("preprocessing", &WebPConfig::preprocessing)
.field("partitions", &WebPConfig::partitions)
.field("partition_limit", &WebPConfig::partition_limit)
.field("emulate_jpeg_size", &WebPConfig::emulate_jpeg_size)
.field("thread_level", &WebPConfig::thread_level)
.field("low_memory", &WebPConfig::low_memory)
.field("near_lossless", &WebPConfig::near_lossless)
.field("exact", &WebPConfig::exact)
.field("use_delta_palette", &WebPConfig::use_delta_palette)
.field("use_sharp_yuv", &WebPConfig::use_sharp_yuv);
function("version", &version);
function("encode", &encode);
function("free_result", &free_result);
}

View File

@ -0,0 +1,70 @@
var webp_enc = (function() {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
return (
function(webp_enc) {
webp_enc = webp_enc || {};
var d;d||(d=typeof webp_enc !== 'undefined' ? webp_enc : {});var u={},w;for(w in d)d.hasOwnProperty(w)&&(u[w]=d[w]);var x=!1,y=!1,aa=!1,ba=!1;x="object"===typeof window;y="function"===typeof importScripts;aa="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node;ba=!x&&!aa&&!y;var z="",B,C,ca,da;
if(aa)z=y?require("path").dirname(z)+"/":__dirname+"/",B=function(a,b){ca||(ca=require("fs"));da||(da=require("path"));a=da.normalize(a);return ca.readFileSync(a,b?null:"utf8")},C=function(a){a=B(a,!0);a.buffer||(a=new Uint8Array(a));a.buffer||D("Assertion failed: undefined");return a},1<process.argv.length&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),process.on("uncaughtException",function(a){throw a;}),process.on("unhandledRejection",D),d.inspect=function(){return"[Emscripten Module object]"};
else if(ba)"undefined"!=typeof read&&(B=function(a){return read(a)}),C=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");"object"===typeof a||D("Assertion failed: undefined");return a},"undefined"!==typeof print&&("undefined"===typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!==typeof printErr?printErr:print);else if(x||y)y?z=self.location.href:document.currentScript&&(z=document.currentScript.src),_scriptDir&&
(z=_scriptDir),0!==z.indexOf("blob:")?z=z.substr(0,z.lastIndexOf("/")+1):z="",B=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},y&&(C=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)});var ea=d.print||console.log.bind(console),E=d.printErr||console.warn.bind(console);for(w in u)u.hasOwnProperty(w)&&(d[w]=u[w]);u=null;var F;d.wasmBinary&&(F=d.wasmBinary);var noExitRuntime;
d.noExitRuntime&&(noExitRuntime=d.noExitRuntime);"object"!==typeof WebAssembly&&E("no native wasm support detected");var G,fa=new WebAssembly.Table({initial:129,maximum:129,element:"anyfunc"}),ha=!1,ia="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;
function ja(a,b,c){var e=I;if(0<c){c=b+c-1;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var n=a.charCodeAt(++f);g=65536+((g&1023)<<10)|n&1023}if(127>=g){if(b>=c)break;e[b++]=g}else{if(2047>=g){if(b+1>=c)break;e[b++]=192|g>>6}else{if(65535>=g){if(b+2>=c)break;e[b++]=224|g>>12}else{if(b+3>=c)break;e[b++]=240|g>>18;e[b++]=128|g>>12&63}e[b++]=128|g>>6&63}e[b++]=128|g&63}}e[b]=0}}var ka="undefined"!==typeof TextDecoder?new TextDecoder("utf-16le"):void 0;
function la(a){var b;for(b=a>>1;J[b];)++b;b<<=1;if(32<b-a&&ka)return ka.decode(I.subarray(a,b));b=0;for(var c="";;){var e=J[a+2*b>>1];if(0==e)return c;++b;c+=String.fromCharCode(e)}}function ma(a,b,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var e=b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f)J[b>>1]=a.charCodeAt(f),b+=2;J[b>>1]=0;return b-e}function na(a){return 2*a.length}
function oa(a){for(var b=0,c="";;){var e=K[a+4*b>>2];if(0==e)return c;++b;65536<=e?(e-=65536,c+=String.fromCharCode(55296|e>>10,56320|e&1023)):c+=String.fromCharCode(e)}}function pa(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var e=b;c=e+c-4;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var n=a.charCodeAt(++f);g=65536+((g&1023)<<10)|n&1023}K[b>>2]=g;b+=4;if(b+4>c)break}K[b>>2]=0;return b-e}
function qa(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&++c;b+=4}return b}var L,ra,I,J,sa,K,M,ta,ua;function va(a){L=a;d.HEAP8=ra=new Int8Array(a);d.HEAP16=J=new Int16Array(a);d.HEAP32=K=new Int32Array(a);d.HEAPU8=I=new Uint8Array(a);d.HEAPU16=sa=new Uint16Array(a);d.HEAPU32=M=new Uint32Array(a);d.HEAPF32=ta=new Float32Array(a);d.HEAPF64=ua=new Float64Array(a)}var wa=d.INITIAL_MEMORY||16777216;d.wasmMemory?G=d.wasmMemory:G=new WebAssembly.Memory({initial:wa/65536});
G&&(L=G.buffer);wa=L.byteLength;va(L);K[8664]=5277696;function xa(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b();else{var c=b.X;"number"===typeof c?void 0===b.R?d.dynCall_v(c):d.dynCall_vi(c,b.R):c(void 0===b.R?null:b.R)}}}var ya=[],za=[],Aa=[],Ba=[];function Ca(){var a=d.preRun.shift();ya.unshift(a)}var N=0,Da=null,O=null;d.preloadedImages={};d.preloadedAudios={};
function D(a){if(d.onAbort)d.onAbort(a);ea(a);E(a);ha=!0;throw new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");}function Ea(){var a=P;return String.prototype.startsWith?a.startsWith("data:application/octet-stream;base64,"):0===a.indexOf("data:application/octet-stream;base64,")}var P="webp_enc.wasm";if(!Ea()){var Fa=P;P=d.locateFile?d.locateFile(Fa,z):z+Fa}
function Ga(){try{if(F)return new Uint8Array(F);if(C)return C(P);throw"both async and sync fetching of the wasm failed";}catch(a){D(a)}}function Ha(){return F||!x&&!y||"function"!==typeof fetch?new Promise(function(a){a(Ga())}):fetch(P,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+P+"'";return a.arrayBuffer()}).catch(function(){return Ga()})}za.push({X:function(){Ia()}});function Ja(){return 0<Ja.T}var Ka={};
function La(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function Ma(a){return this.fromWireType(M[a>>2])}var Q={},R={},Na={};function Oa(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 Pa(a,b){a=Oa(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}
function Qa(a){var b=Error,c=Pa(a,function(e){this.name=a;this.message=e;e=Error(e).stack;void 0!==e&&(this.stack=this.toString()+"\n"+e.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 Ra=void 0;
function Sa(a,b,c){function e(h){h=c(h);if(h.length!==a.length)throw new Ra("Mismatched type converter count");for(var k=0;k<a.length;++k)S(a[k],h[k])}a.forEach(function(h){Na[h]=b});var f=Array(b.length),g=[],n=0;b.forEach(function(h,k){R.hasOwnProperty(h)?f[k]=R[h]:(g.push(h),Q.hasOwnProperty(h)||(Q[h]=[]),Q[h].push(function(){f[k]=R[h];++n;n===g.length&&e(f)}))});0===g.length&&e(f)}
function Ta(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 Ua=void 0;function T(a){for(var b="";I[a];)b+=Ua[I[a++]];return b}var Va=void 0;function U(a){throw new Va(a);}
function S(a,b,c){c=c||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var e=b.name;a||U('type "'+e+'" must have a positive integer typeid pointer');if(R.hasOwnProperty(a)){if(c.aa)return;U("Cannot register type '"+e+"' twice")}R[a]=b;delete Na[a];Q.hasOwnProperty(a)&&(b=Q[a],delete Q[a],b.forEach(function(f){f()}))}var Wa=[],V=[{},{value:void 0},{value:null},{value:!0},{value:!1}];
function Xa(a){4<a&&0===--V[a].S&&(V[a]=void 0,Wa.push(a))}function Ya(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=Wa.length?Wa.pop():V.length;V[b]={S:1,value:a};return b}}
function Za(a,b){var c=d;if(void 0===c[a].P){var e=c[a];c[a]=function(){c[a].P.hasOwnProperty(arguments.length)||U("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+c[a].P+")!");return c[a].P[arguments.length].apply(this,arguments)};c[a].P=[];c[a].P[e.V]=e}}
function $a(a,b,c){d.hasOwnProperty(a)?((void 0===c||void 0!==d[a].P&&void 0!==d[a].P[c])&&U("Cannot register public name '"+a+"' twice"),Za(a,a),d.hasOwnProperty(c)&&U("Cannot register multiple overloads of a function with the same number of arguments ("+c+")!"),d[a].P[c]=b):(d[a]=b,void 0!==c&&(d[a].ia=c))}
function ab(a,b,c){switch(b){case 0:return function(e){return this.fromWireType((c?ra:I)[e])};case 1:return function(e){return this.fromWireType((c?J:sa)[e>>1])};case 2:return function(e){return this.fromWireType((c?K:M)[e>>2])};default:throw new TypeError("Unknown integer type: "+a);}}function bb(a){a=cb(a);var b=T(a);X(a);return b}function db(a,b){var c=R[a];void 0===c&&U(b+" has unknown type "+bb(a));return c}
function eb(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}function fb(a,b){switch(b){case 2:return function(c){return this.fromWireType(ta[c>>2])};case 3:return function(c){return this.fromWireType(ua[c>>3])};default:throw new TypeError("Unknown float type: "+a);}}
function gb(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=Pa(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c}function hb(a,b){for(var c=[],e=0;e<a;e++)c.push(K[(b>>2)+e]);return c}
function Y(a,b){a=T(a);var c=d["dynCall_"+a];for(var e=[],f=1;f<a.length;++f)e.push("a"+f);f="return function dynCall_"+(a+"_"+b)+"("+e.join(", ")+") {\n";f+=" return dynCall(rawFunction"+(e.length?", ":"")+e.join(", ")+");\n";c=(new Function("dynCall","rawFunction",f+"};\n"))(c,b);"function"!==typeof c&&U("unknown function pointer with signature "+a+": "+b);return c}var ib=void 0;
function jb(a,b){function c(g){f[g]||R[g]||(Na[g]?Na[g].forEach(c):(e.push(g),f[g]=!0))}var e=[],f={};b.forEach(c);throw new ib(a+": "+e.map(bb).join([", "]));}function kb(a,b,c){switch(b){case 0:return c?function(e){return ra[e]}:function(e){return I[e]};case 1:return c?function(e){return J[e>>1]}:function(e){return sa[e>>1]};case 2:return c?function(e){return K[e>>2]}:function(e){return M[e>>2]};default:throw new TypeError("Unknown integer type: "+a);}}Ra=d.InternalError=Qa("InternalError");
for(var lb=Array(256),mb=0;256>mb;++mb)lb[mb]=String.fromCharCode(mb);Ua=lb;Va=d.BindingError=Qa("BindingError");d.count_emval_handles=function(){for(var a=0,b=5;b<V.length;++b)void 0!==V[b]&&++a;return a};d.get_first_emval=function(){for(var a=5;a<V.length;++a)if(void 0!==V[a])return V[a];return null};ib=d.UnboundTypeError=Qa("UnboundTypeError");
var ob={j:function(a){return nb(a)},i:function(a){"uncaught_exception"in Ja?Ja.T++:Ja.T=1;throw a;},l:function(a){var b=Ka[a];delete Ka[a];var c=b.ba,e=b.da,f=b.U,g=f.map(function(n){return n.$}).concat(f.map(function(n){return n.fa}));Sa([a],g,function(n){var h={};f.forEach(function(k,l){var m=n[l],p=k.Y,r=k.Z,v=n[l+f.length],q=k.ea,t=k.ga;h[k.W]={read:function(A){return m.fromWireType(p(r,A))},write:function(A,H){var W=[];q(t,A,v.toWireType(W,H));La(W)}}});return[{name:b.name,fromWireType:function(k){var l=
{},m;for(m in h)l[m]=h[m].read(k);e(k);return l},toWireType:function(k,l){for(var m in h)if(!(m in l))throw new TypeError("Missing field");var p=c();for(m in h)h[m].write(p,l[m]);null!==k&&k.push(e,p);return p},argPackAdvance:8,readValueFromPointer:Ma,O:e}]})},s:function(a,b,c,e,f){var g=Ta(c);b=T(b);S(a,{name:b,fromWireType:function(n){return!!n},toWireType:function(n,h){return h?e:f},argPackAdvance:8,readValueFromPointer:function(n){if(1===c)var h=ra;else if(2===c)h=J;else if(4===c)h=K;else throw new TypeError("Unknown boolean type size: "+
b);return this.fromWireType(h[n>>g])},O:null})},r:function(a,b){b=T(b);S(a,{name:b,fromWireType:function(c){var e=V[c].value;Xa(c);return e},toWireType:function(c,e){return Ya(e)},argPackAdvance:8,readValueFromPointer:Ma,O:null})},o:function(a,b,c,e){function f(){}c=Ta(c);b=T(b);f.values={};S(a,{name:b,constructor:f,fromWireType:function(g){return this.constructor.values[g]},toWireType:function(g,n){return n.value},argPackAdvance:8,readValueFromPointer:ab(b,c,e),O:null});$a(b,f)},n:function(a,b,c){var e=
db(a,"enum");b=T(b);a=e.constructor;e=Object.create(e.constructor.prototype,{value:{value:c},constructor:{value:Pa(e.name+"_"+b,function(){})}});a.values[c]=e;a[b]=e},g:function(a,b,c){c=Ta(c);b=T(b);S(a,{name:b,fromWireType:function(e){return e},toWireType:function(e,f){if("number"!==typeof f&&"boolean"!==typeof f)throw new TypeError('Cannot convert "'+eb(f)+'" to '+this.name);return f},argPackAdvance:8,readValueFromPointer:fb(b,c),O:null})},d:function(a,b,c,e,f,g){var n=hb(b,c);a=T(a);f=Y(e,f);
$a(a,function(){jb("Cannot call "+a+" due to unbound types",n)},b-1);Sa([],n,function(h){var k=[h[0],null].concat(h.slice(1)),l=h=a,m=f,p=k.length;2>p&&U("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var r=null!==k[1]&&!1,v=!1,q=1;q<k.length;++q)if(null!==k[q]&&void 0===k[q].O){v=!0;break}var t="void"!==k[0].name,A="",H="";for(q=0;q<p-2;++q)A+=(0!==q?", ":"")+"arg"+q,H+=(0!==q?", ":"")+"arg"+q+"Wired";l="return function "+Oa(l)+"("+A+") {\nif (arguments.length !== "+
(p-2)+") {\nthrowBindingError('function "+l+" called with ' + arguments.length + ' arguments, expected "+(p-2)+" args!');\n}\n";v&&(l+="var destructors = [];\n");var W=v?"destructors":"null";A="throwBindingError invoker fn runDestructors retType classParam".split(" ");m=[U,m,g,La,k[0],k[1]];r&&(l+="var thisWired = classParam.toWireType("+W+", this);\n");for(q=0;q<p-2;++q)l+="var arg"+q+"Wired = argType"+q+".toWireType("+W+", arg"+q+"); // "+k[q+2].name+"\n",A.push("argType"+q),m.push(k[q+2]);r&&(H=
"thisWired"+(0<H.length?", ":"")+H);l+=(t?"var rv = ":"")+"invoker(fn"+(0<H.length?", ":"")+H+");\n";if(v)l+="runDestructors(destructors);\n";else for(q=r?1:2;q<k.length;++q)p=1===q?"thisWired":"arg"+(q-2)+"Wired",null!==k[q].O&&(l+=p+"_dtor("+p+"); // "+k[q].name+"\n",A.push(p+"_dtor"),m.push(k[q].O));t&&(l+="var ret = retType.fromWireType(rv);\nreturn ret;\n");A.push(l+"}\n");k=gb(A).apply(null,m);q=b-1;if(!d.hasOwnProperty(h))throw new Ra("Replacing nonexistant public symbol");void 0!==d[h].P&&
void 0!==q?d[h].P[q]=k:(d[h]=k,d[h].V=q);return[]})},b:function(a,b,c,e,f){function g(l){return l}b=T(b);-1===f&&(f=4294967295);var n=Ta(c);if(0===e){var h=32-8*c;g=function(l){return l<<h>>>h}}var k=-1!=b.indexOf("unsigned");S(a,{name:b,fromWireType:g,toWireType:function(l,m){if("number"!==typeof m&&"boolean"!==typeof m)throw new TypeError('Cannot convert "'+eb(m)+'" to '+this.name);if(m<e||m>f)throw new TypeError('Passing a number "'+eb(m)+'" from JS side to C/C++ side to an argument of type "'+
b+'", which is outside the valid range ['+e+", "+f+"]!");return k?m>>>0:m|0},argPackAdvance:8,readValueFromPointer:kb(b,n,0!==e),O:null})},a:function(a,b,c){function e(g){g>>=2;var n=M;return new f(L,n[g+1],n[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=T(c);S(a,{name:c,fromWireType:e,argPackAdvance:8,readValueFromPointer:e},{aa:!0})},h:function(a,b){b=T(b);var c="std::string"===b;S(a,{name:b,fromWireType:function(e){var f=M[e>>2];if(c){var g=
I[e+4+f],n=0;0!=g&&(n=g,I[e+4+f]=0);var h=e+4;for(g=0;g<=f;++g){var k=e+4+g;if(0==I[k]){if(h){for(var l=I,m=h+NaN,p=h;l[p]&&!(p>=m);)++p;if(16<p-h&&l.subarray&&ia)h=ia.decode(l.subarray(h,p));else{for(m="";h<p;){var r=l[h++];if(r&128){var v=l[h++]&63;if(192==(r&224))m+=String.fromCharCode((r&31)<<6|v);else{var q=l[h++]&63;r=224==(r&240)?(r&15)<<12|v<<6|q:(r&7)<<18|v<<12|q<<6|l[h++]&63;65536>r?m+=String.fromCharCode(r):(r-=65536,m+=String.fromCharCode(55296|r>>10,56320|r&1023))}}else m+=String.fromCharCode(r)}h=
m}}else h="";if(void 0===t)var t=h;else t+=String.fromCharCode(0),t+=h;h=k+1}}0!=n&&(I[e+4+f]=n)}else{t=Array(f);for(g=0;g<f;++g)t[g]=String.fromCharCode(I[e+4+g]);t=t.join("")}X(e);return t},toWireType:function(e,f){f instanceof ArrayBuffer&&(f=new Uint8Array(f));var g="string"===typeof f;g||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array||U("Cannot pass non-string to std::string");var n=(c&&g?function(){for(var l=0,m=0;m<f.length;++m){var p=f.charCodeAt(m);55296<=
p&&57343>=p&&(p=65536+((p&1023)<<10)|f.charCodeAt(++m)&1023);127>=p?++l:l=2047>=p?l+2:65535>=p?l+3:l+4}return l}:function(){return f.length})(),h=nb(4+n+1);M[h>>2]=n;if(c&&g)ja(f,h+4,n+1);else if(g)for(g=0;g<n;++g){var k=f.charCodeAt(g);255<k&&(X(h),U("String has UTF-16 code units that do not fit in 8 bits"));I[h+4+g]=k}else for(g=0;g<n;++g)I[h+4+g]=f[g];null!==e&&e.push(X,h);return h},argPackAdvance:8,readValueFromPointer:Ma,O:function(e){X(e)}})},f:function(a,b,c){c=T(c);if(2===b){var e=la;var f=
ma;var g=na;var n=function(){return sa};var h=1}else 4===b&&(e=oa,f=pa,g=qa,n=function(){return M},h=2);S(a,{name:c,fromWireType:function(k){var l=M[k>>2],m=n(),p=m[k+4+l*b>>h],r=0;0!=p&&(r=p,m[k+4+l*b>>h]=0);var v=k+4;for(p=0;p<=l;++p){var q=k+4+p*b;if(0==m[q>>h]){v=e(v);if(void 0===t)var t=v;else t+=String.fromCharCode(0),t+=v;v=q+b}}0!=r&&(m[k+4+l*b>>h]=r);X(k);return t},toWireType:function(k,l){"string"!==typeof l&&U("Cannot pass non-string to C++ string type "+c);var m=g(l),p=nb(4+m+b);M[p>>
2]=m>>h;f(l,p+4,m+b);null!==k&&k.push(X,p);return p},argPackAdvance:8,readValueFromPointer:Ma,O:function(k){X(k)}})},m:function(a,b,c,e,f,g){Ka[a]={name:T(b),ba:Y(c,e),da:Y(f,g),U:[]}},e:function(a,b,c,e,f,g,n,h,k,l){Ka[a].U.push({W:T(b),$:c,Y:Y(e,f),Z:g,fa:n,ea:Y(h,k),ga:l})},t:function(a,b){b=T(b);S(a,{ha:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},u:Xa,k:function(a){4<a&&(V[a].S+=1)},q:function(a,b){a=db(a,"_emval_take_value");a=a.readValueFromPointer(b);return Ya(a)},
p:function(a,b,c){I.copyWithin(a,b,b+c)},c:function(a){var b=I.length;if(2147418112<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);e=Math.max(16777216,a,e);0<e%65536&&(e+=65536-e%65536);a:{try{G.grow(Math.min(2147418112,e)-L.byteLength+65535>>16);va(G.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},memory:G,table:fa},pb=function(){function a(f){d.asm=f.exports;N--;d.monitorRunDependencies&&d.monitorRunDependencies(N);0==N&&(null!==Da&&(clearInterval(Da),
Da=null),O&&(f=O,O=null,f()))}function b(f){a(f.instance)}function c(f){return Ha().then(function(g){return WebAssembly.instantiate(g,e)}).then(f,function(g){E("failed to asynchronously prepare wasm: "+g);D(g)})}var e={a:ob};N++;d.monitorRunDependencies&&d.monitorRunDependencies(N);if(d.instantiateWasm)try{return d.instantiateWasm(e,a)}catch(f){return E("Module.instantiateWasm callback failed with error: "+f),!1}(function(){if(F||"function"!==typeof WebAssembly.instantiateStreaming||Ea()||"function"!==
typeof fetch)return c(b);fetch(P,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(g){E("wasm streaming compile failed: "+g);E("falling back to ArrayBuffer instantiation");c(b)})})})();return{}}();d.asm=pb;
var Ia=d.___wasm_call_ctors=function(){return(Ia=d.___wasm_call_ctors=d.asm.v).apply(null,arguments)},nb=d._malloc=function(){return(nb=d._malloc=d.asm.w).apply(null,arguments)},X=d._free=function(){return(X=d._free=d.asm.x).apply(null,arguments)},cb=d.___getTypeName=function(){return(cb=d.___getTypeName=d.asm.y).apply(null,arguments)};d.___embind_register_native_and_builtin_types=function(){return(d.___embind_register_native_and_builtin_types=d.asm.z).apply(null,arguments)};
d.dynCall_i=function(){return(d.dynCall_i=d.asm.A).apply(null,arguments)};d.dynCall_vi=function(){return(d.dynCall_vi=d.asm.B).apply(null,arguments)};d.dynCall_iii=function(){return(d.dynCall_iii=d.asm.C).apply(null,arguments)};d.dynCall_viii=function(){return(d.dynCall_viii=d.asm.D).apply(null,arguments)};d.dynCall_fii=function(){return(d.dynCall_fii=d.asm.E).apply(null,arguments)};d.dynCall_viif=function(){return(d.dynCall_viif=d.asm.F).apply(null,arguments)};
d.dynCall_ii=function(){return(d.dynCall_ii=d.asm.G).apply(null,arguments)};d.dynCall_iiiiii=function(){return(d.dynCall_iiiiii=d.asm.H).apply(null,arguments)};d.dynCall_viiiii=function(){return(d.dynCall_viiiii=d.asm.I).apply(null,arguments)};d.dynCall_v=function(){return(d.dynCall_v=d.asm.J).apply(null,arguments)};d.dynCall_iiii=function(){return(d.dynCall_iiii=d.asm.K).apply(null,arguments)};d.dynCall_viiiiiiiii=function(){return(d.dynCall_viiiiiiiii=d.asm.L).apply(null,arguments)};
d.dynCall_viiii=function(){return(d.dynCall_viiii=d.asm.M).apply(null,arguments)};d.dynCall_viiiiii=function(){return(d.dynCall_viiiiii=d.asm.N).apply(null,arguments)};d.asm=pb;var Z;d.then=function(a){if(Z)a(d);else{var b=d.onRuntimeInitialized;d.onRuntimeInitialized=function(){b&&b();a(d)}}return d};O=function qb(){Z||rb();Z||(O=qb)};
function rb(){function a(){if(!Z&&(Z=!0,d.calledRun=!0,!ha)){xa(za);xa(Aa);if(d.onRuntimeInitialized)d.onRuntimeInitialized();if(d.postRun)for("function"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var b=d.postRun.shift();Ba.unshift(b)}xa(Ba)}}if(!(0<N)){if(d.preRun)for("function"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)Ca();xa(ya);0<N||(d.setStatus?(d.setStatus("Running..."),setTimeout(function(){setTimeout(function(){d.setStatus("")},1);a()},1)):a())}}d.run=rb;
if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.pop()();noExitRuntime=!0;rb();
return webp_enc
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = webp_enc;
else if (typeof define === 'function' && define['amd'])
define([], function() { return webp_enc; });
else if (typeof exports === 'object')
exports["webp_enc"] = webp_enc;

Binary file not shown.

View File

@ -1,5 +1,5 @@
{
"name": "webp_dec",
"name": "webp",
"requires": true,
"lockfileVersion": 1,
"dependencies": {

View File

@ -1,8 +1,8 @@
{
"name": "webp_dec",
"name": "webp",
"scripts": {
"install": "napa",
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten-upstream ./build.sh"
},
"napa": {
"libwebp": "webmproject/libwebp#v1.0.2"

View File

@ -1,60 +0,0 @@
#!/bin/bash
set -e
export OPTIMIZE="-Os"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
apt-get update
apt-get install -qqy autoconf libtool libpng-dev pkg-config
echo "============================================="
echo "Compiling libwebp"
echo "============================================="
test -n "$SKIP_LIBWEBP" || (
cd node_modules/libwebp
autoreconf -fiv
rm -rf build || true
mkdir -p build && cd build
emconfigure ../configure \
--disable-libwebpdemux \
--disable-wic \
--disable-gif \
--disable-tiff \
--disable-jpeg \
--disable-png \
--disable-sdl \
--disable-gl \
--disable-threading \
--disable-neon-rtcd \
--disable-neon \
--disable-sse2 \
--disable-sse4.1
emmake make
)
echo "============================================="
echo "Compiling wasm bindings"
echo "============================================="
(
emcc \
${OPTIMIZE} \
--bind \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="webp_dec"' \
--std=c++11 \
-I node_modules/libwebp \
-o ./webp_dec.js \
-x c++ \
webp_dec.cpp \
node_modules/libwebp/build/src/.libs/libwebp.a
)
echo "============================================="
echo "Compiling wasm bindings done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
{
"name": "webp_enc",
"scripts": {
"install": "napa",
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
},
"napa": {
"libwebp": "webmproject/libwebp#v1.0.2"
},
"devDependencies": {
"napa": "3.0.0"
}
}

View File

@ -1,96 +0,0 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include "src/webp/encode.h"
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
using namespace emscripten;
int version() {
return WebPGetEncoderVersion();
}
uint8_t* last_result;
val encode(std::string img, int width, int height, WebPConfig config) {
uint8_t* img_in = (uint8_t*) img.c_str();
// A lot of this is duplicated from Encode in picture_enc.c
WebPPicture pic;
WebPMemoryWriter wrt;
int ok;
if (!WebPPictureInit(&pic)) {
// shouldn't happen, except if system installation is broken
throw std::runtime_error("Unexpected error");
}
// Only use use_argb if we really need it, as it's slower.
pic.use_argb = config.lossless || config.use_sharp_yuv || config.preprocessing > 0;
pic.width = width;
pic.height = height;
pic.writer = WebPMemoryWrite;
pic.custom_ptr = &wrt;
WebPMemoryWriterInit(&wrt);
ok = WebPPictureImportRGBA(&pic, (uint8_t*) img_in, width * 4) && WebPEncode(&config, &pic);
WebPPictureFree(&pic);
if (!ok) {
WebPMemoryWriterClear(&wrt);
throw std::runtime_error("Encode failed");
}
last_result = wrt.mem;
return val(typed_memory_view(wrt.size, wrt.mem));
}
void free_result() {
WebPFree(last_result);
}
EMSCRIPTEN_BINDINGS(my_module) {
enum_<WebPImageHint>("WebPImageHint")
.value("WEBP_HINT_DEFAULT", WebPImageHint::WEBP_HINT_DEFAULT)
.value("WEBP_HINT_PICTURE", WebPImageHint::WEBP_HINT_PICTURE)
.value("WEBP_HINT_PHOTO", WebPImageHint::WEBP_HINT_PHOTO)
.value("WEBP_HINT_GRAPH", WebPImageHint::WEBP_HINT_GRAPH)
;
value_object<WebPConfig>("WebPConfig")
.field("lossless", &WebPConfig::lossless)
.field("quality", &WebPConfig::quality)
.field("method", &WebPConfig::method)
.field("image_hint", &WebPConfig::image_hint)
.field("target_size", &WebPConfig::target_size)
.field("target_PSNR", &WebPConfig::target_PSNR)
.field("segments", &WebPConfig::segments)
.field("sns_strength", &WebPConfig::sns_strength)
.field("filter_strength", &WebPConfig::filter_strength)
.field("filter_sharpness", &WebPConfig::filter_sharpness)
.field("filter_type", &WebPConfig::filter_type)
.field("autofilter", &WebPConfig::autofilter)
.field("alpha_compression", &WebPConfig::alpha_compression)
.field("alpha_filtering", &WebPConfig::alpha_filtering)
.field("alpha_quality", &WebPConfig::alpha_quality)
.field("pass", &WebPConfig::pass)
.field("show_compressed", &WebPConfig::show_compressed)
.field("preprocessing", &WebPConfig::preprocessing)
.field("partitions", &WebPConfig::partitions)
.field("partition_limit", &WebPConfig::partition_limit)
.field("emulate_jpeg_size", &WebPConfig::emulate_jpeg_size)
.field("thread_level", &WebPConfig::thread_level)
.field("low_memory", &WebPConfig::low_memory)
.field("near_lossless", &WebPConfig::near_lossless)
.field("exact", &WebPConfig::exact)
.field("use_delta_palette", &WebPConfig::use_delta_palette)
.field("use_sharp_yuv", &WebPConfig::use_sharp_yuv)
;
function("version", &version);
function("encode", &encode);
function("free_result", &free_result);
}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,203 +0,0 @@
const path = require('path');
const { URL } = require('url');
const gzipSize = require('gzip-size');
const fetch = require('node-fetch');
const prettyBytes = require('pretty-bytes');
const escapeRE = require('escape-string-regexp');
const readdirp = require('readdirp');
const chalk = new require('chalk').constructor({ level: 4 });
function fetchTravis(path, options = {}) {
const url = new URL(path, 'https://api.travis-ci.org');
url.search = new URLSearchParams(options);
return fetch(url, {
headers: { 'Travis-API-Version': '3' },
});
}
function fetchTravisBuildInfo(user, repo, branch) {
return fetchTravis(`/repo/${encodeURIComponent(`${user}/${repo}`)}/builds`, {
'branch.name': branch,
state: 'passed',
limit: 1,
event_type: 'push',
}).then(r => r.json());
}
function fetchTravisText(path) {
return fetchTravis(path).then(r => r.text());
}
/**
* Recursively-read a directory and turn it into an array of { name, size, gzipSize }
*/
async function dirToInfoArray(startPath) {
const results = await new Promise((resolve, reject) => {
readdirp({ root: startPath }, (err, results) => {
if (err) reject(err); else resolve(results);
});
});
return Promise.all(
results.files.map(async (entry) => ({
name: entry.path,
gzipSize: await gzipSize.file(entry.fullPath),
size: entry.stat.size,
})),
);
}
/**
* Try to treat two entries with different file name hashes as the same file.
*/
function findHashedMatch(name, buildInfo) {
const nameParts = /^(.+\.)[a-f0-9]+(\..+)$/.exec(name);
if (!nameParts) return;
const matchRe = new RegExp(`^${escapeRE(nameParts[1])}[a-f0-9]+${escapeRE(nameParts[2])}$`);
const matchingEntry = buildInfo.find(entry => matchRe.test(entry.name));
return matchingEntry;
}
const buildSizePrefix = '=== BUILD SIZES: ';
const buildSizePrefixRe = new RegExp(`^${escapeRE(buildSizePrefix)}(.+)$`, 'm');
async function getPreviousBuildInfo() {
const buildData = await fetchTravisBuildInfo('GoogleChromeLabs', 'squoosh', 'master');
const jobUrl = buildData.builds[0].jobs[0]['@href'];
const log = await fetchTravisText(jobUrl + '/log.txt');
const reResult = buildSizePrefixRe.exec(log);
if (!reResult) return;
return JSON.parse(reResult[1]);
}
/**
* Generate an array that represents the difference between builds.
* Returns an array of { beforeName, afterName, beforeSize, afterSize }.
* Sizes are gzipped size.
* Before/after properties are missing if resource isn't in the previous/new build.
*/
function getChanges(previousBuildInfo, buildInfo) {
const buildChanges = [];
const alsoInPreviousBuild = new Set();
for (const oldEntry of previousBuildInfo) {
const newEntry = buildInfo.find(entry => entry.name === oldEntry.name) ||
findHashedMatch(oldEntry.name, buildInfo);
// Entry is in previous build, but not the new build.
if (!newEntry) {
buildChanges.push({
beforeName: oldEntry.name,
beforeSize: oldEntry.gzipSize,
});
continue;
}
// Mark this entry so we know we've dealt with it.
alsoInPreviousBuild.add(newEntry);
// If they're the same, just ignore.
// Using size rather than gzip size. I've seen different platforms produce different zipped
// sizes.
if (
oldEntry.size === newEntry.size &&
oldEntry.name === newEntry.name
) continue;
// Entry is in both builds (maybe renamed).
buildChanges.push({
beforeName: oldEntry.name,
afterName: newEntry.name,
beforeSize: oldEntry.gzipSize,
afterSize: newEntry.gzipSize,
});
}
// Look for entries that are only in the new build.
for (const newEntry of buildInfo) {
if (alsoInPreviousBuild.has(newEntry)) continue;
buildChanges.push({
afterName: newEntry.name,
afterSize: newEntry.gzipSize,
});
}
return buildChanges;
}
async function main() {
// Output the current build sizes for later retrieval.
const buildInfo = await dirToInfoArray(__dirname + '/../build');
console.log(buildSizePrefix + JSON.stringify(buildInfo));
console.log('\nBuild change report:');
let previousBuildInfo;
try {
previousBuildInfo = await getPreviousBuildInfo();
} catch (err) {
console.log(` Couldn't parse previous build info`);
return;
}
if (!previousBuildInfo) {
console.log(` Couldn't find previous build info`);
return;
}
const buildChanges = getChanges(previousBuildInfo, buildInfo);
if (buildChanges.length === 0) {
console.log(' No changes');
return;
}
// One letter references, so it's easier to get the spacing right.
const y = chalk.yellow;
const g = chalk.green;
const r = chalk.red;
for (const change of buildChanges) {
// New file.
if (!change.beforeSize) {
console.log(` ${g('ADDED')} ${change.afterName} - ${prettyBytes(change.afterSize)}`);
continue;
}
// Removed file.
if (!change.afterSize) {
console.log(` ${r('REMOVED')} ${change.beforeName} - was ${prettyBytes(change.beforeSize)}`);
continue;
}
// Changed file.
let size;
if (change.beforeSize === change.afterSize) {
// Just renamed.
size = `${prettyBytes(change.afterSize)} -> no change`;
} else {
const color = change.afterSize > change.beforeSize ? r : g;
const sizeDiff = prettyBytes(change.afterSize - change.beforeSize, { signed: true });
const relativeDiff = Math.round((change.afterSize / change.beforeSize) * 1000) / 1000;
size = `${prettyBytes(change.beforeSize)} -> ${prettyBytes(change.afterSize)}` +
' (' +
color(`${sizeDiff}, ${relativeDiff}x`) +
')';
}
console.log(` ${y('CHANGED')} ${change.afterName} - ${size}`);
if (change.beforeName !== change.afterName) {
console.log(` Renamed from: ${change.beforeName}`);
}
}
}
main();

BIN
icon-large-maskable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

11222
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,14 @@
{
"private": true,
"name": "squoosh",
"version": "1.5.0",
"version": "1.11.2",
"license": "apache-2.0",
"scripts": {
"start": "webpack-dev-server --host 0.0.0.0 --hot",
"build": "webpack -p",
"lint": "tslint -c tslint.json -p tsconfig.json -t verbose",
"lintfix": "tslint -c tslint.json -p tsconfig.json -t verbose --fix 'src/**/*.{ts,tsx,js,jsx}'",
"sizereport": "node config/size-report.js"
"sizereport": "sizereport --config"
},
"husky": {
"hooks": {
@ -16,60 +16,61 @@
}
},
"devDependencies": {
"@types/node": "10.12.30",
"@types/node": "10.14.15",
"@types/pretty-bytes": "5.1.0",
"@types/webassembly-js-api": "0.0.2",
"@webcomponents/custom-elements": "1.2.1",
"@webpack-cli/serve": "0.1.3",
"@types/webassembly-js-api": "0.0.3",
"@webcomponents/custom-elements": "1.2.4",
"@webpack-cli/serve": "0.1.8",
"assets-webpack-plugin": "3.9.10",
"chokidar": "2.1.2",
"chalk": "2.4.2",
"chokidar": "3.0.2",
"classnames": "2.2.6",
"clean-webpack-plugin": "1.0.1",
"comlink": "3.1.1",
"copy-webpack-plugin": "5.0.0",
"critters-webpack-plugin": "2.3.0",
"copy-webpack-plugin": "5.0.4",
"critters-webpack-plugin": "2.4.0",
"css-loader": "1.0.1",
"ejs": "2.6.1",
"escape-string-regexp": "1.0.5",
"ejs": "2.6.2",
"escape-string-regexp": "2.0.0",
"exports-loader": "0.7.0",
"file-drop-element": "0.2.0",
"file-loader": "3.0.1",
"gzip-size": "5.0.0",
"file-loader": "4.2.0",
"gzip-size": "5.1.1",
"html-webpack-plugin": "3.2.0",
"husky": "1.3.1",
"idb-keyval": "3.1.0",
"husky": "3.0.4",
"idb-keyval": "3.2.0",
"linkstate": "1.1.1",
"loader-utils": "1.2.3",
"mini-css-extract-plugin": "0.5.0",
"mini-css-extract-plugin": "0.8.0",
"minimatch": "3.0.4",
"node-fetch": "2.3.0",
"node-sass": "4.11.0",
"node-fetch": "2.6.0",
"node-sass": "4.13.0",
"optimize-css-assets-webpack-plugin": "5.0.1",
"pointer-tracker": "2.0.3",
"preact": "8.4.2",
"prerender-loader": "1.3.0",
"pretty-bytes": "5.1.0",
"pretty-bytes": "5.3.0",
"progress-bar-webpack-plugin": "1.12.1",
"raw-loader": "1.0.0",
"readdirp": "2.2.1",
"sass-loader": "7.1.0",
"script-ext-html-webpack-plugin": "2.1.3",
"raw-loader": "3.1.0",
"readdirp": "3.1.2",
"sass-loader": "7.3.1",
"script-ext-html-webpack-plugin": "2.1.4",
"source-map-loader": "0.2.4",
"style-loader": "0.23.1",
"terser-webpack-plugin": "1.2.3",
"ts-loader": "5.3.3",
"tslint": "5.13.1",
"style-loader": "1.0.0",
"terser-webpack-plugin": "1.4.1",
"travis-size-report": "1.1.0",
"ts-loader": "6.0.3",
"tslint": "5.19.0",
"tslint-config-airbnb": "5.11.1",
"tslint-config-semistandard": "7.0.0",
"tslint-react": "3.6.0",
"typed-css-modules": "0.4.1",
"typescript": "3.3.3333",
"url-loader": "1.1.2",
"webpack": "4.28.0",
"webpack-bundle-analyzer": "3.1.0",
"webpack-cli": "3.2.3",
"webpack-dev-server": "3.2.1",
"tslint-config-semistandard": "8.0.1",
"tslint-react": "4.0.0",
"typed-css-modules": "0.4.2",
"typescript": "3.5.3",
"url-loader": "2.1.0",
"webpack": "4.39.3",
"webpack-bundle-analyzer": "3.4.1",
"webpack-cli": "3.3.4",
"webpack-dev-server": "3.8.0",
"worker-plugin": "3.1.0"
}
}

View File

@ -1,5 +1,3 @@
{
"extends": [
"config:base"
]
"enabled": false
}

14
sizereport.config.js Normal file
View File

@ -0,0 +1,14 @@
const escapeRE = require("escape-string-regexp");
module.exports = {
repo: "GoogleChromeLabs/squoosh",
path: "build/**/!(*.map)",
branch: "dev",
findRenamed(path, newPaths) {
const nameParts = /^(.+\.)[a-f0-9]+(\..+)$/.exec(path);
if (!nameParts) return;
const matchRe = new RegExp(`^${escapeRE(nameParts[1])}[a-f0-9]+${escapeRE(nameParts[2])}$`);
return newPaths.find(newPath => matchRe.test(newPath));
}
};

View File

@ -1,5 +1,5 @@
import * as identity from './identity/encoder-meta';
import * as optiPNG from './optipng/encoder-meta';
import * as oxiPNG from './oxipng/encoder-meta';
import * as mozJPEG from './mozjpeg/encoder-meta';
import * as webP from './webp/encoder-meta';
import * as browserPNG from './browser-png/encoder-meta';
@ -17,7 +17,7 @@ export interface EncoderSupportMap {
export type EncoderState =
identity.EncoderState |
optiPNG.EncoderState |
oxiPNG.EncoderState |
mozJPEG.EncoderState |
webP.EncoderState |
browserPNG.EncoderState |
@ -31,7 +31,7 @@ export type EncoderState =
export type EncoderOptions =
identity.EncodeOptions |
optiPNG.EncodeOptions |
oxiPNG.EncodeOptions |
mozJPEG.EncodeOptions |
webP.EncodeOptions |
browserPNG.EncodeOptions |
@ -47,7 +47,7 @@ export type EncoderType = keyof typeof encoderMap;
export const encoderMap = {
[identity.type]: identity,
[optiPNG.type]: optiPNG,
[oxiPNG.type]: oxiPNG,
[mozJPEG.type]: mozJPEG,
[webP.type]: webP,
[browserPNG.type]: browserPNG,

View File

@ -0,0 +1,3 @@
export interface HqxOptions {
factor: 2 | 3 | 4;
}

View File

@ -0,0 +1,20 @@
import { resize } from '../../../codecs/hqx/pkg';
import { HqxOptions } from './processor-meta';
export async function hqx(
data: ImageData,
opts: HqxOptions,
): Promise<ImageData> {
const input = data;
const result = resize(
new Uint32Array(input.data.buffer),
input.width,
input.height,
opts.factor,
);
return new ImageData(
new Uint8ClampedArray(result.buffer),
data.width * opts.factor,
data.height * opts.factor,
);
}

View File

@ -1,18 +0,0 @@
import optipng, { OptiPngModule } from '../../../codecs/optipng/optipng';
import wasmUrl from '../../../codecs/optipng/optipng.wasm';
import { EncodeOptions } from './encoder-meta';
import { initEmscriptenModule } from '../util';
let emscriptenModule: Promise<OptiPngModule>;
export async function compress(data: BufferSource, options: EncodeOptions): Promise<ArrayBuffer> {
if (!emscriptenModule) emscriptenModule = initEmscriptenModule(optipng, wasmUrl);
const module = await emscriptenModule;
const resultView = module.compress(data, options);
const result = new Uint8Array(resultView);
module.free_result();
// wasm cant run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
return result.buffer as ArrayBuffer;
}

View File

@ -4,7 +4,7 @@ export interface EncodeOptions {
export interface EncoderState { type: typeof type; options: EncodeOptions; }
export const type = 'png';
export const label = 'OptiPNG';
export const label = 'OxiPNG';
export const mimeType = 'image/png';
export const extension = 'png';

Some files were not shown because too many files have changed in this diff Show More