Compare commits

..

105 Commits

Author SHA1 Message Date
Jamie
5f72c2ed74 Fix single threaded avif encoding (#1409)
* Fix single threaded encoding by compiling a separate copy of libsharpyuv
- This version will have threads turned off

* Add the fixed compilations of avif_enc.js and the wasm file

* ensure that ST and MT builds run sequentially

* update OUT_ENC_JS to be an order-only dependency

* use WEBP_BUILD_WEBP_JS=ON flag instead

* update compiled ST files

* refactor to use -DWEBP_USE_THREAD=OFF
2024-08-13 11:11:17 +01:00
Surma
19beb1a7ab Merge pull request #1396 from andrews05/oxipng9
Update oxipng to v9 [updated]
2024-03-18 15:54:13 +00:00
Andrew
e2514df601 Remove unused imports 2024-03-16 21:04:23 +13:00
Andrew
9db572e446 Rebuild oxipng 2024-03-16 19:05:59 +13:00
Andrew
42ef430cee Use oxipng raw api 2024-03-16 19:05:50 +13:00
Andrew
df7b622413 Build oxipng 2024-03-16 17:35:50 +13:00
Andrew
5649427670 Update wasm-pack 2024-03-16 17:35:50 +13:00
Andrew
1b24d2f3fa Update oxipng rust (nightly-buster-slim) 2024-03-16 17:35:50 +13:00
Andrew
e4322bcbc3 Update oxipng to v9 2024-03-16 17:35:50 +13:00
Aryan Pingle
e217740e53 Update libavif (#1381)
* Update libavif (v1.0.0-main)

* Update libavif for improved compression and speed
* v1.0.0 deprecates usage of min and max-quantizers; we use `quality` and `qualityAlpha` instead
* Renamed `maxSpeed` to `MAX_EFFORT` for better readability

* Update libavif (v1.0.1-main)

* Refactor variable names for clarity

* Update libaom (v3.7.0)

* Add checks for API return values

* Rename variables for readability

Changes `cqlevel` to `quality`, and `cqAlphaLevel` to `qualityAlpha`

* Minor patches in logic

* Minor patches in lossless calculation

* Add chroma subsampling options to AVIF

* Add skeleton for sharp downsampling param

* Try to use libsharpyuv

* Encoder working, decoder isnt

* Make sure sharpyuv is disabled for decoder

* Add AVIF_LOCAL flags for sharp yuv

* Get AVIF sharp YUV working

* Clean up AVIF makefiles

* AVIF: Make sharpyuv conditional on subsample

* AVIF: Flags to speed up sharpyuv build

* AVIF: Minor refactoring in enc.cpp

* AVIF: Minor refactoring & renaming

* AVIF: Use smart pointers to prevent memory leaks

* AVIF: Minor refactoring

* AVIF: Revert defaultoptions logic change

---------

Co-authored-by: Surma <surma@surma.dev>
Co-authored-by: Jake Archibald <jaffathecake@gmail.com>
2024-01-24 08:04:33 +00:00
Aryan Pingle
d87eff7645 Adding the Quite OK Image (QOI) Codec (#1384) 2023-10-20 09:28:59 +01:00
Adam Argyle
f374068fb2 check support and upgrade colors (#1356) 2023-09-29 14:03:28 +01:00
Adam Argyle
ecc715fe55 Merge pull request #1362 from Frank-Mayer/593
added snack bar inside noscript element
2023-04-12 14:31:49 -07:00
Frank Mayer
82caed4277 Merge branch 'dev' into 593 2023-04-12 23:13:11 +02:00
Adam Argyle
a7dff9475d Merge pull request #1348 from aryanpingle/keyboard-a11y
Better Keyboard A11y + Navigation
2023-04-12 09:11:16 -07:00
robo-mop
d168f7a447 Add focus animation to back button 2023-04-12 13:52:36 +05:30
robo-mop
edf9cb755e Add styles to save-import buttons 2023-04-12 13:52:36 +05:30
Frank-Mayer
a7503e69a2 better wording wor error message 2023-04-11 11:17:19 +02:00
Frank-Mayer
5a9733563e more information in the error message 2023-04-11 11:12:04 +02:00
robo-mop
2000e16ba2 Make text-fields match the dark theme 2023-04-08 22:35:55 +05:30
robo-mop
7dbe0a7714 Add focus effects to inputs
Provides better keyboard accessibility for:
* Checkboxes
* Range Inputs
* Copy-over Buttons
* Option-reveal Elements
Along with some minor design improvements
2023-04-08 22:35:55 +05:30
Frank-Mayer
25bc43e409 added snack bar inside noscript element 2023-04-08 18:27:29 +02:00
Adam Argyle
cee51bf355 Merge pull request #1359 from harsh26shah03/save-and-import-side-settings
Feat : Save and import side settings
2023-04-04 15:41:45 -07:00
Adam Argyle
8d6daf0fc4 Merge branch 'dev' into save-and-import-side-settings 2023-04-04 15:39:09 -07:00
Adam Argyle
61209d0b62 Merge pull request #1358 from harsh26shah03/file-size-update-sample-data
Fix : Sample File Size Unit
2023-04-04 15:38:10 -07:00
Adam Argyle
d0b4855022 Merge branch 'dev' into file-size-update-sample-data 2023-04-04 15:36:38 -07:00
Adam Argyle
6cb64a59ca Merge pull request #1355 from harsh26shah03/sample-image-data-styles
Feat : added hover animation to sample data
2023-04-04 15:32:50 -07:00
Harsh Shah
979fba0af1 Feat : Save and import side settings
There were requests from multiple users that
they use squoosh for compression but for each
iteration side settings resets to default
causing issues and there is no way to save and
import side settings.

There will be two buttons adjacent to copy-over

save side settings : This will save side encoder
and latest settings to localstorage of browser

import side settings : This will import side encoder
and latest settings from localstorage of browser and
replace the existing settings

Also if there are saved settings in locaStorage then
whenever user loads the app it will take that settings
and populate the side so user do not have to repeatedly
enter same settings for similar compression operation
subject to user has saved side settings

Update:1

Import settings button remains disabled if there
is nothing to import

Whenever the side setting is saved there will be
event fired and eventually listened to enable import
button

All 2 operations show notifications now

Import notification has undo option

Update : 2

Changed Icon SVGs
2023-04-04 22:35:09 +05:30
Harsh Shah
b1df3e1d54 Feat : Save and import side settings
There were requests from multiple users that
they use squoosh for compression but for each
iteration side settings resets to default
causing issues and there is no way to save and
import side settings.

There will be two buttons adjacent to copy-over

save side settings : This will save side encoder
and latest settings to localstorage of browser

import side settings : This will import side encoder
and latest settings from localstorage of browser and
replace the existing settings

Also if there are saved settings in locaStorage then
whenever user loads the app it will take that settings
and populate the side so user do not have to repeatedly
enter same settings for similar compression operation
subject to user has saved side settings

Update:1

Import settings button remains disabled if there
is nothing to import

Whenever the side setting is saved there will be
event fired and eventually listened to enable import
button

All 2 operations show notifications now

Import notification has undo option
2023-04-04 15:20:06 +05:30
Harsh Shah
4f6138d97d Fix : Sample File Size Unit
Sample data had size label showing wrong memory units

13k instead of 13KB
2.8mb instead of 2.8MB

small b corresponds to bits and this would change entire
meaning of file so fixed it
2023-04-04 11:39:57 +05:30
Harsh Shah
6b6e3724d2 Undoing this as separate PR is raised 2023-04-04 11:34:40 +05:30
Harsh Shah
8ac5e6f678 Merge branch 'GoogleChromeLabs:dev' into sample-image-data-styles 2023-04-04 11:30:38 +05:30
Adam Argyle
a930e8d928 Merge pull request #1353 from harsh26shah03/filename-in-result-dropdowns
Feat : Original image name (file name)
2023-04-03 09:08:57 -07:00
Harsh Shah
c814700cd2 Feat : changed unit of sample data and added hover animation 2023-04-03 15:00:19 +05:30
Harsh Shah
dfdf2a7f71 Feat : Original image name (file name)
Inside Compress tab Original image string
will be appended by file name.

In mobile view due to space constrain there
will be only <file name>
2023-04-02 23:11:17 +05:30
André R
cd336909fc Update libavif (v0.12-main) and AOM (3.6) for improved compression and speed (#1334)
* Update libavif and AOM (3.6) for improved compression and speed

* Minor fixes to package-lock done by NPM, also trigger new build

* Update AVIF version

---------

Co-authored-by: Jake Archibald <jaffathecake@gmail.com>
2023-03-10 10:24:15 +00:00
Aryan Pingle
a8bc48f94c Rotate copy-over-buttons correctly (#1335) 2023-03-02 11:42:52 +00:00
Jake Archibald
583117697e Ensure browser supports workers-in-workers (#1325)
Fixes #1324
2023-01-09 10:42:14 +00:00
Jake Archibald
13a185def2 Remove CLI / libsquoosh (#1321)
Unfortunately, due to a few people leaving the team, and staffing issues resulting from the current economic climate (ugh), I'm deprecating the CLI and libsquoosh parts of Squoosh. The web app will continue to be supported and improved. I know that sucks, but there simply isn't the time & people to work on this. If anyone from the community wants to fork it, you have my blessing.
2023-01-03 14:44:54 +00:00
jakearchibald
918c596cba Add no-longer-maintained message to cli and libsquoosh 2023-01-03 13:55:36 +00:00
jakearchibald
42594277fd Remove web codecs usage
It was decoding transparency incorrectly (multiplication wrong?), and I'd rather not have a different code path there for the sake of it
2022-12-15 14:56:51 +00:00
François Beaufort
97d13de273 Add desktop screenshots to web app manifest (#1283)
Co-authored-by: jakearchibald <jaffathecake@gmail.com>
2022-09-18 03:22:10 +01:00
jakearchibald
a1c3304c56 Fix issue with Chrome 105 and flexbox. Fixes #1281
https://bugs.chromium.org/p/chromium/issues/detail?id=1358807
2022-09-01 08:50:43 +01:00
Anthony Swierkosz
7a2fc917c1 Remove margin in Safari between buttons in button group (#1275) 2022-08-18 12:45:10 +01:00
Anthony Swierkosz
1c4233b5ae Add uniform spacing vertically and horizontally (#1277) 2022-08-18 12:44:11 +01:00
Anthony Swierkosz
4d67ec5a7b Fix misplaced border (#1273) 2022-08-15 08:38:36 +01:00
Jake Archibald
c24505230d Bump version due to breaking changes 2022-02-18 15:36:31 +00:00
Jake Archibald
2238d1abaf Update version 2022-02-16 16:23:33 +00:00
Ergün Erdoğmuş
65ea02627b Expose Typescript types in libSquoosh (#1142)
* Expose type declarations in libSquoosh npm package

* Add comment on why we remove the tsbuildinfo

* Fix PreprocessOptions type

Resize should require at least one of the width, height.
The other options are optional for all preprocessors

* Update libSquoosh README to reflect encode changes

I also removed requiring `await image.decoded` call before calling
preprocess or encode since they decode the image before the operation
2022-02-16 16:19:42 +00:00
Ziemowit Zabawa
18b53e2b8a JPEG XL: Add lossy Modular option (#1136)
* Improve .gitattributes

* Add disabled checkbox style

* Update Makefile

* Update jxl_enc.cpp

* add -O3 flag to skia compilation for optimization's sake

* Bump libjxl revision to 9f544641ec83f6abd9da598bdd08178ee8a003e0

Change use of EncodeFile from `EncodeFile(cparams, &io, &passes_enc_state, &bytes, /*aux=*/nullptr, pool_ptr)` to `EncodeFile(cparams, &io, &passes_enc_state, &bytes, /*cms=*/nullptr, /*aux=*/jxl::GetJxlCms(), pool_ptr)`

* JPEG XL: Add lossy Modular option

Co-authored-by: CanadianBaconBoi <beamconnor@gmail.com>
Co-authored-by: CanadianBaconBoi <bc.bacon.bits@gmail.com>
2022-01-21 12:42:27 +00:00
Surma
66ec763667 Merge pull request #1171 from TimvdLippe/fix-webassembly-instantiate 2021-10-20 15:42:50 +01:00
Surma
029eda7b37 Merge branch 'dev' into fix-webassembly-instantiate 2021-10-20 15:36:48 +01:00
Tim van der Lippe
e6810059ef Add warning for using multiple image pools
Instantiating and using multiple image pools is not intended and can
lead to memory problems. Instead, users should use a single pool and
reuse that pool across all image processing. Therefore, let's add
a warning in the README to specify call this out and avoid users
of running into issues.

Relates to #1065
2021-10-20 14:56:34 +01:00
Surma
4eba015009 Merge pull request #1165 from TimvdLippe/update-typescript 2021-10-20 13:25:54 +01:00
Surma
dd49a1f23d Merge branch 'dev' into update-typescript 2021-10-20 13:15:39 +01:00
Surma
5ecb99992c Merge pull request #1169 from TimvdLippe/update-prettier 2021-10-20 13:15:32 +01:00
Surma
d9c6ebe0a2 Merge branch 'dev' into update-prettier 2021-10-20 12:48:59 +01:00
Surma
fba67a7a18 Merge pull request #1170 from TimvdLippe/fix-husky 2021-10-20 12:47:01 +01:00
Tim van der Lippe
129b925098 Fix Husky pre-commit
By upgrading to version 7, we now ensure that NPM/Yarn will run
the `prepare` script and appropriately install Husky. This also
migrates us to the `pre-commit` hook as a separate file, rather
than as part of the `package.json` definition.
2021-10-20 12:44:12 +01:00
Tim van der Lippe
e23bc4d2e5 Update Prettier
Also manually run prettier on `src/` and `lib/` to ensure
consistent formatting.
2021-10-20 12:28:45 +01:00
Tim van der Lippe
f523a07f01 Update TypeScript and types packages
This pulls in TypeScript 4.4, which ships ResizeObserver in the DOM
types, as well as sets caught errors to `unknown`, requiring explicit
checks for `AbortError`.
2021-10-20 11:36:27 +01:00
Vignesh Raj
e3f840c6da Added Apple touch Icon for PWA (#1160) 2021-10-15 11:52:13 +01:00
Jake Archibald
cad09160b6 Reducing browser spinner time (#1157) 2021-09-20 13:49:53 +01:00
Surma
9663c23489 Merge pull request #1151 from ergunsh/improve-encode-types
Improve `encode` API and its types
2021-09-17 13:50:29 +01:00
ergunsh
95a1b35c91 Update encodedWith to contain resolved values
We already await the promises that we set on the `encodedWith` instead of setting already
resolved promises to `encodedWith` we can set the resolved values

So, the users can use like
`const { mozjpeg: { binary } } = await image.encode({ mozjpeg })` or
they can first run
`await image.encode({ mozjpeg })` and then
`image.encodedWith.mozjpeg.binary`
2021-09-10 15:18:14 +02:00
ergunsh
914cdea41d Return encode result from Image.encode calls
Before this, there were one way to use the API:
call `await image.encode({ mozjpeg: {} })`
then use `encodedWith` by asserting that `mozjpeg` property exists on it

After adding return value to encode, people
will be able to use it like
`const { mozjpeg } = await image.encode({ mozjpeg: {} });`
which provides better type safety
2021-09-10 14:45:20 +02:00
ergunsh
6bfce29af6 Improve typing of Image.encode
Instead of returning `any` we're now returning the whole object.

Still from typing perspective, the API is not that
great since we don't have any type relation
between `encode` calls and `encodedWith` property. Maybe we can think about
returning directly from `encode` call
with the returned object having properties
that is supplied in `encode` calls
2021-09-10 14:08:21 +02:00
Surma
64cad1cc23 Merge pull request #1123 from styfle/load-file-async
Reduce `@squoosh/lib` Node.js API usage (make it run on the web)
2021-09-08 22:30:53 +01:00
Steven
87f25d909b Merge branch 'dev' into load-file-async 2021-09-08 17:04:50 -04:00
Steven
bdfdaf53af Remove unused readme link per atjn
Co-authored-by: Anton <dev@atjn.dk>
2021-09-08 17:04:46 -04:00
Surma
1ab9e8b3ab Merge pull request #1141 from ergunsh/improve-exposed-types 2021-09-08 17:57:46 +01:00
Ergün Erdoğmuş
2718077d3d Merge branch 'dev' into improve-exposed-types 2021-09-08 19:48:01 +03:00
Jake Archibald
255dfa434a Update pointer-tracker (#1147) 2021-09-07 14:43:19 +01:00
François Beaufort
0bef05bcd4 Remove origin trial header 2021-09-06 15:00:48 +01:00
ergunsh
c4bc369c6b Fix typo in triangle 2021-09-03 15:03:28 +03:00
ergunsh
68ce8f420d Improve encode parameter typing 2021-09-03 14:54:08 +03:00
ergunsh
27f103fee5 Improve preprocess parameter type 2021-09-03 11:53:52 +03:00
Steven
c21d3714a8 Fix link in readme 2021-09-02 16:38:22 -04:00
Steven
3ea0d88c4f Apply suggestions from atjn
Co-authored-by: Anton <dev@atjn.dk>
2021-09-02 16:36:37 -04:00
Surma
00cfdafdf3 Merge pull request #1138 from jcao219/fix-windows-path
Use pathify to calculate absolute paths for cross-platform compatibility
2021-08-31 13:34:28 +01:00
Jimmy Cao
92f52319da Use pathify to calculate absolute paths for cross-platform compatibility 2021-08-31 00:18:21 -07:00
Jake Archibald
023304803f JPEG-XL: Better 'effort' and adding noise synth (#1039) 2021-08-27 14:18:54 +01:00
Vishal
6b08cd2355 Aliasing toggle button (#1132) 2021-08-26 16:44:20 +01:00
Jake Archibald
db1a5138e6 Fix pinch zoom on iOS (#1133) 2021-08-26 15:59:42 +01:00
Jake Archibald
a547491146 Maintain DC_SCAN_OPT_MODE if subsampling is > 2. Fixes #1129 (#1130) 2021-08-26 14:29:13 +01:00
Jake Archibald
6e427f9208 The observer is null if user prefers reduced motion
Turns out TypeScript is there for a reason and shouldn't be bypassed. Fixes #1135
2021-08-25 14:10:57 +01:00
Jake Archibald
0d35fbd349 Fix horizontal scroll on option elements on mobile (#1134) 2021-08-25 09:25:09 +01:00
Mike DelGaudio
4e901c714c [RFC] Add Three Homepage Sections (#1112) 2021-08-25 09:08:22 +01:00
Adam Burgess
b74788e036 Stable mousewheel scrolling, one wheel up + one wheel down = no change (#1131) 2021-08-24 14:52:25 +01:00
Vishal
14c3d190e9 Max cap on scale #905 (#1128) 2021-08-23 13:27:17 +01:00
Steven
202d0bc088 Generalize file to ArrayLike<number> 2021-08-20 18:48:30 -04:00
Steven
bdb5b16372 Remove Buffer from decodeFile() 2021-08-20 18:36:23 -04:00
Steven
30140c2b7a Fix CLI bug 2021-08-20 18:35:29 -04:00
Steven
10996cdbca Add missing import 2021-08-20 16:08:01 -04:00
Steven
e5806507d4 Remove Node.js API surface in libsquoosh 2021-08-20 15:11:14 -04:00
Steven
1c5b44f9a1 Add loadFile parameter to ImagePool 2021-08-16 16:51:23 -04:00
Surma
eeaa19589e Merge pull request #1120 from veluca93/jxl_05
Bump JPEG XL to v0.5.
2021-08-14 09:23:04 +01:00
Luca Versari
35b8c56f1a Bump JPEG XL to v0.5. 2021-08-13 23:27:44 +02:00
Surma
816d1f92fd Merge pull request #1110 from styfle/libsquoosh-ts-remaining 2021-08-10 12:38:11 +01:00
Steven
4091f2efec Remove unused export 2021-08-06 13:20:14 -04:00
Steven
821d14c6ab Merge branch 'dev' into libsquoosh-ts-remaining 2021-08-06 13:02:46 -04:00
Steven
a72ca46531 Move as to input param instead of return type 2021-08-06 12:49:17 -04:00
ergunsh
fafcf97f0c Update code for the review comments
* Make decode module return value `ImageData`
* Fix global definition of ImageData
* Use concrete Encoder types for encode functions
* Use ArrayBufferView in FileLike instead of using a similar type
* Throw error when the `encode` functions
return null
* Use generic types for WorkerPool
* Fix `encode` function typing
in `index.ts`
* Remove ts-ignore for web-streams-polyfill
and handle nulls for TransformStream
* Fix rollup entry point (now we need to have
`index.ts` instead of `index.js`)
2021-08-06 16:05:14 +03:00
Steven
de4eb9c8f7 Add encode() and decode() types 2021-07-26 23:22:28 -04:00
Steven
16a53caa48 Convert remaining JS to TS in libSquoosh 2021-07-26 22:37:00 -04:00
212 changed files with 2053 additions and 8192 deletions

4
.gitattributes vendored
View File

@@ -1,2 +1,2 @@
/codecs/**/*.js linguist-generated=true /codecs/**/*.js linguist-generated -diff
/codecs/*/pkg*/*.d.ts linguist-generated=true /codecs/*/pkg*/*.d.ts linguist-generated

1
.husky/pre-commit Executable file
View File

@@ -0,0 +1 @@
npx lint-staged

View File

@@ -2,10 +2,6 @@
[Squoosh] is an image compression web app that reduces image sizes through numerous formats. [Squoosh] is an image compression web app that reduces image sizes through numerous formats.
# API & CLI
Squoosh has [an API](https://github.com/GoogleChromeLabs/squoosh/tree/dev/libsquoosh) and [a CLI](https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli) to compress many images at once.
# Privacy # Privacy
Squoosh does not send your image to a server. All image compression processes locally. Squoosh does not send your image to a server. All image compression processes locally.

3
cli/.gitignore vendored
View File

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

View File

@@ -1 +0,0 @@
node_modules

View File

View File

@@ -1,59 +0,0 @@
# Squoosh CLI
Squoosh CLI is an _experimental_ way to run all the codecs you know from the [Squoosh] web app on your command line using WebAssembly. The Squoosh CLI uses a worker pool to parallelize processing images. This way you can apply the same codec to many images at once.
Squoosh CLI is currently not the fastest image compression tool in town and doesnt aim to be. It is, however, fast enough to compress many images sufficiently quick at once.
## Installation
The Squoosh CLI can be used straight from the command line without installing using `npx`:
```
$ npx @squoosh/cli <options...>
```
Of course, you can also install the Squoosh CLI:
```
$ npm i -g @squoosh/cli
$ squoosh-cli <options...>
```
## Usage
```
Usage: squoosh-cli [options] <files...>
Options:
-V, --version output the version number
-d, --output-dir <dir> Output directory (default: ".")
-s, --suffix <suffix> Append suffix to output files (default: "")
--max-optimizer-rounds <rounds> Maximum number of compressions to use for auto optimizations (default: "6")
--optimizer-butteraugli-target <butteraugli distance> Target Butteraugli distance for auto optimizer (default: "1.4")
--resize [config] Resize the image before compressing
--quant [config] Reduce the number of colors used (aka. paletting)
--rotate [config] Rotate image
--mozjpeg [config] Use MozJPEG to generate a .jpg file with the given configuration
--webp [config] Use WebP to generate a .webp file with the given configuration
--avif [config] Use AVIF to generate a .avif file with the given configuration
--jxl [config] Use JPEG-XL to generate a .jxl file with the given configuration
--wp2 [config] Use WebP2 to generate a .wp2 file with the given configuration
--oxipng [config] Use OxiPNG to generate a .png file with the given configuration
-h, --help display help for command
```
The default values for each `config` option can be found in the [`codecs.ts`][codecs.ts] file under `defaultEncoderOptions`. Every unspecified value will use the default value specified here. _Better documentation is needed here._
## Auto optimizer
Squoosh CLI has an _experimental_ auto optimizer that compresses an image as much as possible, trying to hit a specific [Butteraugli] target value. The higher the Butteraugli target value, the more artifacts can be introduced.
You can make use of the auto optimizer by using “auto” as the config object.
```
$ npx @squoosh/cli --wp2 auto test.png
```
[squoosh]: https://squoosh.app
[codecs.ts]: https://github.com/GoogleChromeLabs/squoosh/blob/dev/libsquoosh/src/codecs.ts
[butteraugli]: https://github.com/google/butteraugli

613
cli/package-lock.json generated
View File

@@ -1,613 +0,0 @@
{
"name": "@squoosh/cli",
"version": "0.7.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@squoosh/cli",
"version": "0.7.2",
"license": "Apache-2.0",
"dependencies": {
"@squoosh/lib": "^0.4.0",
"commander": "^7.2.0",
"json5": "^2.2.0",
"kleur": "^4.1.4",
"ora": "^5.4.0"
},
"bin": {
"cli": "src/index.js",
"squoosh-cli": "src/index.js"
},
"engines": {
"node": " ^12.20.2 || ^14.13.1 || ^16.0.0 "
}
},
"node_modules/@squoosh/lib": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@squoosh/lib/-/lib-0.4.0.tgz",
"integrity": "sha512-O1LyugWLZjMI4JZeZMA5vzfhfPjfMZXH5/HmVkRagP8B70wH3uoR7tjxfGNdSavey357MwL8YJDxbGwBBdHp7Q==",
"dependencies": {
"wasm-feature-detect": "^1.2.11",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": " ^12.5.0 || ^14.0.0 || ^16.0.0 "
}
},
"node_modules/ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/chalk": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"dependencies": {
"restore-cursor": "^3.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/cli-spinners": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz",
"integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==",
"engines": {
"node": ">=6"
}
},
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"engines": {
"node": ">= 10"
}
},
"node_modules/defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"dependencies": {
"clone": "^1.0.2"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"engines": {
"node": ">=10"
}
},
"node_modules/json5": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"dependencies": {
"minimist": "^1.2.5"
},
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/kleur": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
"integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==",
"engines": {
"node": ">=6"
}
},
"node_modules/log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dependencies": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"engines": {
"node": ">=6"
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"node_modules/onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dependencies": {
"mimic-fn": "^2.1.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/ora": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz",
"integrity": "sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg==",
"dependencies": {
"bl": "^4.1.0",
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-spinners": "^2.5.0",
"is-interactive": "^1.0.0",
"is-unicode-supported": "^0.1.0",
"log-symbols": "^4.1.0",
"strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dependencies": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"node_modules/signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"dependencies": {
"ansi-regex": "^5.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"node_modules/wasm-feature-detect": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.2.11.tgz",
"integrity": "sha512-HUqwaodrQGaZgz1lZaNioIkog9tkeEJjrM3eq4aUL04whXOVDRc/o2EGb/8kV0QX411iAYWEqq7fMBmJ6dKS6w=="
},
"node_modules/wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
"dependencies": {
"defaults": "^1.0.3"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz",
"integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==",
"engines": {
"node": ">= 8"
}
}
},
"dependencies": {
"@squoosh/lib": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@squoosh/lib/-/lib-0.4.0.tgz",
"integrity": "sha512-O1LyugWLZjMI4JZeZMA5vzfhfPjfMZXH5/HmVkRagP8B70wH3uoR7tjxfGNdSavey357MwL8YJDxbGwBBdHp7Q==",
"requires": {
"wasm-feature-detect": "^1.2.11",
"web-streams-polyfill": "^3.0.3"
}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"requires": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"chalk": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"requires": {
"restore-cursor": "^3.1.0"
}
},
"cli-spinners": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz",
"integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q=="
},
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"commander": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
},
"defaults": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
"integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=",
"requires": {
"clone": "^1.0.2"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-interactive": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
},
"is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
},
"json5": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"requires": {
"minimist": "^1.2.5"
}
},
"kleur": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz",
"integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA=="
},
"log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"requires": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
}
},
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"onetime": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"requires": {
"mimic-fn": "^2.1.0"
}
},
"ora": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz",
"integrity": "sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg==",
"requires": {
"bl": "^4.1.0",
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-spinners": "^2.5.0",
"is-interactive": "^1.0.0",
"is-unicode-supported": "^0.1.0",
"log-symbols": "^4.1.0",
"strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
},
"restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"requires": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"signal-exit": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"requires": {
"safe-buffer": "~5.2.0"
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"requires": {
"ansi-regex": "^5.0.0"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "^4.0.0"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"wasm-feature-detect": {
"version": "1.2.11",
"resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.2.11.tgz",
"integrity": "sha512-HUqwaodrQGaZgz1lZaNioIkog9tkeEJjrM3eq4aUL04whXOVDRc/o2EGb/8kV0QX411iAYWEqq7fMBmJ6dKS6w=="
},
"wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
"integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=",
"requires": {
"defaults": "^1.0.3"
}
},
"web-streams-polyfill": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz",
"integrity": "sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA=="
}
}
}

View File

@@ -1,32 +0,0 @@
{
"name": "@squoosh/cli",
"version": "0.7.2",
"description": "A CLI for Squoosh",
"public": true,
"type": "module",
"homepage": "https://github.com/GoogleChromeLabs/squoosh",
"repository": {
"type": "git",
"url": "https://github.com/GoogleChromeLabs/squoosh.git"
},
"bin": {
"squoosh-cli": "src/index.js",
"@squoosh/cli": "src/index.js"
},
"files": [
"/src/index.js"
],
"keywords": [],
"author": "Google Chrome Developers <chromium-dev@google.com>",
"license": "Apache-2.0",
"engines": {
"node": " ^12.20.2 || ^14.13.1 || ^16.0.0 "
},
"dependencies": {
"@squoosh/lib": "^0.4.0",
"commander": "^7.2.0",
"json5": "^2.2.0",
"kleur": "^4.1.4",
"ora": "^5.4.0"
}
}

View File

@@ -1,232 +0,0 @@
#!/usr/bin/env node
import { program } from 'commander/esm.mjs';
import JSON5 from 'json5';
import path from 'path';
import { promises as fsp } from 'fs';
import ora from 'ora';
import kleur from 'kleur';
import { ImagePool, preprocessors, encoders } from '@squoosh/lib';
function clamp(v, min, max) {
if (v < min) return min;
if (v > max) return max;
return v;
}
const suffix = ['B', 'KB', 'MB'];
function prettyPrintSize(size) {
const base = Math.floor(Math.log2(size) / 10);
const index = clamp(base, 0, 2);
return (size / 2 ** (10 * index)).toFixed(2) + suffix[index];
}
function progressTracker(results) {
const spinner = ora();
const tracker = {};
tracker.spinner = spinner;
tracker.progressOffset = 0;
tracker.totalOffset = 0;
let status = '';
tracker.setStatus = (text) => {
status = text || '';
update();
};
let progress = '';
tracker.setProgress = (done, total) => {
spinner.prefixText = kleur.dim(`${done}/${total}`);
const completeness =
(tracker.progressOffset + done) / (tracker.totalOffset + total);
progress = kleur.cyan(
`${'▨'.repeat((completeness * 10) | 0).padEnd(10, '╌')}`,
);
update();
};
function update() {
spinner.text = progress + kleur.bold(status) + getResultsText();
}
tracker.finish = (text) => {
spinner.succeed(kleur.bold(text) + getResultsText());
};
function getResultsText() {
let out = '';
for (const result of results.values()) {
out += `\n ${kleur.cyan(result.file)}: ${prettyPrintSize(result.size)}`;
for (const { outputFile, size: outputSize, infoText } of result.outputs) {
out += `\n ${kleur.dim('└')} ${kleur.cyan(
outputFile.padEnd(5),
)}${prettyPrintSize(outputSize)}`;
const percent = ((outputSize / result.size) * 100).toPrecision(3);
out += ` (${kleur[outputSize > result.size ? 'red' : 'green'](
percent + '%',
)})`;
if (infoText) out += kleur.yellow(infoText);
}
}
return out || '\n';
}
spinner.start();
return tracker;
}
async function getInputFiles(paths) {
const validFiles = [];
for (const inputPath of paths) {
const files = (await fsp.lstat(inputPath)).isDirectory()
? (await fsp.readdir(inputPath, {withFileTypes: true})).filter(dirent => dirent.isFile()).map(dirent => path.join(inputPath, dirent.name))
: [inputPath];
for (const file of files) {
try {
await fsp.stat(file);
} catch (err) {
if (err.code === 'ENOENT') {
console.warn(
`Warning: Input file does not exist: ${path.resolve(file)}`,
);
continue;
} else {
throw err;
}
}
validFiles.push(file);
}
}
return validFiles;
}
async function processFiles(files) {
files = await getInputFiles(files);
const imagePool = new ImagePool();
const results = new Map();
const progress = progressTracker(results);
progress.setStatus('Decoding...');
progress.totalOffset = files.length;
progress.setProgress(0, files.length);
// Create output directory
await fsp.mkdir(program.opts().outputDir, { recursive: true });
let decoded = 0;
let decodedFiles = await Promise.all(
files.map(async (file) => {
const image = imagePool.ingestImage(file);
await image.decoded;
results.set(image, {
file,
size: (await image.decoded).size,
outputs: [],
});
progress.setProgress(++decoded, files.length);
return image;
}),
);
const preprocessOptions = {};
for (const preprocessorName of Object.keys(preprocessors)) {
if (!program.opts()[preprocessorName]) {
continue;
}
preprocessOptions[preprocessorName] = JSON5.parse(
program.opts()[preprocessorName],
);
}
for (const image of decodedFiles) {
image.preprocess(preprocessOptions);
}
await Promise.all(decodedFiles.map((image) => image.decoded));
progress.progressOffset = decoded;
progress.setStatus(
'Encoding ' + kleur.dim(`(${imagePool.workerPool.numWorkers} threads)`),
);
progress.setProgress(0, files.length);
const jobs = [];
let jobsStarted = 0;
let jobsFinished = 0;
for (const image of decodedFiles) {
const originalFile = results.get(image).file;
const encodeOptions = {
optimizerButteraugliTarget: Number(
program.opts().optimizerButteraugliTarget,
),
maxOptimizerRounds: Number(program.opts().maxOptimizerRounds),
};
for (const encName of Object.keys(encoders)) {
if (!program.opts()[encName]) {
continue;
}
const encParam = program.opts()[encName];
const encConfig =
encParam.toLowerCase() === 'auto' ? 'auto' : JSON5.parse(encParam);
encodeOptions[encName] = encConfig;
}
jobsStarted++;
const job = image.encode(encodeOptions).then(async () => {
jobsFinished++;
const outputPath = path.join(
program.opts().outputDir,
path.basename(originalFile, path.extname(originalFile)) +
program.opts().suffix
);
for (const output of Object.values(image.encodedWith)) {
const outputFile = `${outputPath}.${(await output).extension}`;
await fsp.writeFile(outputFile, (await output).binary);
results
.get(image)
.outputs.push(Object.assign(await output, { outputFile }));
}
progress.setProgress(jobsFinished, jobsStarted);
});
jobs.push(job);
}
// update the progress to account for multi-format
progress.setProgress(jobsFinished, jobsStarted);
// Wait for all jobs to finish
await Promise.all(jobs);
await imagePool.close();
progress.finish('Squoosh results:');
}
program
.name('squoosh-cli')
.arguments('<files...>')
.option('-d, --output-dir <dir>', 'Output directory', '.')
.option('-s, --suffix <suffix>', 'Append suffix to output files', '')
.option(
'--max-optimizer-rounds <rounds>',
'Maximum number of compressions to use for auto optimizations',
'6',
)
.option(
'--optimizer-butteraugli-target <butteraugli distance>',
'Target Butteraugli distance for auto optimizer',
'1.4',
)
.action(processFiles);
// Create a CLI option for each supported preprocessor
for (const [key, value] of Object.entries(preprocessors)) {
program.option(`--${key} [config]`, value.description);
}
// Create a CLI option for each supported encoder
for (const [key, value] of Object.entries(encoders)) {
program.option(
`--${key} [config]`,
`Use ${value.name} to generate a .${value.extension} file with the given configuration`,
);
}
program.parse(process.argv);

View File

@@ -14,6 +14,7 @@
// for comlink // for comlink
"src/features/**/worker/**/*", "src/features/**/worker/**/*",
"src/features-worker/**/*", "src/features-worker/**/*",
"src/features/worker-utils/**/*" "src/features/worker-utils/**/*",
"src/worker-shared/**/*"
] ]
} }

View File

@@ -1,9 +1,9 @@
# libavif and libaom versions are from # using libavif from https://github.com/AOMediaCodec/libavif
# https://docs.google.com/document/d/1wEEA5rRU7wT54k41u3qyZIZHDCJArIMzLuzsrLAwaK8/edit LIBAVIF_URL = https://github.com/AOMediaCodec/libavif/archive/refs/tags/v1.0.1.tar.gz
CODEC_URL = https://github.com/AOMediaCodec/libavif/archive/1c39e772c2c0d687691dd4b589a12c323f5f767d.tar.gz LIBAVIF_PACKAGE = node_modules/libavif.tar.gz
CODEC_PACKAGE = node_modules/libavif.tar.gz
LIBAOM_URL = https://aomedia.googlesource.com/aom/+archive/v3.1.0.tar.gz # using libaom from https://aomedia.googlesource.com/aom
LIBAOM_URL = https://aomedia.googlesource.com/aom/+archive/v3.7.0.tar.gz
LIBAOM_PACKAGE = node_modules/libaom.tar.gz LIBAOM_PACKAGE = node_modules/libaom.tar.gz
export CODEC_DIR = node_modules/libavif export CODEC_DIR = node_modules/libavif
@@ -11,7 +11,14 @@ export BUILD_DIR = node_modules/build
export LIBAOM_DIR = node_modules/libaom export LIBAOM_DIR = node_modules/libaom
override CFLAGS += "-Wno-unused-macros" override CFLAGS += "-Wno-unused-macros"
export
# We must build libsharpyuv from a specific libwebp commit
# See libavif/ext/libsharpyuv.cmd for more detail
LIBWEBP_URL_WITH_SHARPYUV = https://chromium.googlesource.com/webm/libwebp/+archive/e2c85878f6a33f29948b43d3492d9cdaf801aa54.tar.gz
LIBWEBP_DIR := $(CODEC_DIR)/ext/libwebp
LIBSHARPYUV_ST := $(LIBWEBP_DIR)/build_st/libsharpyuv.a
LIBSHARPYUV_MT := $(LIBWEBP_DIR)/build_mt/libsharpyuv.a
export LIBSHARPYUV := $(LIBWEBP_DIR)/build/libsharpyuv.a
OUT_ENC_JS = enc/avif_enc.js OUT_ENC_JS = enc/avif_enc.js
OUT_NODE_ENC_JS = enc/avif_node_enc.js OUT_NODE_ENC_JS = enc/avif_node_enc.js
@@ -28,10 +35,11 @@ HELPER_MAKEFLAGS := -f helper.Makefile
.PHONY: all clean .PHONY: all clean
all: $(OUT_ENC_JS) $(OUT_DEC_JS) $(OUT_ENC_MT_JS) $(OUT_NODE_ENC_JS) $(OUT_NODE_ENC_MT_JS) $(OUT_NODE_DEC_JS) all: $(OUT_ENC_JS) $(OUT_DEC_JS) $(OUT_ENC_MT_JS)
$(OUT_NODE_ENC_JS) $(OUT_NODE_ENC_MT_JS): ENVIRONMENT=node # ST-Encoding
$(OUT_NODE_ENC_JS) $(OUT_ENC_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt $(OUT_ENC_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt $(LIBSHARPYUV_ST)
mkdir -p $(LIBWEBP_DIR)/build && cp $(LIBSHARPYUV_ST) $(LIBSHARPYUV)
$(MAKE) \ $(MAKE) \
$(HELPER_MAKEFLAGS) \ $(HELPER_MAKEFLAGS) \
OUT_JS=$@ \ OUT_JS=$@ \
@@ -42,9 +50,12 @@ $(OUT_NODE_ENC_JS) $(OUT_ENC_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(L
-DCONFIG_AV1_HIGHBITDEPTH=0 \ -DCONFIG_AV1_HIGHBITDEPTH=0 \
" \ " \
ENVIRONMENT=$(ENVIRONMENT) \ ENVIRONMENT=$(ENVIRONMENT) \
LIBAVIF_FLAGS="-DAVIF_CODEC_AOM_DECODE=0" LIBAVIF_FLAGS="-DAVIF_CODEC_AOM_DECODE=0 -DAVIF_LOCAL_LIBSHARPYUV=ON"
$(OUT_ENC_MT_JS) $(OUT_NODE_ENC_MT_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt # MT-Encoding
# We need to run the ST and MT tasks sequentially to avoid conflicts with the copy of libsharpyuv in the build directory
$(OUT_ENC_MT_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt $(LIBSHARPYUV_MT) | $(OUT_ENC_JS)
mkdir -p $(LIBWEBP_DIR)/build && cp $(LIBSHARPYUV_MT) $(LIBSHARPYUV)
$(MAKE) \ $(MAKE) \
$(HELPER_MAKEFLAGS) \ $(HELPER_MAKEFLAGS) \
OUT_JS=$@ \ OUT_JS=$@ \
@@ -54,11 +65,11 @@ $(OUT_ENC_MT_JS) $(OUT_NODE_ENC_MT_JS): $(OUT_ENC_CPP) $(CODEC_DIR)/CMakeLists.t
-DCONFIG_AV1_HIGHBITDEPTH=0 \ -DCONFIG_AV1_HIGHBITDEPTH=0 \
" \ " \
ENVIRONMENT=$(ENVIRONMENT) \ ENVIRONMENT=$(ENVIRONMENT) \
LIBAVIF_FLAGS="-DAVIF_CODEC_AOM_DECODE=0" \ LIBAVIF_FLAGS="-DAVIF_CODEC_AOM_DECODE=0 -DAVIF_LOCAL_LIBSHARPYUV=ON" \
OUT_FLAGS="-pthread" OUT_FLAGS="-pthread"
$(OUT_NODE_DEC_JS): ENVIRONMENT=node # Decoding
$(OUT_NODE_DEC_JS) $(OUT_DEC_JS): $(OUT_DEC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt $(OUT_DEC_JS): $(OUT_DEC_CPP) $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_DIR)/CMakeLists.txt
$(MAKE) \ $(MAKE) \
$(HELPER_MAKEFLAGS) \ $(HELPER_MAKEFLAGS) \
OUT_JS=$@ \ OUT_JS=$@ \
@@ -70,22 +81,77 @@ $(OUT_NODE_DEC_JS) $(OUT_DEC_JS): $(OUT_DEC_CPP) $(CODEC_DIR)/CMakeLists.txt $(L
ENVIRONMENT=$(ENVIRONMENT) \ ENVIRONMENT=$(ENVIRONMENT) \
LIBAVIF_FLAGS="-DAVIF_CODEC_AOM_ENCODE=0" LIBAVIF_FLAGS="-DAVIF_CODEC_AOM_ENCODE=0"
$(CODEC_PACKAGE): # LIBAOM EXTRACTION SECTION
mkdir -p $(@D)
curl -sL $(CODEC_URL) -o $@
# Download the libaom tarball
$(LIBAOM_PACKAGE): $(LIBAOM_PACKAGE):
mkdir -p $(@D) mkdir -p $(@D)
curl -sL $(LIBAOM_URL) -o $@ curl -sL $(LIBAOM_URL) -o $@
$(CODEC_DIR)/CMakeLists.txt: $(CODEC_PACKAGE) # Extract libaom from the tarball
mkdir -p $(@D)
tar xzm --strip 1 -C $(@D) -f $(CODEC_PACKAGE)
$(LIBAOM_DIR)/CMakeLists.txt: $(LIBAOM_PACKAGE) $(LIBAOM_DIR)/CMakeLists.txt: $(LIBAOM_PACKAGE)
mkdir -p $(@D) mkdir -p $(@D)
tar xzm -C $(@D) -f $(LIBAOM_PACKAGE) tar xzm -C $(@D) -f $(LIBAOM_PACKAGE)
# LIBAVIF EXTRACTION SECTION
# Download the libavif tarball
$(LIBAVIF_PACKAGE):
mkdir -p $(@D)
curl -sL $(LIBAVIF_URL) -o $@
# Extract libavif from the tarball
$(CODEC_DIR)/CMakeLists.txt: $(LIBAVIF_PACKAGE)
mkdir -p $(@D)
tar xzm --strip 1 -C $(@D) -f $(LIBAVIF_PACKAGE)
# Create libavif/ext/libwebp
$(LIBWEBP_DIR)/CMakeLists.txt: $(CODEC_DIR)/CMakeLists.txt
mkdir -p $(LIBWEBP_DIR)
curl -sL $(LIBWEBP_URL_WITH_SHARPYUV) \
| tar xzm -C $(LIBWEBP_DIR)
# Make libsharpyuv.a for ST-Encoding
$(LIBSHARPYUV_ST): $(LIBWEBP_DIR)/CMakeLists.txt
mkdir -p $(@D)
emcmake cmake \
-DWEBP_USE_THREAD=OFF \
-DWEBP_BUILD_ANIM_UTILS=OFF \
-DWEBP_BUILD_CWEBP=OFF \
-DWEBP_BUILD_DWEBP=OFF \
-DWEBP_BUILD_GIF2WEBP=OFF \
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_VWEBP=OFF \
-DWEBP_BUILD_WEBPINFO=OFF \
-DWEBP_BUILD_LIBWEBPMUX=OFF \
-DWEBP_BUILD_WEBPMUX=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=Release \
-S $(LIBWEBP_DIR) \
-B $(@D)
$(MAKE) -C $(@D) sharpyuv
# Make libsharpyuv.a for MT-Encoding
$(LIBSHARPYUV_MT): $(LIBWEBP_DIR)/CMakeLists.txt
mkdir -p $(@D)
emcmake cmake \
-DWEBP_BUILD_ANIM_UTILS=OFF \
-DWEBP_BUILD_CWEBP=OFF \
-DWEBP_BUILD_DWEBP=OFF \
-DWEBP_BUILD_GIF2WEBP=OFF \
-DWEBP_BUILD_IMG2WEBP=OFF \
-DWEBP_BUILD_VWEBP=OFF \
-DWEBP_BUILD_WEBPINFO=OFF \
-DWEBP_BUILD_LIBWEBPMUX=OFF \
-DWEBP_BUILD_WEBPMUX=OFF \
-DWEBP_BUILD_EXTRAS=OFF \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=Release \
-S $(LIBWEBP_DIR) \
-B $(@D)
$(MAKE) -C $(@D) sharpyuv
clean: clean:
$(MAKE) $(HELPER_MAKEFLAGS) OUT_JS=$(OUT_ENC_JS) clean $(MAKE) $(HELPER_MAKEFLAGS) OUT_JS=$(OUT_ENC_JS) clean
$(MAKE) $(HELPER_MAKEFLAGS) OUT_JS=$(OUT_ENC_MT_JS) clean $(MAKE) $(HELPER_MAKEFLAGS) OUT_JS=$(OUT_ENC_MT_JS) clean

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -3,15 +3,27 @@
#include <emscripten/val.h> #include <emscripten/val.h>
#include "avif/avif.h" #include "avif/avif.h"
#include <memory>
#include <string>
#define RETURN_NULL_IF(expression) \
do { \
if (expression) \
return val::null(); \
} while (false)
using namespace emscripten; using namespace emscripten;
using AvifImagePtr = std::unique_ptr<avifImage, decltype(&avifImageDestroy)>;
using AvifEncoderPtr = std::unique_ptr<avifEncoder, decltype(&avifEncoderDestroy)>;
struct AvifOptions { struct AvifOptions {
// [0 - 63] // [0 - 100]
// 0 = lossless // 0 = worst quality
// 63 = worst quality // 100 = lossless
int cqLevel; int quality;
// As above, but -1 means 'use cqLevel' // As above, but -1 means 'use quality'
int cqAlphaLevel; int qualityAlpha;
// [0 - 6] // [0 - 6]
// Creates 2^n tiles in that dimension // Creates 2^n tiles in that dimension
int tileRowsLog2; int tileRowsLog2;
@@ -35,12 +47,15 @@ struct AvifOptions {
int tune; int tune;
// 0-50 // 0-50
int denoiseLevel; int denoiseLevel;
// toggles AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV
bool enableSharpYUV;
}; };
thread_local const val Uint8Array = val::global("Uint8Array"); thread_local const val Uint8Array = val::global("Uint8Array");
val encode(std::string buffer, int width, int height, AvifOptions options) { val encode(std::string buffer, int width, int height, AvifOptions options) {
avifRWData output = AVIF_DATA_EMPTY; avifResult status; // To check the return status for avif API's
int depth = 8; int depth = 8;
avifPixelFormat format; avifPixelFormat format;
switch (options.subsample) { switch (options.subsample) {
@@ -58,11 +73,13 @@ val encode(std::string buffer, int width, int height, AvifOptions options) {
break; break;
} }
bool lossless = options.cqLevel == AVIF_QUANTIZER_LOSSLESS && bool lossless = options.quality == AVIF_QUALITY_LOSSLESS &&
options.cqAlphaLevel <= AVIF_QUANTIZER_LOSSLESS && (options.qualityAlpha == -1 || options.qualityAlpha == AVIF_QUALITY_LOSSLESS) &&
format == AVIF_PIXEL_FORMAT_YUV444; format == AVIF_PIXEL_FORMAT_YUV444;
avifImage* image = avifImageCreate(width, height, depth, format); // Smart pointer for the input image in YUV format
AvifImagePtr image(avifImageCreate(width, height, depth, format), avifImageDestroy);
RETURN_NULL_IF(image == nullptr);
if (lossless) { if (lossless) {
image->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_IDENTITY; image->matrixCoefficients = AVIF_MATRIX_COEFFICIENTS_IDENTITY;
@@ -73,43 +90,49 @@ val encode(std::string buffer, int width, int height, AvifOptions options) {
uint8_t* rgba = reinterpret_cast<uint8_t*>(const_cast<char*>(buffer.data())); uint8_t* rgba = reinterpret_cast<uint8_t*>(const_cast<char*>(buffer.data()));
avifRGBImage srcRGB; avifRGBImage srcRGB;
avifRGBImageSetDefaults(&srcRGB, image); avifRGBImageSetDefaults(&srcRGB, image.get());
srcRGB.pixels = rgba; srcRGB.pixels = rgba;
srcRGB.rowBytes = width * 4; srcRGB.rowBytes = width * 4;
avifImageRGBToYUV(image, &srcRGB); if (options.enableSharpYUV) {
srcRGB.chromaDownsampling = AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV;
}
status = avifImageRGBToYUV(image.get(), &srcRGB);
RETURN_NULL_IF(status != AVIF_RESULT_OK);
avifEncoder* encoder = avifEncoderCreate(); // Create a smart pointer for the encoder
AvifEncoderPtr encoder(avifEncoderCreate(), avifEncoderDestroy);
RETURN_NULL_IF(encoder == nullptr);
if (lossless) { if (lossless) {
encoder->minQuantizer = AVIF_QUANTIZER_LOSSLESS; encoder->quality = AVIF_QUALITY_LOSSLESS;
encoder->maxQuantizer = AVIF_QUANTIZER_LOSSLESS; encoder->qualityAlpha = AVIF_QUALITY_LOSSLESS;
encoder->minQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
encoder->maxQuantizerAlpha = AVIF_QUANTIZER_LOSSLESS;
} else { } else {
encoder->minQuantizer = AVIF_QUANTIZER_BEST_QUALITY; status = avifEncoderSetCodecSpecificOption(encoder.get(), "sharpness",
encoder->maxQuantizer = AVIF_QUANTIZER_WORST_QUALITY; std::to_string(options.sharpness).c_str());
encoder->minQuantizerAlpha = AVIF_QUANTIZER_BEST_QUALITY; RETURN_NULL_IF(status != AVIF_RESULT_OK);
encoder->maxQuantizerAlpha = AVIF_QUANTIZER_WORST_QUALITY;
avifEncoderSetCodecSpecificOption(encoder, "end-usage", "q");
avifEncoderSetCodecSpecificOption(encoder, "cq-level", std::to_string(options.cqLevel).c_str());
avifEncoderSetCodecSpecificOption(encoder, "sharpness",
std::to_string(options.sharpness).c_str());
if (options.cqAlphaLevel != -1) { // Set base quality
avifEncoderSetCodecSpecificOption(encoder, "alpha:cq-level", encoder->quality = options.quality;
std::to_string(options.cqAlphaLevel).c_str()); // Conditionally set alpha quality
if (options.qualityAlpha == -1) {
encoder->qualityAlpha = options.quality;
} else {
encoder->qualityAlpha = options.qualityAlpha;
} }
if (options.tune == 2 || (options.tune == 0 && options.cqLevel <= 32)) { if (options.tune == 2 || (options.tune == 0 && options.quality >= 50)) {
avifEncoderSetCodecSpecificOption(encoder, "tune", "ssim"); status = avifEncoderSetCodecSpecificOption(encoder.get(), "tune", "ssim");
RETURN_NULL_IF(status != AVIF_RESULT_OK);
} }
if (options.chromaDeltaQ) { if (options.chromaDeltaQ) {
avifEncoderSetCodecSpecificOption(encoder, "enable-chroma-deltaq", "1"); status = avifEncoderSetCodecSpecificOption(encoder.get(), "color:enable-chroma-deltaq", "1");
RETURN_NULL_IF(status != AVIF_RESULT_OK);
} }
avifEncoderSetCodecSpecificOption(encoder, "color:denoise-noise-level", status = avifEncoderSetCodecSpecificOption(encoder.get(), "color:denoise-noise-level",
std::to_string(options.denoiseLevel).c_str()); std::to_string(options.denoiseLevel).c_str());
RETURN_NULL_IF(status != AVIF_RESULT_OK);
} }
encoder->maxThreads = emscripten_num_logical_cores(); encoder->maxThreads = emscripten_num_logical_cores();
@@ -117,22 +140,21 @@ val encode(std::string buffer, int width, int height, AvifOptions options) {
encoder->tileColsLog2 = options.tileColsLog2; encoder->tileColsLog2 = options.tileColsLog2;
encoder->speed = options.speed; encoder->speed = options.speed;
avifResult encodeResult = avifEncoderWrite(encoder, image, &output); avifRWData output = AVIF_DATA_EMPTY;
avifResult encodeResult = avifEncoderWrite(encoder.get(), image.get(), &output);
auto js_result = val::null(); auto js_result = val::null();
if (encodeResult == AVIF_RESULT_OK) { if (encodeResult == AVIF_RESULT_OK) {
js_result = Uint8Array.new_(typed_memory_view(output.size, output.data)); js_result = Uint8Array.new_(typed_memory_view(output.size, output.data));
} }
avifImageDestroy(image);
avifEncoderDestroy(encoder);
avifRWDataFree(&output); avifRWDataFree(&output);
return js_result; return js_result;
} }
EMSCRIPTEN_BINDINGS(my_module) { EMSCRIPTEN_BINDINGS(my_module) {
value_object<AvifOptions>("AvifOptions") value_object<AvifOptions>("AvifOptions")
.field("cqLevel", &AvifOptions::cqLevel) .field("quality", &AvifOptions::quality)
.field("cqAlphaLevel", &AvifOptions::cqAlphaLevel) .field("qualityAlpha", &AvifOptions::qualityAlpha)
.field("tileRowsLog2", &AvifOptions::tileRowsLog2) .field("tileRowsLog2", &AvifOptions::tileRowsLog2)
.field("tileColsLog2", &AvifOptions::tileColsLog2) .field("tileColsLog2", &AvifOptions::tileColsLog2)
.field("speed", &AvifOptions::speed) .field("speed", &AvifOptions::speed)
@@ -140,7 +162,8 @@ EMSCRIPTEN_BINDINGS(my_module) {
.field("sharpness", &AvifOptions::sharpness) .field("sharpness", &AvifOptions::sharpness)
.field("tune", &AvifOptions::tune) .field("tune", &AvifOptions::tune)
.field("denoiseLevel", &AvifOptions::denoiseLevel) .field("denoiseLevel", &AvifOptions::denoiseLevel)
.field("subsample", &AvifOptions::subsample); .field("subsample", &AvifOptions::subsample)
.field("enableSharpYUV", &AvifOptions::enableSharpYUV);
function("encode", &encode); function("encode", &encode);
} }

View File

@@ -5,15 +5,16 @@ export const enum AVIFTune {
} }
export interface EncodeOptions { export interface EncodeOptions {
cqLevel: number; quality: number;
qualityAlpha: number;
denoiseLevel: number; denoiseLevel: number;
cqAlphaLevel: number;
tileRowsLog2: number; tileRowsLog2: number;
tileColsLog2: number; tileColsLog2: number;
speed: number; speed: number;
subsample: number; subsample: number;
chromaDeltaQ: boolean; chromaDeltaQ: boolean;
sharpness: number; sharpness: number;
enableSharpYUV: boolean;
tune: AVIFTune; tune: AVIFTune;
} }

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){var imports={};imports["wasm"]=e.data.wasmModule;imports["wasmMemory"]=e.data.wasmMemory;imports["buffer"]=imports["wasmMemory"].buffer;imports["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./avif_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}}; "use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./avif_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance})}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["__emscripten_thread_exit"](result)}}catch(ex){if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["__emscripten_thread_exit"](ex.status)}}else{throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}postMessage({"cmd":"cancelDone"})}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -10,8 +10,11 @@
# $(LIBAVIF_FLAGS) # $(LIBAVIF_FLAGS)
# $(ENVIRONMENT) # $(ENVIRONMENT)
# $(OUT_JS) is something like "enc/avif_enc.js" or "enc/avif_enc_mt.js"
# so $(OUT_BUILD_DIR) will be "node_modules/build/enc/avif_enc[_mt]"
OUT_BUILD_DIR := $(BUILD_DIR)/$(basename $(OUT_JS)) OUT_BUILD_DIR := $(BUILD_DIR)/$(basename $(OUT_JS))
# We're making libavif and libaom for every node_modules/[enc|dec]/
CODEC_BUILD_DIR := $(OUT_BUILD_DIR)/libavif CODEC_BUILD_DIR := $(OUT_BUILD_DIR)/libavif
CODEC_OUT := $(CODEC_BUILD_DIR)/libavif.a CODEC_OUT := $(CODEC_BUILD_DIR)/libavif.a
@@ -25,6 +28,13 @@ OUT_WORKER=$(OUT_JS:.js=.worker.js)
all: $(OUT_JS) all: $(OUT_JS)
# Only add libsharpyuv as a dependency for encoders.
# Yes, that if statement is true for encoders.
ifneq (,$(findstring enc/, $(OUT_JS)))
$(OUT_JS): $(LIBSHARPYUV)
$(CODEC_OUT): $(LIBSHARPYUV)
endif
$(OUT_JS): $(OUT_CPP) $(LIBAOM_OUT) $(CODEC_OUT) $(OUT_JS): $(OUT_CPP) $(LIBAOM_OUT) $(CODEC_OUT)
$(CXX) \ $(CXX) \
-I $(CODEC_DIR)/include \ -I $(CODEC_DIR)/include \
@@ -32,6 +42,7 @@ $(OUT_JS): $(OUT_CPP) $(LIBAOM_OUT) $(CODEC_OUT)
$(LDFLAGS) \ $(LDFLAGS) \
$(OUT_FLAGS) \ $(OUT_FLAGS) \
--bind \ --bind \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
-s ENVIRONMENT=$(ENVIRONMENT) \ -s ENVIRONMENT=$(ENVIRONMENT) \
-s EXPORT_ES6=1 \ -s EXPORT_ES6=1 \
-o $@ \ -o $@ \
@@ -39,6 +50,7 @@ $(OUT_JS): $(OUT_CPP) $(LIBAOM_OUT) $(CODEC_OUT)
$(CODEC_OUT): $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_OUT) $(CODEC_OUT): $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_OUT)
emcmake cmake \ emcmake cmake \
-DCMAKE_LIBRARY_PATH=$(LIBSHARPYUV_BUILD_DIR) \
-DCMAKE_BUILD_TYPE=Release \ -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=0 \ -DBUILD_SHARED_LIBS=0 \
-DAVIF_CODEC_AOM=1 \ -DAVIF_CODEC_AOM=1 \

View File

@@ -1,4 +1,4 @@
FROM emscripten/emsdk:2.0.23 FROM emscripten/emsdk:2.0.34
RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config
ENV CFLAGS "-O3 -flto" ENV CFLAGS "-O3 -flto"
ENV CXXFLAGS "${CFLAGS} -std=c++17" ENV CXXFLAGS "${CFLAGS} -std=c++17"
@@ -8,7 +8,6 @@ ENV LDFLAGS "${CFLAGS} \
-s ALLOW_MEMORY_GROWTH=1 \ -s ALLOW_MEMORY_GROWTH=1 \
-s TEXTDECODER=2 \ -s TEXTDECODER=2 \
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \ -s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \
-s MINIMAL_RUNTIME=1 \
" "
# Build and cache standard libraries with these flags + Embind. # Build and cache standard libraries with these flags + Embind.
RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -xc++ /dev/null -o /dev/null RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -xc++ /dev/null -o /dev/null

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
CODEC_URL = https://github.com/libjxl/libjxl.git CODEC_URL = https://github.com/libjxl/libjxl.git
CODEC_VERSION = 3f76321a7cbcf4f452894dc173eb7be60f508ecb CODEC_VERSION = 9f544641ec83f6abd9da598bdd08178ee8a003e0
CODEC_DIR = node_modules/jxl CODEC_DIR = node_modules/jxl
CODEC_BUILD_ROOT := $(CODEC_DIR)/build CODEC_BUILD_ROOT := $(CODEC_DIR)/build
CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt CODEC_MT_BUILD_DIR := $(CODEC_BUILD_ROOT)/mt
@@ -75,6 +75,9 @@ $(CODEC_MT_SIMD_BUILD_DIR)/Makefile: CXXFLAGS+=-msimd128
-DCMAKE_CROSSCOMPILING_EMULATOR=node \ -DCMAKE_CROSSCOMPILING_EMULATOR=node \
-B $(@D) \ -B $(@D) \
$(<D) $(<D)
emcc -Wall -O3 -o $(CODEC_DIR)/third_party/skcms/skcms.cc.o -I$(CODEC_DIR)/third_party/skcms -c $(CODEC_DIR)/third_party/skcms/skcms.cc
llvm-ar rc $(CODEC_BUILD_DIR)/third_party/libskcms.a $(CODEC_DIR)/third_party/skcms/skcms.cc.o
rm $(CODEC_DIR)/third_party/skcms/skcms.cc.o
$(CODEC_DIR)/CMakeLists.txt: $(CODEC_DIR)/CMakeLists.txt:
$(RM) -r $(@D) $(RM) -r $(@D)

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -4,21 +4,21 @@
#include "lib/jxl/base/thread_pool_internal.h" #include "lib/jxl/base/thread_pool_internal.h"
#include "lib/jxl/enc_external_image.h" #include "lib/jxl/enc_external_image.h"
#include "lib/jxl/enc_file.h" #include "lib/jxl/enc_file.h"
#include "lib/jxl/enc_color_management.h"
using namespace emscripten; using namespace emscripten;
thread_local const val Uint8Array = val::global("Uint8Array"); thread_local const val Uint8Array = val::global("Uint8Array");
struct JXLOptions { struct JXLOptions {
// 1 = slowest int effort;
// 7 = fastest
int speed;
float quality; float quality;
bool progressive; bool progressive;
int epf; int epf;
int nearLossless;
bool lossyPalette; bool lossyPalette;
size_t decodingSpeedTier; size_t decodingSpeedTier;
float photonNoiseIso;
bool lossyModular;
}; };
val encode(std::string image, int width, int height, JXLOptions options) { val encode(std::string image, int width, int height, JXLOptions options) {
@@ -33,11 +33,14 @@ val encode(std::string image, int width, int height, JXLOptions options) {
pool_ptr = &pool; pool_ptr = &pool;
#endif #endif
cparams.epf = options.epf; size_t st = 10 - options.effort;
cparams.speed_tier = static_cast<jxl::SpeedTier>(options.speed); cparams.speed_tier = jxl::SpeedTier(st);
cparams.decoding_speed_tier = options.decodingSpeedTier;
if (options.lossyPalette || options.nearLossless) { cparams.epf = options.epf;
cparams.decoding_speed_tier = options.decodingSpeedTier;
cparams.photon_noise_iso = options.photonNoiseIso;
if (options.lossyPalette) {
cparams.lossy_palette = true; cparams.lossy_palette = true;
cparams.palette_colors = 0; cparams.palette_colors = 0;
cparams.options.predictor = jxl::Predictor::Zero; cparams.options.predictor = jxl::Predictor::Zero;
@@ -49,11 +52,16 @@ val encode(std::string image, int width, int height, JXLOptions options) {
float quality = options.quality; float quality = options.quality;
// Quality settings roughly match libjpeg qualities. // Quality settings roughly match libjpeg qualities.
if (quality < 7 || quality == 100) { if (options.lossyModular || quality == 100) {
cparams.modular_mode = true; cparams.modular_mode = true;
// Internal modular quality to roughly match VarDCT size. // Internal modular quality to roughly match VarDCT size.
cparams.quality_pair.first = cparams.quality_pair.second = if (quality < 7) {
std::min(35 + (quality - 7) * 3.0f, 100.0f); cparams.quality_pair.first = cparams.quality_pair.second =
std::min(35 + (quality - 7) * 3.0f, 100.0f);
} else {
cparams.quality_pair.first = cparams.quality_pair.second =
std::min(35 + (quality - 7) * 65.f / 93.f, 100.0f);
}
} else { } else {
cparams.modular_mode = false; cparams.modular_mode = false;
if (quality >= 30) { if (quality >= 30) {
@@ -90,14 +98,14 @@ val encode(std::string image, int width, int height, JXLOptions options) {
jxl::Span<const uint8_t>(reinterpret_cast<const uint8_t*>(image.data()), image.size()), width, jxl::Span<const uint8_t>(reinterpret_cast<const uint8_t*>(image.data()), image.size()), width,
height, jxl::ColorEncoding::SRGB(/*is_gray=*/false), /*has_alpha=*/true, height, jxl::ColorEncoding::SRGB(/*is_gray=*/false), /*has_alpha=*/true,
/*alpha_is_premultiplied=*/false, /*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN, /*alpha_is_premultiplied=*/false, /*bits_per_sample=*/8, /*endiannes=*/JXL_LITTLE_ENDIAN,
/*flipped_y=*/false, pool_ptr, main); /*flipped_y=*/false, pool_ptr, main, /*(only true if bits_per_sample==32) float_in=*/false);
if (!result) { if (!result) {
return val::null(); return val::null();
} }
auto js_result = val::null(); auto js_result = val::null();
if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, /*aux=*/nullptr, pool_ptr)) { if (EncodeFile(cparams, &io, &passes_enc_state, &bytes, jxl::GetJxlCms(), /*aux=*/nullptr, pool_ptr)) {
js_result = Uint8Array.new_(typed_memory_view(bytes.size(), bytes.data())); js_result = Uint8Array.new_(typed_memory_view(bytes.size(), bytes.data()));
} }
@@ -106,12 +114,13 @@ val encode(std::string image, int width, int height, JXLOptions options) {
EMSCRIPTEN_BINDINGS(my_module) { EMSCRIPTEN_BINDINGS(my_module) {
value_object<JXLOptions>("JXLOptions") value_object<JXLOptions>("JXLOptions")
.field("speed", &JXLOptions::speed) .field("effort", &JXLOptions::effort)
.field("quality", &JXLOptions::quality) .field("quality", &JXLOptions::quality)
.field("progressive", &JXLOptions::progressive) .field("progressive", &JXLOptions::progressive)
.field("nearLossless", &JXLOptions::nearLossless)
.field("lossyPalette", &JXLOptions::lossyPalette) .field("lossyPalette", &JXLOptions::lossyPalette)
.field("decodingSpeedTier", &JXLOptions::decodingSpeedTier) .field("decodingSpeedTier", &JXLOptions::decodingSpeedTier)
.field("photonNoiseIso", &JXLOptions::photonNoiseIso)
.field("lossyModular", &JXLOptions::lossyModular)
.field("epf", &JXLOptions::epf); .field("epf", &JXLOptions::epf);
function("encode", &encode); function("encode", &encode);

View File

@@ -1,11 +1,12 @@
export interface EncodeOptions { export interface EncodeOptions {
speed: number; effort: number;
quality: number; quality: number;
progressive: boolean; progressive: boolean;
epf: number; epf: number;
nearLossless: number;
lossyPalette: boolean; lossyPalette: boolean;
decodingSpeedTier: number; decodingSpeedTier: number;
photonNoiseIso: number;
lossyModular: boolean;
} }
export interface JXLModule extends EmscriptenWasm.Module { export interface JXLModule extends EmscriptenWasm.Module {

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){var imports={};imports["wasm"]=e.data.wasmModule;imports["wasmMemory"]=e.data.wasmMemory;imports["buffer"]=imports["wasmMemory"].buffer;imports["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}}; "use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -1 +1 @@
"use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){var imports={};imports["wasm"]=e.data.wasmModule;imports["wasmMemory"]=e.data.wasmMemory;imports["buffer"]=imports["wasmMemory"].buffer;imports["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt_simd.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);Module["PThread"].threadExit(result)}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}}; "use strict";var Module={};var initializedJS=false;function threadPrintErr(){var text=Array.prototype.slice.call(arguments).join(" ");console.error(text)}function threadAlert(){var text=Array.prototype.slice.call(arguments).join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=function(info,receiveInstance){var instance=new WebAssembly.Instance(Module["wasmModule"],info);receiveInstance(instance);Module["wasmModule"]=null;return instance.exports};function moduleLoaded(){}self.onmessage=function(e){try{if(e.data.cmd==="load"){Module["wasmModule"]=e.data.wasmModule;Module["wasmMemory"]=e.data.wasmMemory;Module["buffer"]=Module["wasmMemory"].buffer;Module["ENVIRONMENT_IS_PTHREAD"]=true;(e.data.urlOrBlob?import(e.data.urlOrBlob):import("./jxl_enc_mt_simd.js")).then(function(exports){return exports.default(Module)}).then(function(instance){Module=instance;moduleLoaded()})}else if(e.data.cmd==="objectTransfer"){Module["PThread"].receiveObjectTransfer(e.data)}else if(e.data.cmd==="run"){Module["__performance_now_clock_drift"]=performance.now()-e.data.time;Module["__emscripten_thread_init"](e.data.threadInfoStruct,0,0);var max=e.data.stackBase;var top=e.data.stackBase+e.data.stackSize;Module["establishStackSpace"](top,max);Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInit();if(!initializedJS){Module["___embind_register_native_and_builtin_types"]();initializedJS=true}try{var result=Module["invokeEntryPoint"](e.data.start_routine,e.data.arg);if(Module["keepRuntimeAlive"]()){Module["PThread"].setExitStatus(result)}else{Module["PThread"].threadExit(result)}}catch(ex){if(ex==="Canceled!"){Module["PThread"].threadCancel()}else if(ex!="unwind"){if(ex instanceof Module["ExitStatus"]){if(Module["keepRuntimeAlive"]()){}else{Module["PThread"].threadExit(ex.status)}}else{Module["PThread"].threadExit(-2);throw ex}}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["PThread"].threadCancel()}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="processThreadQueue"){if(Module["_pthread_self"]()){Module["_emscripten_current_thread_process_queued_calls"]()}}else{err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){err("worker.js onmessage() captured an uncaught exception: "+ex);if(ex&&ex.stack)err(ex.stack);throw ex}};

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -158,6 +158,11 @@ val encode(std::string image_in, int image_width, int image_height, MozJpegOptio
if (!opts.auto_subsample && opts.color_space == JCS_YCbCr) { if (!opts.auto_subsample && opts.color_space == JCS_YCbCr) {
cinfo.comp_info[0].h_samp_factor = opts.chroma_subsample; cinfo.comp_info[0].h_samp_factor = opts.chroma_subsample;
cinfo.comp_info[0].v_samp_factor = opts.chroma_subsample; cinfo.comp_info[0].v_samp_factor = opts.chroma_subsample;
if (opts.chroma_subsample > 2) {
// Otherwise encoding fails.
jpeg_c_set_int_param(&cinfo, JINT_DC_SCAN_OPT_MODE, 1);
}
} }
if (!opts.baseline && opts.progressive) { if (!opts.baseline && opts.progressive) {

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

407
codecs/oxipng/Cargo.lock generated
View File

@@ -2,18 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "adler"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.1" version = "1.0.1"
@@ -21,22 +9,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "bit-vec" name = "bitvec"
version = "0.6.3" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
[[package]] "funty",
name = "bitflags" "radium",
version = "1.2.1" "tap",
source = "registry+https://github.com/rust-lang/crates.io-index" "wyz",
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" ]
[[package]]
name = "build_const"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
@@ -46,15 +28,9 @@ checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.4.1" version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41aa2ec95ca3b5c54cf73c91acf06d24f4495d5f1b1c12506ae3483d646177ac" checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]] [[package]]
name = "cc" name = "cc"
@@ -62,120 +38,51 @@ version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cloudflare-zlib"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5ed63a019d55bacd15cadcbcb96bf41b16281417fff393bdb55fa84255fe4b9"
dependencies = [
"cloudflare-zlib-sys",
]
[[package]]
name = "cloudflare-zlib-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e195cb274a0d6ee87e718838a09baecd7cbc9f6075dac256a84cb5842739c06"
dependencies = [
"cc",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "const_fn"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
[[package]]
name = "crc"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
dependencies = [
"build_const",
]
[[package]]
name = "crc32fast"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if 1.0.0",
]
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.0" version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]] [[package]]
name = "crossbeam-deque" name = "crossbeam-deque"
version = "0.8.0" version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"crossbeam-epoch", "crossbeam-epoch",
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.1" version = "0.9.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "autocfg",
"const_fn", "cfg-if",
"crossbeam-utils", "crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
] ]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.1" version = "0.8.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
dependencies = [ dependencies = [
"autocfg", "cfg-if",
"cfg-if 1.0.0",
"lazy_static",
]
[[package]]
name = "deflate"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
dependencies = [
"adler32",
"byteorder",
] ]
[[package]] [[package]]
@@ -184,56 +91,35 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.9.1" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "hermit-abi"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
dependencies = [
"libc",
]
[[package]]
name = "image"
version = "0.23.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce04077ead78e39ae8610ad26216aed811996b043d47beed5090db674f9e9b5"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"num-iter",
"num-rational",
"num-traits",
"png",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.6.1" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [ dependencies = [
"autocfg", "equivalent",
"hashbrown", "hashbrown",
"rayon", "rayon",
] ]
[[package]]
name = "itertools"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
dependencies = [
"either",
]
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.48" version = "0.3.48"
@@ -249,161 +135,47 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb"
[[package]] [[package]]
name = "libdeflate-sys" name = "libdeflate-sys"
version = "0.7.1" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a95fa4be7085dd06a8296dcc3f399f12ab8b0309c157dcaa90669130b175b97" checksum = "67921a7f85100c1559efc3d1c7c472091b7da05f304b4bbd5356f075e97f1cc2"
dependencies = [ dependencies = [
"cc", "cc",
] ]
[[package]] [[package]]
name = "libdeflater" name = "libdeflater"
version = "0.7.1" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccc147465654929bf7b56518cc46d11701ba290f4ff94398ae3f89f1663cf60f" checksum = "3a31b22f662350ec294b13859f935aea772ba7b2bc8776269f4a5627308eab7d"
dependencies = [ dependencies = [
"libdeflate-sys", "libdeflate-sys",
] ]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.11" version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
dependencies = [
"cfg-if 0.1.10",
]
[[package]]
name = "memoffset"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler32",
]
[[package]]
name = "miniz_oxide"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "oxipng" name = "oxipng"
version = "4.0.3" version = "9.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d0b53912a666fe2970f8ab254e283531c816aed16551ab66c52485eadb44e6" checksum = "28e5c341ef78a228e47a551bfd15ff885d8c501af49f953358763a538c01f14d"
dependencies = [ dependencies = [
"bit-vec", "bitvec",
"byteorder",
"cloudflare-zlib",
"crc",
"crossbeam-channel", "crossbeam-channel",
"image",
"indexmap", "indexmap",
"itertools",
"libdeflater", "libdeflater",
"log", "log",
"miniz_oxide 0.4.3",
"rayon", "rayon",
"rgb", "rgb",
"rustc-hash",
"rustc_version", "rustc_version",
] ]
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "png"
version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide 0.3.7",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.26" version = "1.0.26"
@@ -423,71 +195,60 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rayon" name = "radium"
version = "1.5.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rayon"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
dependencies = [ dependencies = [
"autocfg",
"crossbeam-deque",
"either", "either",
"rayon-core", "rayon-core",
] ]
[[package]] [[package]]
name = "rayon-core" name = "rayon-core"
version = "1.9.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
dependencies = [ dependencies = [
"crossbeam-channel",
"crossbeam-deque", "crossbeam-deque",
"crossbeam-utils", "crossbeam-utils",
"lazy_static",
"num_cpus",
] ]
[[package]] [[package]]
name = "rgb" name = "rgb"
version = "0.8.25" version = "0.8.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287f3c3f8236abb92d8b7e36797f19159df4b58f0a658cc3fb6dd3004b1f3bd3" checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
] ]
[[package]] [[package]]
name = "rustc_version" name = "rustc-hash"
version = "0.3.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65c94201b44764d6d1f7e37c15a8289ed55e546c1762c7f1d57f616966e0c181" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [ dependencies = [
"semver", "semver",
] ]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]] [[package]]
name = "semver" name = "semver"
version = "0.11.0" version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]
[[package]] [[package]]
name = "spmc" name = "spmc"
@@ -499,7 +260,6 @@ checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5"
name = "squoosh-oxipng" name = "squoosh-oxipng"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"libdeflater",
"log", "log",
"oxipng", "oxipng",
"wasm-bindgen", "wasm-bindgen",
@@ -518,10 +278,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "ucd-trie" name = "tap"
version = "0.1.3" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
@@ -535,7 +295,7 @@ version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
] ]
@@ -594,3 +354,12 @@ name = "wasm-bindgen-shared"
version = "0.2.74" version = "0.2.74"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]

View File

@@ -12,8 +12,7 @@ wasm-opt = ["-O", "--no-validation"]
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
oxipng = { version = "4.0.3", default-features = false, features = ["libdeflater"] } oxipng = { version = "9.0", default-features = false, features = ["freestanding"] }
libdeflater = { version = "0.7.1", features = ["freestanding"] }
wasm-bindgen = "0.2.73" wasm-bindgen = "0.2.73"
log = { version = "0.4.11", features = ["release_max_level_off"] } log = { version = "0.4.11", features = ["release_max_level_off"] }
wasm-bindgen-rayon = { version = "1.0", optional = true } wasm-bindgen-rayon = { version = "1.0", optional = true }

View File

@@ -1,5 +1,5 @@
# OxiPNG # OxiPNG
- Source: <https://github.com/shssoichiro/oxipng> - Source: <https://github.com/shssoichiro/oxipng>
- Version: v3.0.0 - Version: v9.0.0
- License: MIT - License: MIT

View File

@@ -5,5 +5,5 @@ set -e
rm -rf pkg,{-parallel} rm -rf pkg,{-parallel}
export CFLAGS="${CFLAGS} -DUNALIGNED_ACCESS_IS_FAST=1" export CFLAGS="${CFLAGS} -DUNALIGNED_ACCESS_IS_FAST=1"
wasm-pack build -t web wasm-pack build -t web
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' wasm-pack build -t web -d pkg-parallel -- -Z build-std=panic_abort,std --features=parallel RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' wasm-pack build -t web -d pkg-parallel . -- -Z build-std=panic_abort,std --features=parallel
rm pkg{,-parallel}/.gitignore rm pkg{,-parallel}/.gitignore

View File

@@ -1,6 +1,6 @@
{ {
"name": "oxipng", "name": "oxipng",
"scripts": { "scripts": {
"build": "RUST_IMG=rustlang/rust@sha256:744aeea5a38f95aa7a96ec37269a65f0c6197a1cdd87d6534e12bb869141d807 ../build-rust.sh ./build.sh" "build": "RUST_IMG=rustlang/rust@sha256:5fd16a5576c22c8fdd5d659247755999e426c04de8dcf18a41ea446c5f253309 ../build-rust.sh ./build.sh"
} }
} }

View File

@@ -1,5 +1,5 @@
# OxiPNG # OxiPNG
- Source: <https://github.com/shssoichiro/oxipng> - Source: <https://github.com/shssoichiro/oxipng>
- Version: v3.0.0 - Version: v9.0.0
- License: MIT - License: MIT

View File

@@ -11,5 +11,7 @@
], ],
"module": "squoosh_oxipng.js", "module": "squoosh_oxipng.js",
"types": "squoosh_oxipng.d.ts", "types": "squoosh_oxipng.d.ts",
"sideEffects": false "sideEffects": [
"./snippets/*"
]
} }

View File

@@ -1,12 +1,14 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
/** /**
* @param {Uint8Array} data * @param {Uint8ClampedArray} data
* @param {number} width
* @param {number} height
* @param {number} level * @param {number} level
* @param {boolean} interlace * @param {boolean} interlace
* @returns {Uint8Array} * @returns {Uint8Array}
*/ */
export function optimise(data: Uint8Array, level: number, interlace: boolean): Uint8Array; export function optimise(data: Uint8ClampedArray, width: number, height: number, level: number, interlace: boolean): Uint8Array;
/** /**
* @param {number} num_threads * @param {number} num_threads
* @returns {Promise<any>} * @returns {Promise<any>}
@@ -36,8 +38,7 @@ export class wbg_rayon_PoolBuilder {
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput { export interface InitOutput {
readonly __wasm_init_memory: () => void; readonly optimise: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
readonly optimise: (a: number, b: number, c: number, d: number, e: number) => void;
readonly __wbg_wbg_rayon_poolbuilder_free: (a: number) => void; readonly __wbg_wbg_rayon_poolbuilder_free: (a: number) => void;
readonly wbg_rayon_poolbuilder_numThreads: (a: number) => number; readonly wbg_rayon_poolbuilder_numThreads: (a: number) => number;
readonly wbg_rayon_poolbuilder_receiver: (a: number) => number; readonly wbg_rayon_poolbuilder_receiver: (a: number) => number;

View File

@@ -54,17 +54,19 @@ function getArrayU8FromWasm0(ptr, len) {
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
} }
/** /**
* @param {Uint8Array} data * @param {Uint8ClampedArray} data
* @param {number} width
* @param {number} height
* @param {number} level * @param {number} level
* @param {boolean} interlace * @param {boolean} interlace
* @returns {Uint8Array} * @returns {Uint8Array}
*/ */
export function optimise(data, level, interlace) { export function optimise(data, width, height, level, interlace) {
try { try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN; var len0 = WASM_VECTOR_LEN;
wasm.optimise(retptr, ptr0, len0, level, interlace); wasm.optimise(retptr, ptr0, len0, width, height, level, interlace);
var r0 = getInt32Memory0()[retptr / 4 + 0]; var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1]; var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice(); var v1 = getArrayU8FromWasm0(r0, r1).slice();

View File

@@ -1,7 +1,6 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
export function __wasm_init_memory(): void; export function optimise(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void;
export function optimise(a: number, b: number, c: number, d: number, e: number): void;
export function __wbg_wbg_rayon_poolbuilder_free(a: number): void; export function __wbg_wbg_rayon_poolbuilder_free(a: number): void;
export function wbg_rayon_poolbuilder_numThreads(a: number): number; export function wbg_rayon_poolbuilder_numThreads(a: number): number;
export function wbg_rayon_poolbuilder_receiver(a: number): number; export function wbg_rayon_poolbuilder_receiver(a: number): number;

View File

@@ -1,5 +1,5 @@
# OxiPNG # OxiPNG
- Source: <https://github.com/shssoichiro/oxipng> - Source: <https://github.com/shssoichiro/oxipng>
- Version: v3.0.0 - Version: v9.0.0
- License: MIT - License: MIT

View File

@@ -11,5 +11,7 @@
], ],
"module": "squoosh_oxipng.js", "module": "squoosh_oxipng.js",
"types": "squoosh_oxipng.d.ts", "types": "squoosh_oxipng.d.ts",
"sideEffects": false "sideEffects": [
"./snippets/*"
]
} }

View File

@@ -1,18 +1,20 @@
/* tslint:disable */ /* tslint:disable */
/* eslint-disable */ /* eslint-disable */
/** /**
* @param {Uint8Array} data * @param {Uint8ClampedArray} data
* @param {number} width
* @param {number} height
* @param {number} level * @param {number} level
* @param {boolean} interlace * @param {boolean} interlace
* @returns {Uint8Array} * @returns {Uint8Array}
*/ */
export function optimise(data: Uint8Array, level: number, interlace: boolean): Uint8Array; export function optimise(data: Uint8ClampedArray, width: number, height: number, level: number, interlace: boolean): Uint8Array;
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
export interface InitOutput { export interface InitOutput {
readonly memory: WebAssembly.Memory; readonly memory: WebAssembly.Memory;
readonly optimise: (a: number, b: number, c: number, d: number, e: number) => void; readonly optimise: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
readonly __wbindgen_add_to_stack_pointer: (a: number) => number; readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
readonly __wbindgen_malloc: (a: number) => number; readonly __wbindgen_malloc: (a: number) => number;
readonly __wbindgen_free: (a: number, b: number) => void; readonly __wbindgen_free: (a: number, b: number) => void;

View File

@@ -38,17 +38,19 @@ function getArrayU8FromWasm0(ptr, len) {
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
} }
/** /**
* @param {Uint8Array} data * @param {Uint8ClampedArray} data
* @param {number} width
* @param {number} height
* @param {number} level * @param {number} level
* @param {boolean} interlace * @param {boolean} interlace
* @returns {Uint8Array} * @returns {Uint8Array}
*/ */
export function optimise(data, level, interlace) { export function optimise(data, width, height, level, interlace) {
try { try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc); var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN; var len0 = WASM_VECTOR_LEN;
wasm.optimise(retptr, ptr0, len0, level, interlace); wasm.optimise(retptr, ptr0, len0, width, height, level, interlace);
var r0 = getInt32Memory0()[retptr / 4 + 0]; var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1]; var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice(); var v1 = getArrayU8FromWasm0(r0, r1).slice();

View File

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

View File

@@ -1,20 +1,27 @@
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
pub use wasm_bindgen_rayon::init_thread_pool; pub use wasm_bindgen_rayon::init_thread_pool;
use oxipng::AlphaOptim; use oxipng::{BitDepth, ColorType, Interlacing};
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use wasm_bindgen::Clamped;
#[wasm_bindgen] #[wasm_bindgen]
pub fn optimise(data: &[u8], level: u8, interlace: bool) -> Vec<u8> { pub fn optimise(
data: Clamped<Vec<u8>>,
width: u32,
height: u32,
level: u8,
interlace: bool,
) -> Vec<u8> {
let mut options = oxipng::Options::from_preset(level); let mut options = oxipng::Options::from_preset(level);
options.alphas.insert(AlphaOptim::Black); options.optimize_alpha = true;
options.alphas.insert(AlphaOptim::White); options.interlace = Some(if interlace {
options.alphas.insert(AlphaOptim::Up); Interlacing::Adam7
options.alphas.insert(AlphaOptim::Down); } else {
options.alphas.insert(AlphaOptim::Left); Interlacing::None
options.alphas.insert(AlphaOptim::Right); });
options.interlace = Some(if interlace { 1 } else { 0 });
options.deflate = oxipng::Deflaters::Libdeflater; let raw = oxipng::RawImage::new(width, height, ColorType::RGBA, BitDepth::Eight, data.0)
oxipng::optimize_from_memory(data, &options).unwrap_throw() .unwrap_throw();
raw.create_optimized_png(&options).unwrap_throw()
} }

42
codecs/qoi/Makefile Normal file
View File

@@ -0,0 +1,42 @@
CODEC_URL = https://github.com/phoboslab/qoi/archive/8d35d93cdca85d2868246c2a8a80a1e2c16ba2a8.tar.gz
CODEC_DIR = node_modules/qoi
CODEC_BUILD_DIR:= $(CODEC_DIR)/build
ENVIRONMENT = worker
OUT_JS = enc/qoi_enc.js dec/qoi_dec.js
OUT_WASM := $(OUT_JS:.js=.wasm)
.PHONY: all clean
all: $(OUT_JS)
$(filter enc/%,$(OUT_JS)): enc/qoi_enc.o
$(filter dec/%,$(OUT_JS)): dec/qoi_dec.o
# ALL .js FILES
$(OUT_JS):
$(LD) \
$(LDFLAGS) \
--bind \
-s ENVIRONMENT=$(ENVIRONMENT) \
-s EXPORT_ES6=1 \
-o $@ \
$+
# ALL .o FILES
%.o: %.cpp $(CODEC_DIR)
$(CXX) -c \
$(CXXFLAGS) \
-I $(CODEC_DIR) \
-o $@ \
$<
# CREATE DIRECTORY
$(CODEC_DIR):
mkdir -p $(CODEC_DIR)
curl -sL $(CODEC_URL) | tar xz --strip 1 -C $(CODEC_DIR)
clean:
$(RM) $(OUT_JS) $(OUT_WASM)
$(MAKE) -C $(CODEC_DIR) clean

View File

@@ -0,0 +1,30 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#define QOI_IMPLEMENTATION
#include "qoi.h"
using namespace emscripten;
thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray");
thread_local const val ImageData = val::global("ImageData");
val decode(std::string qoiimage) {
qoi_desc desc;
uint8_t* rgba = (uint8_t*)qoi_decode(qoiimage.c_str(), qoiimage.length(), &desc, 4);
// Resultant width and height stored in descriptor
int decodedWidth = desc.width;
int decodedHeight = desc.height;
val result = ImageData.new_(
Uint8ClampedArray.new_(typed_memory_view(4 * decodedWidth * decodedHeight, rgba)),
decodedWidth, decodedHeight);
free(rgba);
return result;
}
EMSCRIPTEN_BINDINGS(my_module) {
function("decode", &decode);
}

7
codecs/qoi/dec/qoi_dec.d.ts vendored Normal file
View File

@@ -0,0 +1,7 @@
export interface QOIModule extends EmscriptenWasm.Module {
decode(data: BufferSource): ImageData | null;
}
declare var moduleFactory: EmscriptenWasm.ModuleFactory<QOIModule>;
export default moduleFactory;

16
codecs/qoi/dec/qoi_dec.js generated Normal file

File diff suppressed because one or more lines are too long

BIN
codecs/qoi/dec/qoi_dec.wasm Normal file

Binary file not shown.

View File

@@ -0,0 +1,36 @@
#include <emscripten/bind.h>
#include <emscripten/val.h>
#define QOI_IMPLEMENTATION
#include "qoi.h"
using namespace emscripten;
struct QoiOptions {};
thread_local const val Uint8Array = val::global("Uint8Array");
val encode(std::string buffer, int width, int height, QoiOptions options) {
int compressedSizeInBytes;
qoi_desc desc;
desc.width = width;
desc.height = height;
desc.channels = 4;
desc.colorspace = QOI_SRGB;
uint8_t* encodedData = (uint8_t*)qoi_encode(buffer.c_str(), &desc, &compressedSizeInBytes);
if (encodedData == NULL)
return val::null();
auto js_result =
Uint8Array.new_(typed_memory_view(compressedSizeInBytes, (const uint8_t*)encodedData));
free(encodedData);
return js_result;
}
EMSCRIPTEN_BINDINGS(my_module) {
value_object<QoiOptions>("QoiOptions");
function("encode", &encode);
}

14
codecs/qoi/enc/qoi_enc.d.ts vendored Normal file
View File

@@ -0,0 +1,14 @@
export interface EncodeOptions {}
export interface QoiModule extends EmscriptenWasm.Module {
encode(
data: BufferSource,
width: number,
height: number,
options: EncodeOptions,
): Uint8Array;
}
declare var moduleFactory: EmscriptenWasm.ModuleFactory<QoiModule>;
export default moduleFactory;

16
codecs/qoi/enc/qoi_enc.js generated Normal file

File diff suppressed because one or more lines are too long

BIN
codecs/qoi/enc/qoi_enc.wasm Normal file

Binary file not shown.

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

@@ -0,0 +1,7 @@
{
"name": "qoi",
"scripts": {
"build": "../build-cpp.sh"
}
}

View File

@@ -2,7 +2,7 @@ ARG RUST_IMG=rust:1.47
FROM emscripten/emsdk:2.0.8 AS wasm-tools FROM emscripten/emsdk:2.0.8 AS wasm-tools
WORKDIR /opt/wasm-tools WORKDIR /opt/wasm-tools
RUN wget -qO- https://github.com/rustwasm/wasm-pack/releases/download/v0.9.1/wasm-pack-v0.9.1-x86_64-unknown-linux-musl.tar.gz | tar -xzf - --strip 1 RUN wget -qO- https://github.com/rustwasm/wasm-pack/releases/download/v0.12.1/wasm-pack-v0.12.1-x86_64-unknown-linux-musl.tar.gz | tar -xzf - --strip 1
FROM $RUST_IMG AS rust FROM $RUST_IMG AS rust
ARG RUST_IMG ARG RUST_IMG

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

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