Compare commits

..

699 Commits

Author SHA1 Message Date
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
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
bc5da7ef06 1.5.0 2019-03-08 11:19:34 +00:00
45221c0b03 Implement alpha premultiplication (#507)
* Implement alpha premultiplication

* Add benchmark to resize

* Only display "Premultiply alpha" if it's one of the rust resize types.

* Add comment about division by zero
2019-03-08 11:18:59 +00:00
d29cf2ffa7 Merge pull request #501 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.30
2019-03-06 22:02:52 +00:00
f6c0b89d1f Update dependency @types/node to v10.12.30 2019-03-06 20:14:19 +00:00
ecd9e06665 1.4.0 2019-03-06 17:20:54 +00:00
9e5b66d5f4 Better resize methods (#498)
* Port resize to wasm

* Expose resize algorithms

* Lanczos3 working!

* lol copy paste

* Adding support for other resizers

* Don’t track generated README

* Cache wasm instance
2019-03-06 17:20:25 +00:00
8c35c3cdaa Merge pull request #497 from GoogleChromeLabs/renovate/node-10.x
Update Node.js to v10.15.3
2019-03-05 23:26:23 +00:00
828a6240fe Update Node.js to v10.15.3 2019-03-05 20:51:40 +00:00
eaad0eaee0 1.3.4 2019-03-04 14:53:11 +00:00
db76d4417c Don’t use instantiateStreaming (#494) 2019-03-04 14:50:15 +00:00
7a6c6ec210 Merge pull request #492 from GoogleChromeLabs/renovate/typed-css-modules-0.x
Update dependency typed-css-modules to v0.4.1
2019-03-03 17:22:26 +00:00
8e034f183b Update dependency typed-css-modules to v0.4.1 2019-03-03 15:37:17 +00:00
5a01b34cce Merge pull request #491 from GoogleChromeLabs/renovate/webpack-bundle-analyzer-3.x
Update dependency webpack-bundle-analyzer to v3.1.0
2019-03-03 13:21:08 +00:00
1399a9bffe Update dependency webpack-bundle-analyzer to v3.1.0 2019-03-02 16:47:49 +00:00
653c6ed85a Merge pull request #490 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.29
2019-03-02 16:46:24 +00:00
ebbb7b58cb Update dependency @types/node to v10.12.29 2019-03-02 02:14:38 +00:00
7164e4e315 Merge pull request #489 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.13.1
2019-03-01 08:54:11 +00:00
23398d07f9 Update dependency tslint to v5.13.1 2019-03-01 03:07:29 +00:00
ec2bc3efa2 Merge pull request #488 from GoogleChromeLabs/renovate/assets-webpack-plugin-3.x
Update dependency assets-webpack-plugin to v3.9.10
2019-02-28 19:06:57 +00:00
86d78763c1 Update dependency assets-webpack-plugin to v3.9.10 2019-02-28 19:01:50 +00:00
fb5ae36d7e Merge pull request #487 from GoogleChromeLabs/renovate/assets-webpack-plugin-3.x
Update dependency assets-webpack-plugin to v3.9.9
2019-02-28 15:40:43 +00:00
51f812625b Update dependency assets-webpack-plugin to v3.9.9 2019-02-28 15:33:56 +00:00
479bfee647 Merge pull request #486 from GoogleChromeLabs/renovate/node-10.x
Update Node.js to v10.15.2
2019-02-28 14:03:11 +00:00
a3501a56cd Update Node.js to v10.15.2 2019-02-28 13:51:15 +00:00
c353e286b0 Merge pull request #485 from GoogleChromeLabs/renovate/assets-webpack-plugin-3.x
Update dependency assets-webpack-plugin to v3.9.8
2019-02-28 09:35:03 +00:00
8ed01e8a87 Update dependency assets-webpack-plugin to v3.9.8 2019-02-28 04:55:19 +00:00
36ed21b9f4 Merge pull request #484 from GoogleChromeLabs/renovate/webpack-dev-server-3.x
Update dependency webpack-dev-server to v3.2.1
2019-02-25 15:03:53 +00:00
cca41bb449 Update dependency webpack-dev-server to v3.2.1 2019-02-25 14:14:58 +00:00
8f787ad0e6 Merge pull request #483 from GoogleChromeLabs/renovate/terser-webpack-plugin-1.x
Update dependency terser-webpack-plugin to v1.2.3
2019-02-25 14:13:23 +00:00
9c1170f100 Update dependency terser-webpack-plugin to v1.2.3 2019-02-25 11:20:37 +00:00
5432be4a3f Merge pull request #482 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.13.0
2019-02-24 18:54:51 +00:00
7cae821db5 Update dependency tslint to v5.13.0 2019-02-23 22:21:29 +00:00
19ebb24f03 Merge pull request #481 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.27
2019-02-23 08:45:17 +00:00
d07512566e Update dependency @types/node to v10.12.27 2019-02-22 22:27:01 +00:00
61929666f3 Merge pull request #480 from GoogleChromeLabs/renovate/prerender-loader-1.x
Update dependency prerender-loader to v1.3.0
2019-02-22 15:59:25 +00:00
792ffbfcd7 Update dependency prerender-loader to v1.3.0 2019-02-22 15:54:09 +00:00
9685271bb4 Merge pull request #479 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.3.3333
2019-02-22 15:03:59 +00:00
5b1a6cc95e Update dependency typescript to v3.3.3333 2019-02-22 14:23:45 +00:00
bf34075e6a Update dependency typescript to v3.3.1 (#444)
* Update dependency typescript to v3.3.1

* Fix trailing commas for function calls

* Reverting trailing comma change

* Avoiding trailing comma rule for imports

* I never know what the right thing to do is

* lockfile
2019-02-22 14:22:57 +00:00
f1859eeef2 Only compare against the last 'push' to master (#468) 2019-02-22 11:15:50 +00:00
fa12b37e53 Merge pull request #470 from GoogleChromeLabs/renovate/file-drop-element-0.x
Update dependency file-drop-element to v0.2.0
2019-02-21 23:42:35 +00:00
520a5dc9f2 nggggg - file length === 0 2019-02-21 21:27:59 +00:00
7af949b5a5 Fixing a second whoopsie. 2019-02-21 20:53:14 +00:00
300612b09b Fixing a whoopsie 2019-02-21 20:38:08 +00:00
6f00e9825c Fixing the multifile dep update: file->files 2019-02-21 20:35:49 +00:00
6ca9c5300e Update dependency file-drop-element to v0.2.0 2019-02-21 15:24:22 +00:00
cdeb31051b Merge pull request #464 from GoogleChromeLabs/tiling-rust
Tiling for Rotate
2019-02-21 15:23:32 +00:00
ba90517ad7 Remove baseline benchmark and switch to tile size 16 2019-02-21 15:16:26 +00:00
7aff949f47 Merge pull request #476 from jviide/tiling-rust-02
Fix potential over-the-bounds slicing in rotate.rs introduced in #474
2019-02-21 15:16:26 +00:00
0e8c0da3dd Update the built rotate.wasm file 2019-02-21 15:16:26 +00:00
3132a207e1 Fix potential over-the-bounds slicing in rotate.rs 2019-02-21 15:16:26 +00:00
88dd0e06c5 Merge pull request #474 from jviide/tiling-rust
Remove timing difference between 90° and 270° rotations (in the tiling Rust code)
2019-02-21 15:16:25 +00:00
f507a2464f Update the built rotate.wasm file 2019-02-21 15:16:25 +00:00
14baa6ebf8 Reorganize rotate.rs, separate rotations into their own functions 2019-02-21 15:16:25 +00:00
5d32126565 Use iteration in rotate.rs whenever possible 2019-02-21 15:16:25 +00:00
484ff7ab4c Fix unwrap_hard when debug_assertions is set 2019-02-21 15:16:25 +00:00
36f86385a2 Update benchmark flags 2019-02-21 15:16:24 +00:00
436faa17af More conservative tiling size 2019-02-21 15:16:24 +00:00
d205ae206f Implement 180 and 270 2019-02-21 15:16:24 +00:00
6baa5900fc Implement tiling 2019-02-21 15:16:24 +00:00
fadb53f075 Readd rotation cases 2019-02-21 15:16:24 +00:00
1a63387408 Use a trait to make it nicer 2019-02-21 15:16:23 +00:00
a316120b69 Switch to 8 byte offset 2019-02-21 15:16:23 +00:00
0d1e5ef119 Simplify rotation code to 90deg only 2019-02-21 15:16:23 +00:00
b49cfca39d Scriptify benchmark running 2019-02-21 15:16:23 +00:00
ab58df4c2c Benchmark all rotations 2019-02-21 15:16:22 +00:00
db20f10bd2 Write d8 benchmark using the baseline compiler 2019-02-21 15:16:22 +00:00
444cc5a193 Merge pull request #475 from GoogleChromeLabs/renovate/critters-webpack-plugin-2.x
Update dependency critters-webpack-plugin to v2.3.0
2019-02-21 14:57:58 +00:00
6c253bc9b4 Update dependency critters-webpack-plugin to v2.3.0 2019-02-21 02:46:18 +00:00
2fd28e174e Merge pull request #473 from GoogleChromeLabs/renovate/webpack-dev-server-3.x
Update dependency webpack-dev-server to v3.2.0
2019-02-20 15:03:01 +00:00
a188692c88 Update dependency webpack-dev-server to v3.2.0 2019-02-20 14:41:25 +00:00
b263419e08 Merge pull request #472 from GoogleChromeLabs/renovate/copy-webpack-plugin-5.x
Update dependency copy-webpack-plugin to v5
2019-02-20 14:39:15 +00:00
826e06c727 Update dependency copy-webpack-plugin to v5 2019-02-20 13:22:09 +00:00
dfcdfb105f Merge pull request #471 from GoogleChromeLabs/renovate/worker-plugin-3.x
Update dependency worker-plugin to v3.1.0
2019-02-20 10:46:01 +00:00
0508bbb16f Update dependency worker-plugin to v3.1.0 2019-02-19 16:15:03 +00:00
dfbfa85fd3 Merge pull request #467 from GoogleChromeLabs/renovate/chokidar-2.x
Update dependency chokidar to v2.1.2
2019-02-18 21:03:44 +01:00
b99ad4bdc3 Update dependency chokidar to v2.1.2 2019-02-18 19:59:01 +00:00
e801170496 1.3.3 2019-02-15 09:49:34 +00:00
91e7c9c5ad Make Rust rotate code smaller (#462)
* Make Rust rotate code smaller

* Back on the rust happy path
2019-02-15 09:47:26 +00:00
ca5162ed32 Updating package lock to fix Netlify 2019-02-13 15:08:56 +00:00
0bf87d0c87 Merge pull request #461 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.26
2019-02-13 14:02:00 +00:00
ce91eb5bae Update dependency @types/node to v10.12.26 2019-02-13 00:00:41 +00:00
8d68056bca Merge pull request #457 from GoogleChromeLabs/renovate/chokidar-2.x
Update dependency chokidar to v2.1.1
2019-02-12 13:24:03 +00:00
d0de8e444a Update dependency chokidar to v2.1.1 2019-02-12 12:17:17 +00:00
dfef1f21cc Merge pull request #455 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.25
2019-02-12 12:16:17 +00:00
2440ac4e87 Update dependency @types/node to v10.12.25 2019-02-12 11:09:55 +00:00
e90db78697 Merge pull request #459 from GoogleChromeLabs/renovate/webpack-bundle-analyzer-3.x
Update dependency webpack-bundle-analyzer to v3.0.4
2019-02-12 11:09:08 +00:00
5ae15d429c Update dependency webpack-bundle-analyzer to v3.0.4 2019-02-12 10:54:25 +00:00
89d6b46f3e 1.3.2 2019-02-12 10:03:12 +00:00
e086f64779 Merge pull request #458 from jviide/rust-rotate
Fix buffer offset/size calculations in rotate/processor.ts
2019-02-11 22:42:07 +00:00
9ed3b4f11e Fix buffer size/offset calculations in rotate/processor.ts 2019-02-12 00:12:04 +02:00
ece3fa12b4 Merge pull request #438 from GoogleChromeLabs/rust-rotate
Rotate implementation in Rust
2019-02-11 16:26:01 +00:00
9a35224535 Update wasm build 2019-02-11 16:22:29 +00:00
ef3faa58bc Reuse rotate instance and calculate pages correctly 2019-02-11 16:22:28 +00:00
b6a8f7eeba Rotate implementation in Rust 2019-02-11 16:22:28 +00:00
d1203d9c42 Switching to 1.4x rather than 140% 2019-02-11 13:58:28 +00:00
a834b6ae38 Pin dependencies (#456) 2019-02-11 12:18:07 +00:00
e7982a73ad no one must know I did this, or that it got through review. 2019-02-11 11:34:40 +00:00
717342c80c Adding CI step to compare build size to previous master build. (#450) 2019-02-11 11:12:57 +00:00
075f0e62fd Merge pull request #453 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.23
2019-02-08 11:43:56 +00:00
bcca31fbed Update dependency @types/node to v10.12.23 2019-02-08 02:22:49 +00:00
007891fc11 Merge pull request #413 from GoogleChromeLabs/renovate/loader-utils-1.x
Update dependency loader-utils to v1.2.3
2019-02-06 15:59:07 +00:00
f8e41952d1 Update dependency loader-utils to v1.2.3 2019-02-06 15:53:15 +00:00
e4d64f8a79 Merge pull request #451 from GoogleChromeLabs/renovate/chokidar-2.x
Update dependency chokidar to v2.1.0
2019-02-06 15:52:09 +00:00
1654f69ec1 Update dependency chokidar to v2.1.0 2019-02-05 19:28:54 +00:00
cb16fb5437 Update libwebp to 1.0.2 (#439)
* Update package.json

* Update package.json

* Update README.md

* Update README.md

* Use cmake for libwebp

* Minimize libwebp
2019-02-05 15:45:03 +00:00
36f5fa2c47 Merge pull request #449 from GoogleChromeLabs/renovate/webpack-cli-3.x
Update dependency webpack-cli to v3.2.3
2019-02-05 10:20:37 +00:00
51ad22e72c Update dependency webpack-cli to v3.2.3 2019-02-05 03:22:41 +00:00
1a355c0c16 Merge pull request #448 from GoogleChromeLabs/renovate/terser-webpack-plugin-1.x
Update dependency terser-webpack-plugin to v1.2.2
2019-02-04 15:39:59 +00:00
fe5ba08963 Update dependency terser-webpack-plugin to v1.2.2 2019-02-04 14:46:39 +00:00
7fc994d4af This fixes #446 and sometimes it's best not to ask too many questions. (#447) 2019-02-04 13:34:56 +00:00
a0a8285e02 Merge pull request #445 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.21
2019-02-01 10:08:47 +00:00
da2e35f613 Update dependency @types/node to v10.12.21 2019-02-01 05:41:46 +00:00
09bdc25352 Merge pull request #443 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.20
2019-01-31 10:44:30 +00:00
ad263a9c36 Update dependency @types/node to v10.12.20 2019-01-30 23:41:51 +00:00
c8d8d4e43d Merge pull request #442 from GoogleChromeLabs/renovate/progress-bar-webpack-plugin-1.x
Update dependency progress-bar-webpack-plugin to v1.12.1
2019-01-29 18:11:12 +00:00
94249b8a93 Update dependency progress-bar-webpack-plugin to v1.12.1 2019-01-29 15:49:49 +00:00
edd2c51eb6 Merge pull request #441 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.19
2019-01-29 10:08:35 +00:00
1d24e9399f Update dependency @types/node to v10.12.19 2019-01-29 00:45:56 +00:00
3a0062276d Merge pull request #436 from GoogleChromeLabs/optimize-rotate
Optimize rotate
2019-01-23 22:45:10 -05:00
1993cf3f6c Remove unused bpp 2019-01-23 14:15:39 -05:00
c97aac31c6 Revert "Add rotate user timing"
This reverts commit 887db675c8.
2019-01-23 14:06:24 -05:00
507921cbe8 Use Uint32Array to copy an entire pixel per op 2019-01-23 10:17:52 -05:00
887db675c8 Add rotate user timing 2019-01-23 10:11:35 -05:00
3917618e4e Merge pull request #435 from GoogleChromeLabs/renovate/progress-bar-webpack-plugin-1.x
Update dependency progress-bar-webpack-plugin to v1.12.0
2019-01-22 13:36:30 -05:00
3c42d2e6a4 Update dependency progress-bar-webpack-plugin to v1.12.0 2019-01-22 18:01:07 +00:00
db8777b7f7 Merge pull request #434 from GoogleChromeLabs/renovate/clean-webpack-plugin-1.x
Update dependency clean-webpack-plugin to v1.0.1
2019-01-22 09:04:33 -05:00
18c2cddee2 Update dependency clean-webpack-plugin to v1.0.1 2019-01-22 05:14:58 +00:00
3ff9d3a1fa Merge pull request #432 from GoogleChromeLabs/renovate/critters-webpack-plugin-2.x
Update dependency critters-webpack-plugin to v2.2.0
2019-01-18 14:21:42 -05:00
6503667c78 Update dependency critters-webpack-plugin to v2.2.0 2019-01-18 16:46:25 +00:00
0fa95f84d4 Merge pull request #431 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.2.4
2019-01-17 19:45:53 -05:00
cf91a90270 Update dependency typescript to v3.2.4 2019-01-17 22:56:11 +00:00
690052f989 Merge pull request #427 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.12.1
2019-01-10 23:06:29 +00:00
b3e935f7e4 Update dependency tslint to v5.12.1 2019-01-10 22:41:01 +00:00
17314ebd29 Merge pull request #424 from GoogleChromeLabs/renovate/webpack-cli-3.x
Update dependency webpack-cli to v3.2.1
2019-01-10 17:10:54 +00:00
adc437cd51 Update dependency webpack-cli to v3.2.1 2019-01-07 10:23:37 +00:00
0e97b74510 Merge pull request #422 from GoogleChromeLabs/renovate/critters-webpack-plugin-2.x
Update dependency critters-webpack-plugin to v2.1.3
2019-01-07 11:21:36 +01:00
9ffb475cac Update dependency critters-webpack-plugin to v2.1.3 2019-01-05 20:00:02 +00:00
faa2b030c5 Merge pull request #423 from GoogleChromeLabs/renovate/ts-loader-5.x
Update dependency ts-loader to v5.3.3
2019-01-05 19:59:13 +00:00
e3b3b10e2a Update dependency ts-loader to v5.3.3 2019-01-05 19:19:18 +00:00
b569cf268c Merge pull request #415 from GoogleChromeLabs/renovate/critters-webpack-plugin-2.x
Update dependency critters-webpack-plugin to v2.1.2
2019-01-03 19:34:04 +00:00
b154b77556 Update dependency critters-webpack-plugin to v2.1.2 2019-01-03 19:24:19 +00:00
84c0f30a7c Merge pull request #420 from GoogleChromeLabs/renovate/webpack-cli-serve-0.x
Update dependency @webpack-cli/serve to v0.1.3
2019-01-03 19:23:19 +00:00
16463ff76d Update dependency @webpack-cli/serve to v0.1.3 2019-01-03 19:10:09 +00:00
8314e9e24b Merge pull request #421 from GoogleChromeLabs/renovate/webpack-cli-3.x
Update dependency webpack-cli to v3.2.0
2019-01-03 19:08:32 +00:00
a33c557818 Update dependency webpack-cli to v3.2.0 2019-01-03 05:49:28 +00:00
6fbdc65ad0 Merge pull request #418 from GoogleChromeLabs/renovate/husky-1.x
Update dependency husky to v1.3.1
2018-12-28 10:05:10 -05:00
9c9b6c4711 Update dependency husky to v1.3.1 2018-12-28 06:24:00 +00:00
46278d04c3 Merge pull request #414 from GoogleChromeLabs/renovate/terser-webpack-plugin-1.x
Update dependency terser-webpack-plugin to v1.2.1
2018-12-27 07:41:51 -05:00
c1c16508b5 Update dependency terser-webpack-plugin to v1.2.1 2018-12-27 12:35:42 +00:00
ed1b983711 Merge pull request #412 from GoogleChromeLabs/renovate/loader-utils-1.x
Update dependency loader-utils to v1.2.0
2018-12-24 22:04:29 +00:00
ec23e28eda Update dependency loader-utils to v1.2.0 2018-12-24 18:49:01 +00:00
d48b49e8e4 Merge pull request #411 from GoogleChromeLabs/renovate/webpack-dev-server-3.x
Update dependency webpack-dev-server to v3.1.14
2018-12-24 18:48:10 +00:00
14308970c6 Update dependency webpack-dev-server to v3.1.14 2018-12-24 10:09:10 +00:00
38e86e1012 Merge pull request #410 from GoogleChromeLabs/renovate/webpack-dev-server-3.x
Update dependency webpack-dev-server to v3.1.13
2018-12-22 19:52:50 +00:00
e9a33af831 Update dependency webpack-dev-server to v3.1.13 2018-12-22 19:29:27 +00:00
6a63e5dbb2 Merge pull request #409 from GoogleChromeLabs/renovate/terser-webpack-plugin-1.x
Update dependency terser-webpack-plugin to v1.2.0
2018-12-22 16:48:48 +00:00
1e1892a3d5 Update dependency terser-webpack-plugin to v1.2.0 2018-12-22 16:16:11 +00:00
8bff9a2973 Merge pull request #408 from GoogleChromeLabs/renovate/webpack-dev-server-3.x
Update dependency webpack-dev-server to v3.1.12
2018-12-22 16:15:31 +00:00
cbe753dd29 Update dependency webpack-dev-server to v3.1.12 2018-12-22 15:09:41 +00:00
b047845b43 Merge pull request #407 from GoogleChromeLabs/renovate/webpack-dev-server-3.x
Update dependency webpack-dev-server to v3.1.11
2018-12-21 19:17:48 +00:00
1bebc75381 Update dependency webpack-dev-server to v3.1.11 2018-12-21 18:11:16 +00:00
93c46bfc8d Merge pull request #406 from GoogleChromeLabs/renovate/ts-loader-5.x
Update dependency ts-loader to v5.3.2
2018-12-21 10:46:22 +00:00
a3d0f5963e Update dependency ts-loader to v5.3.2 2018-12-21 06:30:17 +00:00
006b82bf05 Merge pull request #404 from GoogleChromeLabs/renovate/file-loader-3.x
Update dependency file-loader to v3
2018-12-20 20:06:12 +00:00
c36e37ac6b Update dependency file-loader to v3 2018-12-20 17:42:21 +00:00
3cf6d7385a Merge pull request #403 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.18
2018-12-19 18:44:47 +00:00
9045b2fa97 Update dependency @types/node to v10.12.18 2018-12-19 18:26:21 +00:00
be6f3b9c6d Merge pull request #402 from GoogleChromeLabs/renovate/webpack-4.x
Update dependency webpack to v4.28.0
2018-12-19 13:00:37 +00:00
5a699b7ce9 Update dependency webpack to v4.28.0 2018-12-19 12:34:47 +00:00
f366a78e87 Merge pull request #400 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.17
2018-12-18 22:32:16 +00:00
c63c7ead51 Update dependency @types/node to v10.12.17 2018-12-18 22:02:40 +00:00
ecfa5902cd Merge pull request #399 from GoogleChromeLabs/renovate/husky-1.x
Update dependency husky to v1.3.0
2018-12-18 20:06:49 +00:00
444027b496 Update dependency husky to v1.3.0 2018-12-18 19:56:39 +00:00
9c5dcb93c7 Merge pull request #398 from GoogleChromeLabs/renovate/tslint-5.x
Update dependency tslint to v5.12.0
2018-12-18 13:12:06 +00:00
9594221271 Update dependency tslint to v5.12.0 2018-12-18 11:48:40 +00:00
01823d3b75 1.3.1 2018-12-18 09:39:59 +00:00
db07a90139 Merge pull request #396 from GoogleChromeLabs/kosamari-patch-2
Update README.md for OptiPNG
2018-12-17 19:15:55 +00:00
962d0928d3 Update README.md
closes #367
updating incorrect URL
2018-12-17 13:43:18 -05:00
e67d50c8e6 Preventing zoom in iOS Safari. (#395) 2018-12-17 17:05:41 +00:00
f9b2f17852 Merge pull request #385 from GoogleChromeLabs/renovate/typescript-3.x
Update dependency typescript to v3.2.2
2018-12-17 12:42:47 +00:00
9746a9f5ed Fix typings for TypeScript v3.2 2018-12-17 12:36:57 +00:00
be0877ecb0 Update dependency typescript to v3.2.2 2018-12-17 12:36:52 +00:00
d2fcdfae43 Debouncing input. Fixes #277 (#394)
* Debouncing input

* Clarifying comment

* More comments and clarifications
2018-12-17 11:54:30 +00:00
2c9eb46941 Merge pull request #393 from GoogleChromeLabs/webp-sharp-fix
Fixing sharp & preprocess settings. Fixes #392.
2018-12-17 10:59:29 +00:00
d30a85fd48 Using use_argb conditionally 2018-12-17 10:21:30 +00:00
9260bed1b1 Fixing sharp & preprocess settings 2018-12-17 10:01:47 +00:00
f6d12985a9 Merge pull request #390 from GoogleChromeLabs/renovate/worker-plugin-3.x
Update dependency worker-plugin to v3
2018-12-14 18:55:31 +00:00
10c9b1db7c Update dependency worker-plugin to v3 2018-12-14 18:10:49 +00:00
4fb17be8de Merge pull request #388 from GoogleChromeLabs/renovate/raw-loader-1.x
Update dependency raw-loader to v1
2018-12-14 18:08:27 +00:00
b592b1a088 Update dependency raw-loader to v1 2018-12-14 15:47:28 +00:00
0544a6507e Merge pull request #386 from GoogleChromeLabs/renovate/webpack-4.x
Update dependency webpack to v4.27.1
2018-12-14 15:45:24 +00:00
1e20ff15ed Update dependency webpack to v4.27.1 2018-12-14 15:28:46 +00:00
04a0ec0645 Merge pull request #383 from GoogleChromeLabs/renovate/tslint-config-airbnb-5.x
Update dependency tslint-config-airbnb to v5.11.1
2018-12-14 15:01:37 +00:00
f355292fe3 Update dependency tslint-config-airbnb to v5.11.1 2018-12-14 13:48:22 +00:00
32e4d813de Merge pull request #382 from GoogleChromeLabs/renovate/ts-loader-5.x
Update dependency ts-loader to v5.3.1
2018-12-14 13:47:40 +00:00
f960f5ea87 Update dependency ts-loader to v5.3.1 2018-12-14 10:18:46 +00:00
aa6f83e2fa Merge pull request #381 from GoogleChromeLabs/renovate/preact-8.x
Update dependency preact to v8.4.2
2018-12-14 10:18:06 +00:00
c09e1f1895 Update dependency preact to v8.4.2 2018-12-14 10:08:17 +00:00
7c311928dd Merge pull request #379 from GoogleChromeLabs/renovate/husky-1.x
Update dependency husky to v1.2.1
2018-12-14 10:07:31 +00:00
5f1c8bcb6b Update dependency husky to v1.2.1 2018-12-14 09:35:57 +00:00
93bc20f014 Merge pull request #378 from GoogleChromeLabs/renovate/critters-webpack-plugin-2.x
Update dependency critters-webpack-plugin to v2.1.1
2018-12-14 09:35:06 +00:00
d29d9571c6 Update dependency critters-webpack-plugin to v2.1.1 2018-12-14 09:28:18 +00:00
3d47dfc820 Merge pull request #375 from GoogleChromeLabs/renovate/webassembly-js-api-0.x
Update dependency @types/webassembly-js-api to v0.0.2
2018-12-14 09:27:04 +00:00
d7846c9add Update dependency @types/webassembly-js-api to v0.0.2 2018-12-14 08:29:39 +00:00
4d6fe9d641 Merge pull request #377 from GoogleChromeLabs/renovate/comlink-3.x
Update dependency comlink to v3.1.1
2018-12-14 08:28:41 +00:00
205feba75d Update dependency comlink to v3.1.1 2018-12-14 00:59:15 +00:00
ca7663b94a Merge pull request #384 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.15
2018-12-14 00:54:30 +00:00
83e45f054b Update dependency @types/node to v10.12.15 2018-12-13 22:44:08 +00:00
783e893a67 Merge pull request #376 from GoogleChromeLabs/renovate/node-10.x
Update dependency @types/node to v10.12.14
2018-12-13 19:09:00 +00:00
0a941866a9 Update dependency @types/node to v10.12.14 2018-12-13 19:03:04 +00:00
04edfe0085 Merge pull request #380 from GoogleChromeLabs/renovate/mini-css-extract-plugin-0.x
Update dependency mini-css-extract-plugin to v0.5.0
2018-12-13 19:02:16 +00:00
6cae634eca Update dependency mini-css-extract-plugin to v0.5.0 2018-12-13 18:53:39 +00:00
8c7bf278dc Merge pull request #374 from GoogleChromeLabs/renovate/pin-dependencies
Pin dependencies
2018-12-13 13:30:08 +00:00
f6106650b5 Pin dependencies 2018-12-13 13:20:33 +00:00
166e606034 Merge pull request #373 from GoogleChromeLabs/renovate/configure
Configure Renovate
2018-12-13 13:19:16 +00:00
c997e6a3e4 Add renovate.json 2018-12-13 13:13:44 +00:00
2a1b6dc9da 1.3.0 2018-12-12 12:59:05 +00:00
129c33fa12 Add basic history handling (#288) (#309)
* Add basic history handling (#288)

* Move history management to Compress component

* Remove unused pathname property from history

* Rename history listener functions

* Use history.back instead of history.replace

* Support going forward in history. Persist last selected file in runtime

* Add netlify redirects file

* Use 301 status code for redirect

* Cleanup _redirects file

* Use 200 status code for redirects

* Simplify onPopState function

* Always redirect to 301 with url rewrite

* Remove redundant history function

* Remove file check on render. Call openEditor synchronously

* Use pushState only if user is on the initial screen. Mount history listener in constructor

* Simplify openEditor condition

* Update early return condition

* Rolling abstractions back into the main component
2018-12-12 12:58:03 +00:00
3245987113 Prevent both sides sharing a download URL. (#369) 2018-12-12 12:51:06 +00:00
593ad62cbb 1.2.3 2018-12-10 12:25:27 +00:00
a625a76e9e Fixed blank text-fields with dark browser theme (#365)
When using dark browser themes the text-fields' text-color becomes white, so the text in those white background text-fields is unreadable.

Patched text-color so that it now is readable.
2018-12-10 12:24:12 +00:00
c2a305304b Rotation optimise. Fixes #362 (#363)
* Move early exit for no-rotation.

* lol this was meant to be 10 seconds.
2018-12-09 07:11:11 +00:00
7389c507fb 1.2.2 2018-12-04 10:57:07 +00:00
68f0f23016 Prevent image becoming misshapen on resize. Fixes #359. (#360) 2018-12-04 10:55:32 +00:00
dc809dde30 1.2.1 2018-11-30 11:44:33 +00:00
80dfa03b94 Avoid wrapping a single button (#357)
* Avoid wrapping a single button

* Making the zoom controls appear on the bottom, when the controls are positioned on the bottom
2018-11-30 11:44:15 +00:00
fca7a5350d 1.2.0 2018-11-30 11:02:10 +00:00
1b693fb57a Rotate (#322)
* Basic rotate & flip

* Flipping resize when orientation changes

* Hack around critters issue.

* Removing generator. Huge perf boost.

* Stable positioning

* Creating input processors

* Allowing rotation to be changed

* Reverting old change

* Adding tooltips

* No more flip

* Removing need for wrapper element boxing

* Adding comment

* Addressing nits

* Bleh
2018-11-30 11:00:25 +00:00
7723bd3b5f Making processor-worker a real worker (to TypeScript) (#351) 2018-11-29 08:39:48 +00:00
723fc142ec 1.1.0 2018-11-29 08:01:46 +00:00
06d4d946d9 Display uploaded file name in the document title (#244) (#326)
* Add filename to the document.title

* minor fixes

* no-space-before-colon
2018-11-29 07:59:34 +00:00
428b7d976d Create CSS typings before build. Fixes #251. (#350)
* Create CSS typings before build

* Let's try this.

* Adding comment

* Remove hack from travis
2018-11-28 16:09:08 +00:00
32f2b4e573 Remove TypeScript-specific static Compress import (#338)
Previously, Compress had a static import only used by TypeScript, 
as the module was loaded dynamically. The type can be replaced with
`import().default`.

TypeScript 2.9 introduced the ability to use `import()` within type 
statements.
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html#import-types
2018-11-28 14:57:05 +00:00
b3ab983f02 Removing if-env (it used the dreaded event-stream). Fixes 339. (#340)
Also updating node-sass.
2018-11-27 11:53:23 +00:00
e011724af4 Merge pull request #331 from GoogleChromeLabs/fix-windows-build
Fix build on Windows
2018-11-22 11:21:24 +00:00
f11a6cb38a Fix build on Windows
Fixes #282.
2018-11-21 11:18:01 -05:00
adf6d3c60d Preventing form defaults. Fixes #294. (#329) 2018-11-21 07:14:40 +00:00
bb8f35ce09 Merge pull request #323 from GoogleChromeLabs/sass-downgrade
Downgrade node-sass (fixes #319)
2018-11-19 12:22:00 +00:00
ae9ae31ddc Downgrade node-sass (fixes #319) 2018-11-19 12:06:47 +00:00
67893817b5 Update issue templates to include feature request (#318) 2018-11-19 01:26:50 -08:00
f8da5b153d Merge pull request #304 : Create issue templates
Create issue templates
2018-11-19 11:55:40 +09:00
e2a956a088 ask to attach images 2018-11-19 11:51:08 +09:00
5c5b001fc7 Merge pull request #269 from DanielRuf/ci/test-nodejs-6-8-10-11
ci: test Node.js 8, 10 and 11
2018-11-18 13:24:37 +00:00
e4beafed97 ci: do not test on Node.js 6 2018-11-18 14:00:28 +01:00
553a504140 Merge pull request #306 from Jarrku/codec-readme-typo
Fix typo
2018-11-16 11:21:28 -08:00
44dd2ee808 Fix typo 2018-11-15 22:02:11 +01:00
b36c851b2a Create issue templates 2018-11-15 10:34:00 -08:00
0502d70cdf Preventing images from being dragged in Edge (#290) 2018-11-14 14:47:00 -08:00
86546574bb Further losslessly optimize logo.svg (#283) 2018-11-14 14:45:47 -08:00
f351712130 Building on #275 (#289)
* Upgrade devDependcies. Replace UglifyJS ⚰ with TerserJS 👶 Fix TypeScript compiler errors

* Remove babel and associated plugins

* Re-enable strictNullChecks and noImplicitAny

* Use surma's better ga type definition.
`ts-ignore` document.activeElement potential null warnings

* Avoiding ignores
2018-11-14 14:04:01 -08:00
c7f2ae2234 Merge pull request #279 from KraigWalker/bug/manifest-orientation
Fix #268 - change orientation to "any" from "portrait" in manifest.json
2018-11-14 08:25:09 -08:00
436f689115 fixes #268 - change orientation to "any" from "portrait" in manifest.json 2018-11-13 17:34:03 +00:00
951c7af724 Allow text fields next to range inputs be empty (yeah that's horrendous grammar but I'm very tired) (#273) 2018-11-13 07:48:25 -08:00
53b46f879f Avoid "update found" on initial load. 2018-11-13 07:37:07 -08:00
cbe82112ab ci: test Node.js 6, 8, 10 and 11 2018-11-13 11:21:51 +01:00
7f5562ccfe Update README.md 2018-11-12 10:35:58 -08:00
76ec946616 Merge pull request #264 from GoogleChromeLabs/readme-typos
Fix typos 🙈
2018-11-11 19:15:45 -08:00
68bb2edb39 Fix typos 🙈 2018-11-11 17:43:20 -08:00
9c85618aff Merge pull request #263 from GoogleChromeLabs/analytics-privacy
Adding readme, privacy section, reducing resolution of analytics data.
2018-11-11 06:07:52 -08:00
aebeff8b4c Adding readme, privacy section, reducing resolution of analytics data. 2018-11-11 05:11:28 -08:00
8d63125b13 Resetting pinch zoom (#261)
* Resetting pinch zoom

* Bumping version
2018-11-11 04:28:39 -08:00
2ca97ef586 Not entirely sure why this causes dev to fail, but this fixes it. 2018-11-10 16:10:25 -08:00
a1a00f0bfb Preload test (#262)
* Preload test

* Don't prerender analytics

* Version bump
2018-11-10 08:20:13 -08:00
6870b135b7 I'm calling this 1.0 2018-11-09 16:01:24 -08:00
a0f1379feb Adding manifest to headers 2018-11-09 12:08:55 -08:00
9b17322478 Removing old file from serviceworker 2018-11-09 11:11:34 -08:00
f562bad286 Add analytics script (fixes #174) (#245) 2018-11-09 10:53:10 -08:00
6994cc3d15 _headers & _redirects generation (#240)
* Generate `_headers` and `_redirects` by passing assets through ejs templates.

* PR feedback

* Excluding service worker stuff from prerender

* Build SW in dev

* Let's give this a try

* lol

* Is this how it works?
2018-11-09 10:49:01 -08:00
9b572f9541 Ta-da. Back button. (#254) 2018-11-09 09:13:32 -08:00
71f893cb44 Enhanced offline (#249)
* Notification of updates & reloading

* Using version in service worker & allowing version to appear elsewhere

* Stupid file

* Ditching changelog for now. Using package json.

* Ugh.
2018-11-09 09:13:14 -08:00
6b76ea0a6f Update file drop (#253) 2018-11-09 08:53:36 -08:00
7616d33883 Startup optimizations (#226)
* Startup optimisations

* I hate this file

* Inline main script

* Reverting change to do a fairer perf comparison

* Inlining again. Weeeeee!

* Lockfile
2018-11-09 16:01:02 +00:00
3c757bb2b2 Prevent browser pinch-zoom (#247) 2018-11-09 15:58:15 +00:00
a502df80ba Prevent logo taking over on smaller screens. (#250)
* Prevent logo taking over on smaller screens.

* I hate this file
2018-11-09 00:02:23 +00:00
921268ec58 Addressing nits from service worker PR. 2018-11-08 12:11:29 +00:00
7d42d4f973 Add a serviceworker (#234)
* Add a serviceworker

* rename + fix random extra character

* Fixing worker typings

* Fixing types properly this time.

* Once of those rare cases where this matters.

* Naming the things.

* Move registration to the app (so we can use snackbar later)

* Moving SW plugin later so it picks up things like HTML

* MVP service worker

* Two stage-service worker

* Fix prerendering by conditionally awaiting Custom Elements polyfill.

* Fix icon 404's

* add doc comment to autoswplugin

* Fix type
2018-11-08 12:02:05 +00:00
e4e130c5d6 Mark private function as private 2018-11-08 11:21:57 +00:00
bcf7a63118 Android tablet bugs (#246)
* Prevent two-up being lost under options. Fixes #241.

* Working around some glitching when page was scrolled.

* Prevent software keyboard popping up again in Android Chrome.
2018-11-07 08:59:11 +00:00
66aac12db7 Caught a bit of repetition in our utils (#242)
Caught a bit of repetition in our utils
2018-11-06 14:19:48 +00:00
59cd1f8930 Splitting PointerTracker into its own project (#238) 2018-11-06 14:19:24 +00:00
150e704d20 It's a dev package 2018-11-06 13:50:50 +00:00
b2d47f0fb8 fixing a deps issue. 2018-11-06 13:50:49 +00:00
bd3d33296d Updating based on changes to filedrop element. 2018-11-06 13:50:49 +00:00
f4c82ced97 #199 - Removes the file-drop custom element
+ Removes the custom element from the project
+ Replaces it with the externally maintined custom element
2018-11-06 13:50:48 +00:00
76188df0d3 Destructuring args. 2018-11-06 13:47:18 +00:00
9a58e4d339 Fixing lossless slider for webP. Previously you couldn't select "9" :D 2018-11-06 13:47:18 +00:00
f396a5b784 MozJPEG chroma subsampling and quality (#235)
* Adding chroma subsampling for mozjpeg

* Adding separate chroma quality.

* Preact sometimes removes the inline styles, this fixes it.

* Simplifying chroma subsample

* Adding comments
2018-11-06 13:46:52 +00:00
e572b853e2 Snackbar defaults & copy undo (#233)
* Fix snackbar defaults. Fixes #205.

* Undo copy settings across.

* Oops

* Fixing stupid minification bug

* Something weird happened with the last commit
2018-11-06 13:44:15 +00:00
726c2f195a Fixing graphics glitch. Fixes #166 (#232) 2018-11-06 13:41:08 +00:00
4599e51b1e Copy to side ui (#229)
* Copy settings to other side button

* Download button on the outside.

* Whoops
2018-11-06 13:39:03 +00:00
d93169cc5a Mobile ui (#227)
* Basic grid setup

* Fixing thumb on two-up

* Adding margin so you can still access the two-up

* Allow multi-panel to keep one open only

* Edge cases for one-open

* Abstracting results so it can be used as a heading.

* Ordering of items in mobile view. Changing scrolling element.

* Adding labels to collapsed view

* Adding height animation to multi-panel

* Fixing animation bugs

* Expand/collapse icon

* Allow two-up and pinch-zoom to work beneath controls

* Range bubble now behaves properly on mobile

* No longer need this.

* Prevent options overflow at larger widths
2018-11-06 13:37:52 +00:00
bdd3c11f1a Options ui (#222)
* wip

* Commenting stuff to keep the build happy

* Revealing sections

* Custom select elements & more form work

* Range input styles

* Text fields with inputs do the right thing

* Safari & Firefox fixes

* Large compress select

* oops

* MozJPEG options updated

* OptPNG options

* These asserts weren't true

* Generic options

* WebP options

* Hiding "edit" when "original image"

* Download icon

* Copy setting button - still not happy with this

* Progress indicator

* Loading icon enter/exit anim

* Preventing controls going under options

* Ahh so that's what was causing scrolling

* Ahh so that's what was causing outlines

* Simplifying range styles and fixing cross-browser

* Processing custom element styles

* Get precision from step by default

* I don't know how or when this happened.

* Don't need that many steps

* Avoid having an element that covers the pinch zoom

* Preventing overlap with zoom controls

* Prevent ts warning

* Fixing spinner position

* Simplifying FileSize
2018-11-06 13:36:23 +00:00
0cec90c7ca Main ui (#214)
* Class for file drop

* OCD

* We don't need the invalid state, as we'll accept all types.

* Flattening CSS

* Fixing zoom input in Firefox

* Fixing 'container' scaleTo

* two-up closer design match & smaller line

* Fixing edge bug
2018-11-06 13:31:58 +00:00
43def798e1 Two workers & worker termination (#198)
* Refactoring codecs

* Plugging in new processor

* Fixing decorator

* MozJPEG free issue

* Better worker aborting, and terminate workers that aren't used for 10 seconds

* Better comment

* Ooops, half-typed comment

* Uncommenting problematic line

* Surma fixed it!

* Abstracting WASM initialisation

* Better comment

* Don't need this.

* Adding ticket

* noInitalRun

* Reverting MozJPEG issue demo

* Making a const for worker timeout

* Inline docs

* Bail early rather than nesting

* Addressing nits
2018-10-28 09:17:43 +00:00
02b0c022ca Edge encode fix (#211)
* No canvas.toBlob in Edge.

* pffft
2018-10-20 14:50:37 +01:00
c82d0d1b88 Fix for loading SVG in Safari. (#212)
* Fix for loading SVG in Safari.

* Tidier code
2018-10-20 14:50:16 +01:00
e24d7865ce Lazy-loading the main part of the app (#197)
* Splitting main part of app out of the main bundle.

Also improving the transition from intro to compressor.

* Showing error if app fails to load.

* lol these aren't async

* Please don't tell anyone I did this

* Spinner if user selects a file before the app has loaded. (#208)
2018-10-20 12:53:36 +01:00
a79f95b305 Fix <range-input disabled> (#195)
* Fix .disabled property reflection for range-input (only attribute worked previously)

* Revert "Fix .disabled property reflection for range-input (only attribute worked previously)"

This reverts commit f5964635b2.

* Fix reflection

* Use hasAttribute()
2018-10-20 12:51:30 +01:00
49b40b1c3e Remove virtual files before running (fixes #217) (#220) 2018-10-19 12:07:01 +01:00
11ee74e224 Edge gets confused about custom properties in @supports. (#206) 2018-10-14 14:11:20 +01:00
f335246673 Use mozjpeg function to free result (#207) 2018-10-14 14:10:21 +01:00
ccb734aec6 Remove firebase travis deploy (for now) (#196)
* remove firebase (for now)

* Also rm .firebaserc
2018-10-14 09:35:07 +01:00
568b9e9459 Styling intro screen and adding demo images. 2018-10-12 14:12:32 +01:00
a43ea761f5 Missing bind 2018-10-12 14:04:18 +01:00
577c77cc30 Codecs cleanup (#189)
* Update imagequant processor

* Update mozjpeg encoder

* Update optipng encoder

* Update webp decoder

* Update webp encoder

* Remove old codec build tasks

* Add warning about docker image updates
2018-10-12 10:53:33 +01:00
d2f60baef9 Handle vectors (#187)
* Allow loading SVG. Fixes #138.

I also made the resizer vector-aware, so you can resize the image larger & stay sharp.

* Handling SVG without width/height set.

* Simplifying maths

* Doh, case sensitive
2018-10-11 14:15:01 +01:00
64acc08cd7 Improving image open time (#185)
* Moving intro into its own component

* Tidying JSX, and allowing image to render before first compression. Fixes #164.
2018-10-11 14:05:18 +01:00
a1f0b81dff Fixing resize again. Fixes #183. (#184) 2018-10-09 13:34:38 +01:00
48bb58dc89 Moving range input component 2018-10-09 12:19:24 +01:00
765cc213d2 Updating linting rules and fixing bug 2018-10-02 14:56:20 +01:00
37f5c0dd76 Design review fixes (#172)
* Design review fixes

* Adding styles for mozjpeg & fixing some merge errors
2018-10-02 14:53:21 +01:00
b25d1eaf86 <range-input> (#171) 2018-10-02 11:41:07 +01:00
248676aa31 Fixing webp sniffing. Fixes #178. (#179) 2018-10-02 11:30:38 +01:00
Ewa
059c80c05d Center the image canvas in PinchZoom (#170)
* Center the image canvas in PinchZoom

* Fixing pinch zoom
2018-10-01 13:57:26 +01:00
cfd42818b7 Edge file constructor fix (#180)
* Hacking around lack of `new File` in Edge.

* Less hacky solution - preserves types
2018-09-28 14:44:59 +01:00
5e66e0acc4 Adding custom element polyfill (#177) 2018-09-27 14:49:45 +01:00
c9fe5ffbcf Creating fallbacks for all ImageBitmap usage & refactoring. (#175)
Fixes #173
2018-09-27 14:44:54 +01:00
1b630a092f Dockerize mozjpeg (#169)
* Dockerize mozjpeg build process

* Update README
2018-09-26 12:31:26 +01:00
Ewa
09e60284cb Merge pull request #168 from GoogleChromeLabs/devnook-fix-105
Reposition the TwoUp handle on resize
2018-09-18 07:29:21 +02:00
76b34c62db Review code format fixes 2018-09-18 07:26:51 +02:00
9d7212bc1d Review code format fixes 2018-09-17 13:25:33 +02:00
1b69c9231d Keep relative screen division while resizing 2018-09-17 13:21:31 +02:00
bcd88f6356 Add fallback to window.onresize 2018-09-17 11:30:06 +02:00
2a47f67214 Reposition the TwoUp handle on resize 2018-09-17 11:08:54 +02:00
5e8dc1b26c Add multi-panel component (#95)
* add multi-panel component

* make _functions private

* fix spelling errors

* spacing fix

* spelling fix

* store result of _getClosestHeading and avoid calling twice.

* remove returns that are not needed

* move getClosestHeading as separate function

* re-thinking casting and logic

* reflect code review

* do not remove focus when hit spacebar

* add comments and fix type

* handle heading keyevents

* set expanded hight to auto
2018-09-12 14:57:01 +01:00
c591f1f37d Result cache LRU (#165)
* Give the result cache some LRU love

* Fixing LRU cache move-to-start, and simplifying
2018-09-11 17:31:08 +01:00
4db43ccd4e Button to copy settings to the other side 2018-09-06 13:05:17 +01:00
ea5d3c2d78 Adding resize preprocessor (#152)
* Adding resize preprocessor

* Using ! on form

* Haha oops

* Using createImageBitmapPolyfill

* Updating package.json

* Oops again

* Ooops again
2018-09-05 15:46:26 +01:00
700b1f15cd Pinch-zoom: scale around given origin. (#139)
Also setting a min scale.
2018-09-05 09:39:26 +01:00
485ba174e3 Adding result cache. Fixes #87. (#148) 2018-09-05 08:29:17 +01:00
32f6f8b941 Options UI (#135)
* Move gzipped size calculations into a worker and wrap it up in a `<GzipSize />` component that will also handle showing % of original size once that info is plumbed

* A couple tweaks for the app welcome (drop files) screen. We don't have mocks for this one, but this is at least a minor improvement.

* Prettier "pop" effect and styling for the drop zone/indicator.

* Styling for the quantization toggle to make it look like a disclosure triangle/button.

* Add controls bar (zoom in/out/to, background toggle). @todo: extract into its own component.

* When clicking/tapping the image area, give it focus.

* Utilities used by this PR

* Add a `two-up-handle` attribute to the handle for easier styling (classname gets mangled so it doesn't make for a good public API)

* Add a dummy comment to test netlify deploy

* Remove commented-out code.

* Fix styling of vertical split (which as it turns out is slightly different in the mocks anyway)

* Use a composited overlay for the dark background instead of animating background-color

* Move grayscale styling into `<two-up>` by default, then set colors via custom properties

* Remove commented-out svg fill

* Remove dummy comment

* Change `<GzipSize>` to be `<FileSize>`, add `compress` option that lets us show gzipped sizes later if we need. Defaults to `false`, and the gzip worker is only lazily instantiated the first time a compressed size calculation is requested.

* Dependency updates

* Remove color animations from dnd overlay

* Don't use a cyclical import for EncodedImage, instead just specify the types of the properties we Options actually uses.

* Pass source image through to FileSize component so it can compute delta

* Stylize size display with colors based on delta amount/direction

* Remove box-shadow animation.

* Simplify font stack

* Remove commented out code

* Remove gzip compression from size component

* Remove memoization bits

* Use specific flattend props instead of passing large context objects around.

* Remove unused packages.

* Remove unreachable String case in FileSize, and omit redundant File type

* Simplify calculateSize()

* Fix types for FileSize!

* Remove FileSize title

* Make delta variable consistent.

* Skip passing compareTo value for original image

* Remove manual focus

* Fix whitespace

* remove unused keyframes

* remove pointless flex-wrap property

* Remove unused resetZoom() method

* Remove pointless flex properties

* Use `on` prefix for event handling

* Remove pointless justify-self property

* Use an inline SVG for TwoUp's handle icon so it can be colored from outside the component..

* Move orientation state up from `<Output>` into `<App>` and share it with `<Options>`.

* Make the options panels responsive :)

* Show a plus sign for size increases `(+8%)`

* Use inline SVG for the zoom +/- icons, collect SVG icons into one file now that I've verified they get tree-shaken properly.

* Fix top/bottom options panels being reversed

* remove commented out code

* lockfile

* Revert quanitzation toggle styles so it's just a checkbox.

* Remove minimum delta for compare size

* Rename data prop to file.

* scale int -> float

* remove tabIndex

* Remove old icon files

* Add width to options panels

* Add vertical scrolling when options are taller than 80% of the screen height.
2018-09-05 08:21:54 +01:00
54ad30a7ed Optipng (#156)
* omg it’s compiling

* example actually works

* Expose compression level options

* Disable crypto and path module emulation in webpack

* Update README

* Remove small image

* Use -O3 on optipng

* Free memory after copy

* Handle unexpected file reader return types

* Rename level label to effort
2018-09-04 16:49:45 +01:00
170d75482e Merge pull request #155 from sendilkumarn/fix-name-replace
fix broken file renaming for file names with dot
2018-08-29 12:18:33 +01:00
a8db2b30f2 fix broken file renaming for file names with dot
remove grouping in regex
2018-08-29 13:12:33 +02:00
e3b1b08424 Make WebP decoder use memory views (#145)
* Make WebP decoder use memory views

* Update webp_dec README

* Port quantizer to memory views as well
2018-08-21 13:29:53 +01:00
8006a1a5e7 Memory view rather than pointers (#144). Part of #141.
* Returning an object seems to work well

* This doesn't work

* This does!

* Better cast?

* Updating usage in Squoosh
2018-08-21 09:27:04 +01:00
1ae65dd4a1 Mozjpeg opts (#140)
* Switching to embind

* Adding options to mozjpeg wasm

* Updating packages

* Ditching enum - causing more problems than it's worth

* Adding mozjpeg options UI

* Forgot about this enum

* Bools just work
2018-08-17 16:25:28 +01:00
bff515b63f Adding changed points and coalescing to pointer tracker. Fixes #133. (#134)
* Adding changed points and coalescing to pointer tracker. Fixes #133.

* Nits and exposing native pointer
2018-08-15 15:14:33 +01:00
65c3ea826f Avoid preprocessing images that have already been preprocessed. (#125)
* Avoid preprocessing images that have already been preprocessed.

* Using cleanMerge an cleanSet, and fixing bugs in our compression.
2018-08-10 12:59:29 +01:00
602d5140f9 Konami code fix. lol. Thanks @remy. 2018-08-08 14:47:58 +01:00
44f0700332 Adding clean-set (#124)
* Adding clean-set

* Moving to our own cleanSet and cleanMerge.

* Oops, this can be simpler

* Allow the path to be a number

* Better typing
2018-08-07 12:19:06 +01:00
c90db020b0 Snackbar (#99)
* Initial swing

* Finish up <snack-bar> implementation and integrate it

* Add missing types

* Use shift() since we dont care about referential equality

* Use `_` for private fields

* Remove rogue handler

* Remove impossible fallback value

* Make `<snack-bar>` actually contain its children

* will-change for the button ripple

* Guard against mutliple button action clicks

* `onhide()` -> `onremove()`

* remove transitionend

* Replace inline ref callback with linkRef

* showError only accepts strings

* Remove undefined initialization

* Throw on error

* Add missing error type.

* `SnackBar` ▶️ `Snack`

* Avoid child retaining a reference to parent, make show() return a Promise.

* async/await and avoid processing the stack if it is already being processed

* Add a meaningful return value to showSnackbar()
2018-08-06 14:32:48 +01:00
ef4094885e Easter egg (#123)
* lol zx quant

* Adding ZX option

* Improving colour selection so we don't end up with the same colour twice. Also fixing a bug with the colour conflict resolution.

* Putting it behind a konami code

* Better comments

* Adding comment

* Removing unnecessary malloc.
2018-08-06 12:42:23 +01:00
b52d9d9194 Merge pull request #122 from GoogleChromeLabs/quant-ui-fix
Quant fixes
2018-08-06 10:16:58 +01:00
d3f2836f48 Hide quantize options if original image. Fixes #120. 2018-08-02 16:59:13 +01:00
27722f77f9 Simplifying new object creation 2018-08-02 16:56:15 +01:00
3a0db14c40 Minor tweaks 2018-08-02 16:52:57 +01:00
e0dc1b48ec Creating new objects rather than mutating existing objects. Fixes #121. 2018-08-02 16:52:11 +01:00
009327c2c4 Merge pull request #115 from GoogleChromeLabs/imagequant
Implement image quantization via libimagequant
2018-08-01 12:50:08 +01:00
b16d60b52b No name on preprocessors 2018-08-01 12:36:31 +01:00
c550fe9283 Refactor preprocessors module 2018-08-01 12:32:45 +01:00
dce4fc70ac Clean up imagquant codec 2018-08-01 12:19:44 +01:00
b3f3ecbf28 Actually respect numColors lol 2018-07-31 12:46:32 +01:00
e8c0ddfc7f Remove lambda from JSX 2018-07-31 12:41:02 +01:00
a002b376af Hook up options UI to quantizer 2018-07-31 12:32:37 +01:00
2165383da4 Start integrating quantizer in the main data flow 2018-07-30 16:54:30 +01:00
5fbf6b297f Hardcode quantization pass 2018-07-30 16:28:37 +01:00
9d5ad83ff8 Transpile libimagequant 2018-07-30 15:51:57 +01:00
07f17dece2 Adding Travis Support (#113)
* Adds travis script that will build the project whenever the master branch is updated.

The key to upload is in travis env variable.

Note: This does not yet run the test suite, it will deploy if the build is successful.
Note: it has to build twice, because the first build will fail due to a loader issue.
2018-07-30 15:47:00 +01:00
f2f467ecb8 WebP encode options (#110)
* Flailing

* Holy shit struct binding

* Options in the encoder!

* Integrating webp options

* Addressing feedback

* This isn't needed anymore
2018-07-27 14:06:45 +01:00
2ea9e22b52 Merge pull request #91 from GoogleChromeLabs/webp-decoder
WASM WebpDecoder
2018-07-20 11:13:09 +01:00
4ee5572d2f Jake’s thoroughness is doing my head in :P 2018-07-20 11:12:42 +01:00
df7e112d22 Nits by Jake 2018-07-20 10:58:07 +01:00
13ac3ed5b2 Use createImageBitmap as hailmary 2018-07-20 10:56:40 +01:00
b7c223bc0d Remove baseline image decoders, refactor decodeFile 2018-07-20 10:56:40 +01:00
0f08121596 Implement mime type sniffing 2018-07-20 10:56:39 +01:00
b15545402a Adressing smaller review comments 2018-07-20 10:56:39 +01:00
b310c97044 Smaller inline webp image 2018-07-20 10:56:38 +01:00
307c6b05ae Write out logging command 2018-07-20 10:56:38 +01:00
77a6d21924 show decode errors reliably. 2018-07-20 10:56:37 +01:00
d22a343378 Actually move decoding to worker 2018-07-20 10:56:37 +01:00
790a5b580d Set up decoder infrastructure 2018-07-20 10:56:36 +01:00
6e8f8bbe41 Vertical two-up (#100)
* Fixing bad property name.

* Allowing two-up to work vertically at smaller widths.

* Switching to orientation attr

* Fixing type and getter/setter behaviour
2018-07-20 09:32:18 +01:00
cc9d01a9ab Basic webp integration (#103) 2018-07-17 10:37:42 +01:00
526520c399 Adds support for onpaste #97 (#98)
* Adds support for onpaste #97

+ file-drop listens for onpaste, if there is data and it matches the
   type it will use that and raise a custom event
+ Adds a new event on file drop 'onfiledrop'
+ App listens for this event and will map to onFileDrop

* Hoisting getFileData

* The linter seems to think Array.from is of type File, when it's not.

* Remove an entire type of event handler.
+ Removes onfilepaste, joins into 'onfiledrop'
+ Adds 'action' to let you distinguish between the paste or drop
+ Updates app so it just uses the one event.

* Fixing PR issues

+ null return types >>> undefiend.
+ FileDropAction type.
+ remove coercsion on the array types.
2018-07-16 14:00:47 +01:00
acbc31bc35 Merge pull request #96 from GoogleChromeLabs/fix-mjs-errors
Fix errors arising from strict .mjs handling
2018-07-10 10:59:06 -04:00
e8e151a926 Fix errors arising from strict .mjs handling. 2018-07-10 10:57:11 -04:00
835a537c55 Fix lint issues resulting from switching to airbnb (#94)
* Fix lint issues resulting from switching to airbnb.

* Case sensitivity change

* Fix lint script to actually lint tsx files
2018-07-10 14:01:09 +01:00
23ea9fad49 Merge pull request #89 from GoogleChromeLabs/mjs
Switch to .mjs for ES Modules.
2018-07-09 15:45:35 -04:00
491280935a Merge pull request #92 from GoogleChromeLabs/fix-workers
Rename encoding worker so it actually runs in a worker
2018-07-04 15:48:22 +01:00
900eda9a8e Rename encoding worker so it actually runs in a worker 2018-07-04 10:35:16 -04:00
38d0057833 Switch to .mjs for ES Modules. Fixes #88. 2018-07-04 10:02:20 -04:00
3867448aad All the encoders that Chrome/Safari/Firefox support out of the box. (#74)
* All the encoders that Chrome/Safari/Firefox support out of the box.

* Typo
2018-07-02 19:10:10 +01:00
807a76d443 Adding download support. Fixes #47. 2018-07-02 19:04:09 +01:00
3e26a0a3cc Fixing file drop for Safari & Edge (#73) 2018-07-02 18:55:46 +01:00
68729979e3 Adding browser's webp encoder (#72)
* Adding WebP (without feature detect in place)

* Adding WebP check

* Remove unused import
2018-07-02 15:49:52 +01:00
a09ec269b8 Adding native encoders (#71)
* Adding browser png

* Adding native JPEG & file size output

* Removing log

* Fixing blob typing

* Fix timing issue
2018-07-02 15:14:09 +01:00
3f18c927f1 Allow mouse wheel on two-up handle. Fixes #49 (#54) 2018-07-02 09:17:57 +01:00
9add650b75 Refactorings (#65)
* Refactorings

* Responding to feedback
2018-07-01 16:01:42 +01:00
cc3ed168d8 Merge pull request #70 from GoogleChromeLabs/lint-fix
Fixing issues raised by the linter. Fixes #68
2018-06-30 00:25:02 +01:00
3b9b1e9f2e Fixing issues raised by the linter. Fixes #68
+ just cleans up issues, and disables one test that can't be fixed.
+ biggest change is encoders not using multiple imports now.
2018-06-29 21:12:17 +00:00
7c220b1a92 Adding in Drag and Drop support to fix #45 (#56)
* Merging file drop

* Fixing double drop
2018-06-29 16:37:48 +01:00
3035a68b90 Options UI (#39)
* Initial work to add Options config

* Use a single encoder instance and retry up to 10 times on failure.

* Switch both sides to allow encoding from the source image, add options configuration for each.

* Styling for options (and a few tweaks for the app)

* Dep updates.

* Remove commented out code.

* Fix Encoder typing

* Fix lint issues

* Apparently I didnt have tslint autofix enabled on the chromebook

* Attempt to fix layout/panning issues

* Fix missing custom element import!

* Fix variable naming, remove dynamic encoder names, remove retry, allow encoders to return ImageData.

* Refactor state management to use an Array of objects and immutable updates instead of relying on explicit update notifications.

* Add Identity encoder, which is a passthrough encoder that handles the "original" view.

* Drop comlink-loader into the project and add ".worker" to the jpeg encoder filename so it runs in a worker (🦄)

* lint fixes.

* cleanup

* smaller PR feedback fixes

* rename "jpeg" codec to "MozJpeg"

* Formatting fixes for Options

* Colocate codecs and their options UIs in src/codecs, and standardize the namings

* Handle canvas errors

* Throw if quality is undefined, add default quality

* add note about temp styles

* add note about temp styles [2]

* Renaming updateOption

* Clarify option input bindings

* Move updateCanvas() to util and rename to drawBitmapToCanvas

* use generics to pass through encoder options

* Remove unused dependencies

* fix options type

* const

* Use `Array.prototype.some()` for image loading check

* Display encoding errors in the UI.

* I fought typescript and I think I won

* This doesn't need to be optional

* Quality isn't optional

* Simplifying comlink casting

* Splitting counters into loading and displaying

* Still loading if the loading counter isn't equal.
2018-06-29 16:29:18 +01:00
65847c0ed7 Merge pull request #62 from GoogleChromeLabs/linting
Switch to tslint and run it as commit hook
2018-06-26 15:16:42 +01:00
5303afe9ad Fix code lint complaints 2018-06-26 15:11:07 +01:00
579b8a494a Use better exclude option 2018-06-26 15:10:54 +01:00
56faf619d0 Allow leading underscores on variable names 2018-06-26 14:44:31 +01:00
85e3a12c84 Add lint fix script 2018-06-26 14:43:33 +01:00
cab8d3f13c Allow leading underscores in private methods 2018-06-26 14:40:28 +01:00
5c651a1716 Switch to tslint and run it as commit hook 2018-06-26 11:19:44 +01:00
ba0ad81646 Merge pull request #52 from GoogleChromeLabs/codec-fixes
Codec fixes
2018-06-14 13:39:22 +01:00
695bbed12b Update webp to v1.0.0 2018-06-14 13:32:05 +01:00
6a6d478f77 Commit webp decoder binaries 2018-06-14 13:29:11 +01:00
d75a3aca9b Merge pull request #50 from GoogleChromeLabs/webp-dec
Decoder for webp
2018-06-14 13:25:49 +01:00
91945da5ae Add documentation 2018-06-13 23:44:46 +01:00
00e73daabd Decoder for webp 2018-06-13 23:40:24 +01:00
253 changed files with 22955 additions and 12417 deletions

View File

@ -1,13 +0,0 @@
{
"plugins": [
"transform-class-properties",
"transform-react-constant-elements",
"transform-react-remove-prop-types",
[
"transform-react-jsx",
{
"pragma": "h"
}
]
]
}

View File

@ -1,5 +0,0 @@
{
"projects": {
"default": "squoosh-beta"
}
}

36
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,36 @@
---
name: Bug report
about: Something is not working as expected
labels:
---
**Before you start**
Please take a look at the [FAQ](https://github.com/GoogleChromeLabs/squoosh/wiki/FAQ) as well as the already opened issues! If nothing fits your problem, go ahead and fill out the following template:
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Version:**
- OS w/ version: [e.g. iOS 12]
- Browser w/ version [e.g. Chrome 70]
- Node version: [e.g. 10.11.0]
- npm version: [e.g. 6.4.1]
**Is your issue related to the quality of image compression?**
Please attach original and output images (you can drag & drop to attach).
- Original image
- Output image from Squoosh
**Additional context, screenshots, screencasts**
Add any other context about the problem here.

View File

@ -0,0 +1,18 @@
---
name: Feature request
about: Suggest an idea for this project
labels:
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Does other service/app have this feature?**
Add any service you know/use that has this feature (We want to know for research)
**Additional context**
Add any other context or screenshots about the feature request here.

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ node_modules
/*.log
*.scss.d.ts
*.css.d.ts
*.o

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
10.16.2

4
.travis.yml Normal file
View File

@ -0,0 +1,4 @@
language: node_js
cache: npm
script: npm run build
after_success: npm run sizereport

View File

@ -1,20 +0,0 @@
FROM selenium/node-chrome:latest
USER root
RUN apt-get update -qqy \
&& apt-get -qqy install python git build-essential \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* \
&& rm /bin/sh && ln -s /bin/bash /bin/sh \
&& chown seluser /usr/local
ENV NVM_DIR /usr/local/nvm
RUN wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash \
&& source $NVM_DIR/nvm.sh \
&& nvm install v8
ENV CHROME_BIN /opt/google/chrome/chrome
ENV INSIDE_DOCKER=1
WORKDIR /usr/src
ENTRYPOINT source $NVM_DIR/nvm.sh && npm i && npm test

View File

@ -1,5 +1,31 @@
# Squoosh!
# [Squoosh]!
Squoosh will be an image compression web app that allows you to dive into the
advanced options provided by various image compressors.
[Squoosh] is an image compression web app that allows you to dive into the advanced options provided
by various image compressors.
# Privacy
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.
Image compression is handled locally; no additional data is sent to the server.
# Building locally
Clone the repo, and:
```sh
npm install
npm run build
```
You can run the development server with:
```sh
npm start
```
[Squoosh]: https://squoosh.app

18
_headers.ejs Normal file
View File

@ -0,0 +1,18 @@
# Long-term cache by default.
/*
Cache-Control: max-age=31536000
# And here are the exceptions:
/
Cache-Control: no-cache
/serviceworker.js
Cache-Control: no-cache
/manifest.json
Cache-Control: must-revalidate, max-age=3600
# URLs in /assets do not include a hash and are mutable.
# But it isn't a big deal if the user gets an old version.
/assets/*
Cache-Control: must-revalidate, max-age=3600

2
_redirects.ejs Normal file
View File

@ -0,0 +1,2 @@
/index.html / 301
/* /index.html 301

View File

@ -11,6 +11,6 @@ $ npm install
$ npm run build
```
This will build two files: `<codec name>_<enc or dec>.js` and `<codec name>_<enc or dec>.wasm`. It will most likely be necessary to set [`Module["locateFile"]`](https://kripken.github.io/emscripten-site/docs/api_reference/module.html#affecting-execution) to sucessfully load the `.wasm` file. When the `.js` file is loaded, a global `<codec name>_<enc or dec>` is created with the same API as an [Emscripten `Module`](https://kripken.github.io/emscripten-site/docs/api_reference/module.html).
This will build two files: `<codec name>_<enc or dec>.js` and `<codec name>_<enc or dec>.wasm`. It will most likely be necessary to set [`Module["locateFile"]`](https://kripken.github.io/emscripten-site/docs/api_reference/module.html#affecting-execution) to successfully load the `.wasm` file. When the `.js` file is loaded, a global `<codec name>_<enc or dec>` is created with the same API as an [Emscripten `Module`](https://kripken.github.io/emscripten-site/docs/api_reference/module.html).
Each codec will document its API in its README.

BIN
codecs/example.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

BIN
codecs/example_palette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

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

@ -0,0 +1,30 @@
# ImageQuant
- Source: <https://github.com/ImageOptim/libimagequant>
- Version: v2.12.1
## Dependencies
- Docker
## Example
See `example.html`
## API
### `int version()`
Returns the version of libimagequant as a number. va.b.c is encoded as 0x0a0b0c
### `RawImage quantize(std::string buffer, int image_width, int image_height, int numColors, float dithering)`
Quantizes the given images, using at most `numColors`, a value between 2 and 256. `dithering` is a value between 0 and 1 controlling the amount of dithering. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`.
### `RawImage zx_quantize(std::string buffer, int image_width, int image_height, float dithering)`
???
### `void free_result()`
Frees the result created by `quantize()`.

45
codecs/imagequant/build.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
set -e
export OPTIMIZE="-Os"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
echo "============================================="
echo "Compiling libimagequant"
echo "============================================="
(
emcc \
${OPTIMIZE} \
-I node_modules/libimagequant \
--std=c99 \
-c \
node_modules/libimagequant/{libimagequant,pam,mediancut,blur,mempool,kmeans,nearest}.c
)
echo "============================================="
echo "Compiling wasm module"
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
)
echo "============================================="
echo "Compiling wasm module done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -0,0 +1,41 @@
<!doctype html>
<style>
canvas {
image-rendering: pixelated;
}
</style>
<script src='imagequant.js'></script>
<script>
const Module = imagequant();
async function loadImage(src) {
// Load image
const img = document.createElement('img');
img.src = src;
await new Promise(resolve => img.onload = resolve);
// Make canvas same size as image
const canvas = document.createElement('canvas');
[canvas.width, canvas.height] = [img.width, img.height];
// Draw image onto canvas
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
return ctx.getImageData(0, 0, img.width, img.height);
}
Module.onRuntimeInitialized = async _ => {
console.log('Version:', Module.version().toString(16));
const image = await loadImage('../example.png');
// const rawImage = Module.quantize(image.data, image.width, image.height, 256, 1.0);
const rawImage = Module.zx_quantize(image.data, image.width, image.height, 1.0);
console.log('done');
Module.free_result();
const imageData = new ImageData(new Uint8ClampedArray(rawImage.buffer), rawImage.width, rawImage.height);
const canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
const ctx = canvas.getContext('2d');
ctx.putImageData(imageData, 0, 0);
document.body.appendChild(canvas);
};
</script>

View File

@ -0,0 +1,245 @@
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include <stdlib.h>
#include <inttypes.h>
#include <limits.h>
#include <math.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);
}
class RawImage {
public:
val buffer;
int width;
int height;
RawImage(val b, int w, int h)
: buffer(b), width(w), height(h) {}
};
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) {
const uint8_t* image_buffer = (uint8_t*)rawimage.c_str();
int size = image_width * image_height;
attr = liq_attr_create();
image = liq_image_create_rgba(attr, image_buffer, image_width, image_height, 0);
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);
liq_write_remapped_image(res, image, image8bit, size);
const liq_palette *pal = liq_get_palette(res);
// Turn palletted image back into an RGBA image
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;
result[i * 4 + 3] = pal->entries[image8bit[i]].a;
}
free(image8bit);
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
};
}
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
};
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.
*/
RawImage zx_quantize(std::string rawimage, int image_width, int image_height, float dithering) {
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);
// For each 8x8 grid
for (int block_start_y = 0; block_start_y < image_height; block_start_y += 8) {
for (int block_start_x = 0; block_start_x < image_width; block_start_x += 8) {
int color_popularity[15] = {0};
int block_index = 0;
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 (block_start_y + block_height > image_height) {
block_height = image_height - block_start_y;
}
if (block_start_x + block_width > image_width) {
block_width = image_width - block_start_x;
}
// For each pixel in that block:
for (int y = block_start_y; y < block_start_y + block_height; y++) {
for (int x = block_start_x; x < block_start_x + block_width; x++) {
int pixel_start = (y * image_width * bytes_per_pixel) + (x * bytes_per_pixel);
int smallest_distance = INT_MAX;
int winning_index = -1;
// Copy pixel data for quantizing later
block[block_index++] = image_buffer[pixel_start];
block[block_index++] = image_buffer[pixel_start + 1];
block[block_index++] = image_buffer[pixel_start + 2];
block[block_index++] = image_buffer[pixel_start + 3];
// Which zx color is this pixel closest to?
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);
if (distance < smallest_distance) {
winning_index = color_index;
smallest_distance = distance;
}
}
color_popularity[winning_index]++;
}
}
// Get the three most popular colours for the block.
int first_color_index = 0;
int second_color_index = 0;
int third_color_index = 0;
int highest_popularity = -1;
int second_highest_popularity = -1;
int third_highest_popularity = -1;
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:
third_color_index = second_color_index;
third_highest_popularity = second_highest_popularity;
second_color_index = first_color_index;
second_highest_popularity = highest_popularity;
first_color_index = color_index;
highest_popularity = color_popularity[color_index];
} else if (color_popularity[color_index] > second_highest_popularity) {
third_color_index = second_color_index;
third_highest_popularity = second_highest_popularity;
second_color_index = color_index;
second_highest_popularity = color_popularity[color_index];
} else if (color_popularity[color_index] > third_highest_popularity) {
third_color_index = color_index;
third_highest_popularity = color_popularity[color_index];
}
}
// 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) {
if (first_color_index >= 8 && second_color_index < 8) {
// Make the second color bright
second_color_index = second_color_index + 7;
} else if (first_color_index < 8 && second_color_index >= 8) {
// Make the second color regular
second_color_index = second_color_index - 7;
}
}
// 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;
}
// Quantize
attr = liq_attr_create();
image = liq_image_create_rgba(attr, block, block_width, block_height, 0);
liq_set_max_colors(attr, 2);
liq_image_add_fixed_color(image, zx_colors[first_color_index]);
liq_image_add_fixed_color(image, zx_colors[second_color_index]);
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);
// 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);
result[resultStartPos + 0] = pal->entries[image8bit[image8BitPos]].r;
result[resultStartPos + 1] = pal->entries[image8bit[image8BitPos]].g;
result[resultStartPos + 2] = pal->entries[image8bit[image8BitPos]].b;
result[resultStartPos + 3] = pal->entries[image8bit[image8BitPos]].a;
}
}
liq_result_destroy(res);
liq_image_destroy(image);
liq_attr_destroy(attr);
}
}
free(image8bit);
return {
val(typed_memory_view(image_width*image_height*4, result)),
image_width,
image_height
};
}
void free_result() {
free(result);
}
EMSCRIPTEN_BINDINGS(my_module) {
class_<RawImage>("RawImage")
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
function("quantize", &quantize);
function("zx_quantize", &zx_quantize);
function("version", &version);
function("free_result", &free_result);
}

15
codecs/imagequant/imagequant.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
interface RawImage {
buffer: Uint8Array;
width: number;
height: number;
}
interface QuantizerModule extends EmscriptenWasm.Module {
quantize(data: BufferSource, width: number, height: number, numColors: number, dither: number): RawImage;
zx_quantize(data: BufferSource, width: number, height: number, dither: number): RawImage;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): QuantizerModule;

View File

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

Binary file not shown.

1147
codecs/imagequant/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -6,8 +6,6 @@
## Dependencies
- Docker
- Automake
- pkg-config
## Example
@ -19,26 +17,31 @@ See `example.html`
Returns the version of MozJPEG as a number. va.b.c is encoded as 0x0a0b0c
### `uint8_t* create_buffer(int width, int height)`
Allocates an RGBA buffer for an image with the given dimension.
### `void destroy_buffer(uint8_t* p)`
Frees a buffer created with `create_buffer`.
### `void encode(uint8_t* image_buffer, int image_width, int image_height, int quality)`
Encodes the given image with given dimension to JPEG. `quality` is a number between 0 and 100. The higher the number, the better the quality of the encoded image. The result is implicitly stored and can be accessed using the `get_result_*()` functions.
### `void free_result()`
Frees the result created by `encode()`.
### `int get_result_pointer()`
### `Uint8Array encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts)`
Returns the pointer to the start of the buffer holding the encoded data.
Encodes the given image with given dimension to JPEG. Options looks like this:
### `int get_result_size()`
Returns the length of the buffer holding the encoded data.
```c++
struct MozJpegOptions {
int quality;
bool baseline;
bool arithmetic;
bool progressive;
bool optimize_coding;
int smoothing;
int color_space;
int quant_table;
bool trellis_multipass;
bool trellis_opt_zero;
bool trellis_opt_table;
int trellis_loops;
bool auto_subsample;
int chroma_subsample;
bool separate_chroma_quality;
int chroma_quality;
};
```

54
codecs/mozjpeg_enc/build.sh Executable file
View File

@ -0,0 +1,54 @@
#!/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 mozjpeg"
echo "============================================="
(
cd node_modules/mozjpeg
autoreconf -fiv
emconfigure ./configure --without-simd
emmake make libjpeg.la
)
echo "============================================="
echo "Compiling mozjpeg done"
echo "============================================="
echo "============================================="
echo "Compiling wasm bindings"
echo "============================================="
(
emcc \
--bind \
${OPTIMIZE} \
--closure 1 \
-s WASM=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 \
mozjpeg_enc.cpp \
node_modules/mozjpeg/.libs/libjpeg.a
)
echo "============================================="
echo "Compiling wasm bindings done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -1,7 +1,7 @@
<!doctype html>
<script src='mozjpeg_enc.js'></script>
<script>
const Module = mozjpeg_enc();
const module = mozjpeg_enc();
async function loadImage(src) {
// Load image
@ -17,26 +17,27 @@
return ctx.getImageData(0, 0, img.width, img.height);
}
Module.onRuntimeInitialized = async _ => {
const api = {
version: Module.cwrap('version', 'number', []),
create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']),
destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']),
encode: Module.cwrap('encode', '', ['number', 'number', 'number', 'number']),
free_result: Module.cwrap('free_result', '', ['number']),
get_result_pointer: Module.cwrap('get_result_pointer', 'number', []),
get_result_size: Module.cwrap('get_result_size', 'number', []),
};
module.onRuntimeInitialized = async _ => {
console.log('Version:', module.version().toString(16));
const image = await loadImage('../example.png');
const p = api.create_buffer(image.width, image.height);
Module.HEAP8.set(image.data, p);
api.encode(p, image.width, image.height, 2);
const resultPointer = api.get_result_pointer();
const resultSize = api.get_result_size();
const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultSize);
const result = new Uint8Array(resultView);
api.free_result(resultPointer);
api.destroy_buffer(p);
const result = module.encode(image.data, image.width, image.height, {
quality: 75,
baseline: false,
arithmetic: false,
progressive: true,
optimize_coding: true,
smoothing: 0,
color_space: 3,
quant_table: 3,
trellis_multipass: false,
trellis_opt_zero: false,
trellis_opt_table: false,
trellis_loops: 1,
auto_subsample: true,
chroma_subsample: 2,
separate_chroma_quality: false,
chroma_quality: 75,
});
const blob = new Blob([result], {type: 'image/jpeg'});
const blobURL = URL.createObjectURL(blob);

View File

@ -1,17 +1,40 @@
#include "emscripten.h"
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <setjmp.h>
#include <string.h>
#include "jpeglib.h"
#include "config.h"
#include "jpeglib.h"
#include "cdjpeg.h"
// 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
using namespace emscripten;
// MozJPEG doesnt expose a numeric version, so I have to do some fun C macro hackery to turn it
// into a string. More details here: https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
#define xstr(s) str(s)
#define str(s) #s
EMSCRIPTEN_KEEPALIVE
struct MozJpegOptions {
int quality;
bool baseline;
bool arithmetic;
bool progressive;
bool optimize_coding;
int smoothing;
int color_space;
int quant_table;
bool trellis_multipass;
bool trellis_opt_zero;
bool trellis_opt_table;
int trellis_loops;
bool auto_subsample;
int chroma_subsample;
bool separate_chroma_quality;
int chroma_quality;
};
int version() {
char buffer[] = xstr(MOZJPEG_VERSION);
int version = 0;
@ -28,27 +51,11 @@ int version() {
return version;
}
EMSCRIPTEN_KEEPALIVE
uint8_t* create_buffer(int width, int height) {
return malloc(width * height * 4 * sizeof(uint8_t));
}
uint8_t* last_result;
struct jpeg_compress_struct cinfo;
EMSCRIPTEN_KEEPALIVE
void destroy_buffer(uint8_t* p) {
free(p);
}
int result[2];
EMSCRIPTEN_KEEPALIVE
void encode(uint8_t* image_buffer, int image_width, int image_height, int quality) {
// Manually convert RGBA data into RGB
for(int y = 0; y < image_height; y++) {
for(int x = 0; x < image_width; x++) {
image_buffer[(y*image_width + x)*3 + 0] = image_buffer[(y*image_width + x)*4 + 0];
image_buffer[(y*image_width + x)*3 + 1] = image_buffer[(y*image_width + x)*4 + 1];
image_buffer[(y*image_width + x)*3 + 2] = image_buffer[(y*image_width + x)*4 + 2];
}
}
val encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts) {
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
@ -61,7 +68,6 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
* compression/decompression processes, in existence at once. We refer
* to any one struct (and its associated working data) as a "JPEG object".
*/
struct jpeg_compress_struct cinfo;
/* This struct represents a JPEG error handler. It is declared separately
* because applications often want to supply a specialized error handler
* (see the second half of this file for an example). But here we just
@ -109,18 +115,57 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
*/
cinfo.image_width = image_width; /* image width and height, in pixels */
cinfo.image_height = image_height;
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* 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);
/* Now you can set any non-default parameters you wish to.
* Here we just illustrate the use of quality (quantization table) scaling:
*/
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
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);
}
cinfo.optimize_coding = opts.optimize_coding;
if (opts.arithmetic) {
cinfo.arith_code = TRUE;
cinfo.optimize_coding = FALSE;
}
cinfo.smoothing_factor = opts.smoothing;
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_USE_SCANS_IN_TRELLIS, opts.trellis_multipass);
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_TRELLIS_EOB_OPT, opts.trellis_opt_zero);
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_TRELLIS_Q_OPT, opts.trellis_opt_table);
jpeg_c_set_int_param(&cinfo, JINT_TRELLIS_NUM_LOOPS, opts.trellis_loops);
// 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();
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;
cinfo.comp_info[0].v_samp_factor = opts.chroma_subsample;
}
if (!opts.baseline && opts.progressive) {
jpeg_simple_progression(&cinfo);
} else {
cinfo.num_scans = 0;
cinfo.scan_info = NULL;
}
/* Step 4: Start compressor */
/* TRUE ensures that we will write a complete interchange-JPEG file.
@ -136,7 +181,7 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
* To keep things simple, we pass one scanline per call; you can pass
* more if you wish, though.
*/
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
row_stride = image_width * 4; /* JSAMPLEs per row in image_buffer */
while (cinfo.next_scanline < cinfo.image_height) {
/* jpeg_write_scanlines expects an array of pointers to scanlines.
@ -152,27 +197,38 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
jpeg_finish_compress(&cinfo);
/* Step 7: release JPEG compression object */
result[0] = (int)output;
result[1] = size;
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
last_result = output;
/* And we're done! */
return val(typed_memory_view(size, output));
}
EMSCRIPTEN_KEEPALIVE
void free_result() {
free(result[0]); // not sure if this is right with mozjpeg
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_compress(&cinfo);
}
EMSCRIPTEN_KEEPALIVE
int get_result_pointer() {
return result[0];
}
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)
;
EMSCRIPTEN_KEEPALIVE
int get_result_size() {
return result[1];
function("version", &version);
function("encode", &encode);
function("free_result", &free_result);
}

View File

@ -1 +1,8 @@
export default function(opts: EmscriptenWasm.ModuleOpts): EmscriptenWasm.Module;
import { EncodeOptions } from '../../src/codecs/mozjpeg/encoder-meta';
interface MozJPEGModule extends EmscriptenWasm.Module {
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): MozJPEGModule;

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -2,14 +2,12 @@
"name": "mozjpeg_enc",
"scripts": {
"install": "napa",
"build": "npm run build:library && npm run build:wasm",
"build:library": "cd node_modules/mozjpeg && autoreconf -fiv && docker run --rm -v $(pwd):/src trzeci/emscripten emconfigure ./configure --without-simd && docker run --rm -v $(pwd):/src trzeci/emscripten emmake make libjpeg.la",
"build:wasm": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"mozjpeg_enc\"' -I node_modules/mozjpeg -o ./mozjpeg_enc.js mozjpeg_enc.c node_modules/mozjpeg/.libs/libjpeg.a"
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
},
"napa": {
"mozjpeg": "mozilla/mozjpeg#v3.3.1"
},
"devDependencies": {
"napa": "^3.0.0"
"napa": "3.0.0"
}
}

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))
}

6
codecs/resize/.gitignore vendored Normal file
View File

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

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

@ -0,0 +1,37 @@
[package]
name = "resize"
version = "0.1.0"
authors = ["Surma <surma@surma.link>"]
[lib]
#crate-type = ["cdylib", "rlib"]
crate-type = ["cdylib"]
[features]
default = ["console_error_panic_hook", "wee_alloc"]
[dependencies]
cfg-if = "0.1.2"
wasm-bindgen = "0.2.38"
resize = "0.3.0"
# 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

9
codecs/resize/Dockerfile Normal file
View File

@ -0,0 +1,9 @@
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
ENV PATH="/opt/wabt:${PATH}"
WORKDIR /src

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(())
}

22
codecs/resize/build.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/bash
set -e
echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
wasm-pack build
wasm-strip pkg/resize_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-resize .\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

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

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

View File

@ -0,0 +1,7 @@
{
"name": "resize",
"scripts": {
"build:image": "docker build -t squoosh-resize .",
"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"
}

13
codecs/resize/pkg/resize.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
/* tslint:disable */
/**
* @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: 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

@ -0,0 +1,50 @@
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 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;
}
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);
}
/**
* @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;
}

5
codecs/resize/pkg/resize_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, g: number, h: number, i: number, j: number): void;

Binary file not shown.

121
codecs/resize/src/lib.rs Normal file
View File

@ -0,0 +1,121 @@
extern crate cfg_if;
extern crate resize;
extern crate wasm_bindgen;
mod utils;
use cfg_if::cfg_if;
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.
if #[cfg(feature = "wee_alloc")] {
extern crate wee_alloc;
#[global_allocator]
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
}
}
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(
mut input_image: Vec<u8>,
input_width: usize,
input_height: usize,
output_width: usize,
output_height: usize,
typ_idx: usize,
premultiply: bool,
color_space_conversion: bool,
) -> Vec<u8> {
let typ = match typ_idx {
0 => Type::Triangle,
1 => Type::Catrom,
2 => Type::Mitchell,
3 => Type::Lanczos3,
_ => panic!("Nope"),
};
let num_input_pixels = input_width * input_height;
let num_output_pixels = output_width * output_height;
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] =
premultiplier(to_linear(input_image[4 * i + j]), input_image[4 * i + 3]);
}
}
}
let mut resizer = resize::new(
input_width,
input_height,
output_width,
output_height,
RGBA,
typ,
);
let mut output_image = Vec::<u8>::with_capacity(num_output_pixels * 4);
output_image.resize(num_output_pixels * 4, 0);
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
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
// when casting to integers.
output_image[4 * i + j] = to_color_space(demultiplier(
output_image[4 * i + j],
output_image[4 * i + 3],
));
}
}
}
return output_image;
}

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

@ -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() {}
}
}

2
codecs/rotate/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
target
Cargo.lock

14
codecs/rotate/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "rotate"
version = "0.1.0"
authors = ["Surma <surma@google.com>"]
edition = "2018"
[lib]
name = "rotate"
path = "rotate.rs"
crate-type = ["cdylib", "rlib"]
[profile.release]
lto = true
opt-level = "s"

8
codecs/rotate/Dockerfile Normal file
View File

@ -0,0 +1,8 @@
FROM rust
RUN rustup target add wasm32-unknown-unknown
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

@ -0,0 +1,45 @@
// 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
async function init() {
// Adjustable constants.
const imageDimensions = 4096;
const iterations = new Array(100);
// Constants. Dont change.
const imageByteSize = imageDimensions * imageDimensions * 4;
const wasmPageSize = 64 * 1024;
const buffer = readbuffer("rotate.wasm");
const { instance } = await WebAssembly.instantiate(buffer);
const pagesAvailable = Math.floor(
instance.exports.memory.buffer.byteLength / wasmPageSize
);
const pagesNeeded = Math.floor((imageByteSize * 2 + 4) / wasmPageSize) + 1;
const additionalPagesNeeded = pagesNeeded - pagesAvailable;
if (additionalPagesNeeded > 0) {
instance.exports.memory.grow(additionalPagesNeeded);
}
[0, 90, 180, 270].forEach(rotation => {
print(`\n${rotation} degrees`);
print(`==============================`);
for (let i = 0; i < 100; i++) {
const start = Date.now();
instance.exports.rotate(imageDimensions, imageDimensions, rotation);
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.stack));

24
codecs/rotate/build.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash
set -e
echo "============================================="
echo "Compiling wasm"
echo "============================================="
(
cargo build \
--target wasm32-unknown-unknown \
--release
cp target/wasm32-unknown-unknown/release/rotate.wasm .
wasm-strip rotate.wasm
)
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-rotate .\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -0,0 +1,11 @@
{
"name": "rotate",
"scripts": {
"build:image": "docker build -t squoosh-rotate .",
"build": "docker run --rm -v $(pwd):/src squoosh-rotate ./build.sh",
"benchmark": "echo File size after gzip && npm run benchmark:filesize && echo Optimizing && npm run -s benchmark:optimizing",
"benchmark:baseline": "v8 --liftoff --no-wasm-tier-up --no-opt ./benchmark.js",
"benchmark:optimizing": "v8 --no-liftoff --no-wasm-tier-up ./benchmark.js",
"benchmark:filesize": "cat rotate.wasm | gzip -c9n | wc -c"
}
}

113
codecs/rotate/rotate.rs Normal file
View File

@ -0,0 +1,113 @@
use std::slice::{from_raw_parts, from_raw_parts_mut};
// This function is taken from Zachary Dremann
// https://github.com/GoogleChromeLabs/squoosh/pull/462
trait HardUnwrap<T> {
fn unwrap_hard(self) -> T;
}
impl<T> HardUnwrap<T> for Option<T> {
#[cfg(not(debug_assertions))]
#[inline]
fn unwrap_hard(self) -> T {
match self {
Some(t) => t,
None => std::process::abort(),
}
}
#[cfg(debug_assertions)]
fn unwrap_hard(self) -> T {
self.unwrap()
}
}
const TILE_SIZE: usize = 16;
fn get_buffers<'a>(width: usize, height: usize) -> (&'a [u32], &'a mut [u32]) {
let num_pixels = width * height;
let in_b: &[u32];
let out_b: &mut [u32];
unsafe {
in_b = from_raw_parts::<u32>(8 as *const u32, num_pixels);
out_b = from_raw_parts_mut::<u32>((num_pixels * 4 + 8) as *mut u32, num_pixels);
}
return (in_b, out_b);
}
#[inline(never)]
fn rotate_0(width: usize, height: usize) {
let (in_b, out_b) = get_buffers(width, height);
for (in_p, out_p) in in_b.iter().zip(out_b.iter_mut()) {
*out_p = *in_p;
}
}
#[inline(never)]
fn rotate_90(width: usize, height: usize) {
let (in_b, out_b) = get_buffers(width, height);
let new_width = height;
let _new_height = width;
for y_start in (0..height).step_by(TILE_SIZE) {
for x_start in (0..width).step_by(TILE_SIZE) {
for y in y_start..(y_start + TILE_SIZE).min(height) {
let in_offset = y * width;
let in_bounds = if x_start + TILE_SIZE < width {
(in_offset + x_start)..(in_offset + x_start + TILE_SIZE)
} else {
(in_offset + x_start)..(in_offset + width)
};
let in_chunk = in_b.get(in_bounds).unwrap_hard();
for (x, in_p) in in_chunk.iter().enumerate() {
let new_x = (new_width - 1) - y;
let new_y = x + x_start;
*out_b.get_mut(new_y * new_width + new_x).unwrap_hard() = *in_p;
}
}
}
}
}
#[inline(never)]
fn rotate_180(width: usize, height: usize) {
let (in_b, out_b) = get_buffers(width, height);
for (in_p, out_p) in in_b.iter().zip(out_b.iter_mut().rev()) {
*out_p = *in_p;
}
}
#[inline(never)]
fn rotate_270(width: usize, height: usize) {
let (in_b, out_b) = get_buffers(width, height);
let new_width = height;
let new_height = width;
for y_start in (0..height).step_by(TILE_SIZE) {
for x_start in (0..width).step_by(TILE_SIZE) {
for y in y_start..(y_start + TILE_SIZE).min(height) {
let in_offset = y * width;
let in_bounds = if x_start + TILE_SIZE < width {
(in_offset + x_start)..(in_offset + x_start + TILE_SIZE)
} else {
(in_offset + x_start)..(in_offset + width)
};
let in_chunk = in_b.get(in_bounds).unwrap_hard();
for (x, in_p) in in_chunk.iter().enumerate() {
let new_x = y;
let new_y = new_height - 1 - (x_start + x);
*out_b.get_mut(new_y * new_width + new_x).unwrap_hard() = *in_p;
}
}
}
}
}
#[no_mangle]
fn rotate(width: usize, height: usize, rotate: usize) {
match rotate {
0 => rotate_0(width, height),
90 => rotate_90(width, height),
180 => rotate_180(width, height),
270 => rotate_270(width, height),
_ => std::process::abort(),
}
}

BIN
codecs/rotate/rotate.wasm Executable file

Binary file not shown.

22
codecs/webp_dec/README.md Normal file
View File

@ -0,0 +1,22 @@
# WebP decoder
- Source: <https://github.com/webmproject/libwebp>
- Version: v1.0.2
## Example
See `example.html`
## API
### `int version()`
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
### `RawImage decode(std::string buffer)`
Decodes the given webp buffer into raw RGBA. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`.
### `void free_result()`
Frees the result created by `decode()`.

61
codecs/webp_dec/build.sh Executable file
View File

@ -0,0 +1,61 @@
#!/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} \
--closure 1 \
--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 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -0,0 +1,24 @@
<!doctype html>
<script src='webp_dec.js'></script>
<script>
const Module = webp_dec();
async function loadFile(src) {
const resp = await fetch(src);
return await resp.arrayBuffer();
}
Module.onRuntimeInitialized = async _ => {
console.log('Version:', Module.version().toString(16));
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();
const canvas = document.createElement('canvas');
canvas.width = result.width;
canvas.height = result.height;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
ctx.putImageData(imageData, 0, 0);
};
</script>

1147
codecs/webp_dec/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
{
"name": "webp_dec",
"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

@ -0,0 +1,47 @@
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include "src/webp/decode.h"
#include "src/webp/demux.h"
#include <string>
using namespace emscripten;
int version() {
return WebPGetDecoderVersion();
}
class RawImage {
public:
val buffer;
int width;
int height;
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
);
}
void free_result() {
free(last_result);
}
EMSCRIPTEN_BINDINGS(my_module) {
class_<RawImage>("RawImage")
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
function("decode", &decode);
function("version", &version);
function("free_result", &free_result);
}

13
codecs/webp_dec/webp_dec.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
interface RawImage {
buffer: Uint8Array;
width: number;
height: number;
}
interface WebPModule extends EmscriptenWasm.Module {
decode(data: BufferSource): RawImage;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): WebPModule;

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

@ -1,7 +1,7 @@
# WebP encoder
- Source: <https://github.com/webmproject/libwebp>
- Version: v0.6.1
- Version: v1.0.2
## Dependencies
@ -17,26 +17,10 @@ See `example.html`
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
### `uint8_t* create_buffer(int width, int height)`
### `UInt8Array encode(uint8_t* image_buffer, int image_width, int image_height, WebPConfig config)`
Allocates an RGBA buffer for an image with the given dimension.
### `void destroy_buffer(uint8_t* p)`
Frees a buffer created with `create_buffer`.
### `void encode(uint8_t* image_buffer, int image_width, int image_height, float quality)`
Encodes the given image with given dimension to WebP. `quality` is a number between 0 and 100. The higher the number, the better the quality of the encoded image. The result is implicitly stored and can be accessed using the `get_result_*()` functions.
Encodes the given image with given dimension to WebP.
### `void free_result()`
Frees the result created by `encode()`.
### `int get_result_pointer()`
Returns the pointer to the start of the buffer holding the encoded data.
### `int get_result_size()`
Returns the length of the buffer holding the encoded data.
Frees the last result created by `encode()`.

62
codecs/webp_enc/build.sh Executable file
View File

@ -0,0 +1,62 @@
#!/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} \
--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
)
echo "============================================="
echo "Compiling wasm bindings done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

View File

@ -1,7 +1,7 @@
<!doctype html>
<script src='webp_enc.js'></script>
<script>
const Module = webp_enc();
const module = webp_enc();
async function loadImage(src) {
// Load image
@ -17,28 +17,43 @@
return ctx.getImageData(0, 0, img.width, img.height);
}
Module.onRuntimeInitialized = async _ => {
const api = {
version: Module.cwrap('version', 'number', []),
create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']),
destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']),
encode: Module.cwrap('encode', '', ['number', 'number', 'number', 'number']),
free_result: Module.cwrap('free_result', '', ['number']),
get_result_pointer: Module.cwrap('get_result_pointer', 'number', []),
get_result_size: Module.cwrap('get_result_size', 'number', []),
};
module.onRuntimeInitialized = async _ => {
console.log('Version:', module.version().toString(16));
const image = await loadImage('../example.png');
const p = api.create_buffer(image.width, image.height);
Module.HEAP8.set(image.data, p);
api.encode(p, image.width, image.height, 2);
const resultPointer = api.get_result_pointer();
const resultSize = api.get_result_size();
const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultSize);
const result = new Uint8Array(resultView);
api.free_result(resultPointer);
api.destroy_buffer(p);
const result = module.encode(image.data, image.width, image.height, {
quality: 75,
target_size: 0,
target_PSNR: 0,
method: 4,
sns_strength: 50,
filter_strength: 60,
filter_sharpness: 0,
filter_type: 1,
partitions: 0,
segments: 4,
pass: 1,
show_compressed: 0,
preprocessing: 0,
autofilter: 0,
partition_limit: 0,
alpha_compression: 1,
alpha_filtering: 1,
alpha_quality: 100,
lossless: 0,
exact: 0,
image_hint: 0,
emulate_jpeg_size: 0,
thread_level: 0,
low_memory: 0,
near_lossless: 100,
use_delta_palette: 0,
use_sharp_yuv: 0,
});
console.log('size', result.length);
const blob = new Blob([result], {type: 'image/webp'});
module.free_result();
const blob = new Blob([result], {type: 'image/jpeg'});
const blobURL = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = blobURL;

View File

@ -2,12 +2,12 @@
"name": "webp_enc",
"scripts": {
"install": "napa",
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"webp_enc\"' -I node_modules/libwebp -o ./webp_enc.js webp_enc.c node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c"
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
},
"napa": {
"libwebp": "webmproject/libwebp#v0.6.1"
"libwebp": "webmproject/libwebp#v1.0.2"
},
"devDependencies": {
"napa": "^3.0.0"
"napa": "3.0.0"
}
}

View File

@ -1,44 +0,0 @@
#include "emscripten.h"
#include "src/webp/encode.h"
#include <stdlib.h>
EMSCRIPTEN_KEEPALIVE
int version() {
return WebPGetEncoderVersion();
}
EMSCRIPTEN_KEEPALIVE
uint8_t* create_buffer(int width, int height) {
return malloc(width * height * 4 * sizeof(uint8_t));
}
EMSCRIPTEN_KEEPALIVE
void destroy_buffer(uint8_t* p) {
free(p);
}
int result[2];
EMSCRIPTEN_KEEPALIVE
void encode(uint8_t* img_in, int width, int height, float quality) {
uint8_t* img_out;
size_t size;
size = WebPEncodeRGBA(img_in, width, height, width * 4, quality, &img_out);
result[0] = (int)img_out;
result[1] = size;
}
EMSCRIPTEN_KEEPALIVE
void free_result() {
WebPFree(result[0]);
}
EMSCRIPTEN_KEEPALIVE
int get_result_pointer() {
return result[0];
}
EMSCRIPTEN_KEEPALIVE
int get_result_size() {
return result[1];
}

View File

@ -0,0 +1,96 @@
#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);
}

9
codecs/webp_enc/webp_enc.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import { EncodeOptions } from '../../src/codecs/webp/encoder-meta';
interface WebPModule extends EmscriptenWasm.Module {
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): WebPModule;

File diff suppressed because one or more lines are too long

Binary file not shown.

74
config/add-css-types.js Normal file
View File

@ -0,0 +1,74 @@
const DtsCreator = require('typed-css-modules');
const chokidar = require('chokidar');
const util = require('util');
const sass = require('node-sass');
const sassRender = util.promisify(sass.render);
async function sassToCss(path) {
const result = await sassRender({ file: path });
return result.css;
}
/**
* @typedef {Object} Opts
* @property {boolean} watch Watch for changes
*/
/**
* Create typing files for CSS & SCSS.
*
* @param {string[]} rootPaths Paths to search within
* @param {Opts} [opts={}] Options.
*/
function addCssTypes(rootPaths, opts = {}) {
return new Promise((resolve) => {
const { watch = false } = opts;
const paths = [];
const preReadyPromises = [];
let ready = false;
for (const rootPath of rootPaths) {
// Look for scss & css in each path.
paths.push(rootPath + '/**/*.scss');
paths.push(rootPath + '/**/*.css');
}
// For simplicity, the watcher is used even if we're not watching.
// If we're not watching, we stop the watcher after the initial files are found.
const watcher = chokidar.watch(paths, {
// Avoid processing already-processed files.
ignored: '*.d.*',
// Without this, travis and netlify builds never complete. I'm not sure why, but it might be
// related to https://github.com/paulmillr/chokidar/pull/758
persistent: watch,
});
function change(path) {
const promise = (async function() {
const creator = new DtsCreator({ camelCase: true });
const result = path.endsWith('.scss') ?
await creator.create(path, await sassToCss(path)) :
await creator.create(path);
await result.writeFile();
})();
if (!ready) preReadyPromises.push(promise);
}
watcher.on('change', change);
watcher.on('add', change);
// 'ready' is when events have been fired for file discovery.
watcher.on('ready', () => {
ready = true;
// Wait for the current set of processing to finish.
Promise.all(preReadyPromises).then(resolve);
// And if we're not watching, close the watcher.
if (!watch) watcher.close();
});
})
}
module.exports = addCssTypes;

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