├── packages ├── oxipng │ ├── codec │ │ ├── rust-toolchain │ │ ├── README.md │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── squoosh_oxipng_bg.wasm │ │ │ ├── package.json │ │ │ ├── squoosh_oxipng_bg.wasm.d.ts │ │ │ └── squoosh_oxipng.d.ts │ │ ├── pkg-parallel │ │ │ ├── README.md │ │ │ ├── squoosh_oxipng_bg.wasm │ │ │ ├── package.json │ │ │ ├── squoosh_oxipng_bg.wasm.d.ts │ │ │ └── snippets │ │ │ │ └── wasm-bindgen-rayon-3e04391371ad0a8e │ │ │ │ └── src │ │ │ │ ├── workerHelpers.worker.js │ │ │ │ └── workerHelpers.js │ │ ├── package.json │ │ ├── build.sh │ │ ├── Cargo.toml │ │ ├── pre.js │ │ ├── LICENSE.codec.md │ │ └── src │ │ │ └── lib.rs │ ├── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── package.json │ ├── meta.ts │ └── CHANGELOG.md ├── avif │ ├── codec │ │ ├── enc │ │ │ ├── avif_enc_mt.d.ts │ │ │ ├── avif_enc.wasm │ │ │ ├── avif_enc_mt.wasm │ │ │ ├── README.md │ │ │ ├── avif_enc.d.ts │ │ │ └── avif_enc_mt.worker.mjs │ │ ├── dec │ │ │ ├── avif_dec.wasm │ │ │ ├── Readme.md │ │ │ ├── avif_dec.d.ts │ │ │ └── avif_dec.cpp │ │ ├── package.json │ │ ├── pre.js │ │ └── helper.Makefile │ ├── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── package.json │ ├── meta.ts │ ├── utils.ts │ └── CHANGELOG.md ├── jxl │ ├── codec │ │ ├── enc │ │ │ ├── jxl_enc_mt.d.ts │ │ │ ├── jxl_enc_mt_simd.d.ts │ │ │ ├── jxl_enc.wasm │ │ │ ├── jxl_enc_mt.wasm │ │ │ ├── jxl_enc_mt_simd.wasm │ │ │ ├── jxl_enc.d.ts │ │ │ ├── jxl_enc_mt.worker.js │ │ │ └── jxl_enc_mt_simd.worker.js │ │ ├── dec │ │ │ ├── jxl_dec.wasm │ │ │ └── jxl_dec.d.ts │ │ ├── package.json │ │ └── pre.js │ ├── .npmignore │ ├── index.ts │ ├── tsconfig.json │ ├── meta.ts │ ├── package.json │ ├── utils.ts │ ├── CHANGELOG.md │ └── decode.ts ├── webp │ ├── codec │ │ ├── enc │ │ │ ├── webp_enc_simd.d.ts │ │ │ ├── webp_enc.wasm │ │ │ ├── webp_enc_simd.wasm │ │ │ ├── README.md │ │ │ └── webp_enc.d.ts │ │ ├── dec │ │ │ ├── webp_dec.wasm │ │ │ ├── webp_dec.d.ts │ │ │ ├── README.md │ │ │ └── webp_dec.cpp │ │ ├── package.json │ │ ├── README.md │ │ ├── pre.js │ │ ├── LICENSE.codec.md │ │ └── Makefile │ ├── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── package.json │ ├── CHANGELOG.md │ ├── meta.ts │ ├── utils.ts │ └── decode.ts ├── jpeg │ ├── .npmignore │ ├── index.ts │ ├── codec │ │ ├── dec │ │ │ ├── mozjpeg_dec.wasm │ │ │ └── mozjpeg_dec.d.ts │ │ ├── enc │ │ │ ├── mozjpeg_enc.wasm │ │ │ └── mozjpeg_enc.d.ts │ │ ├── package.json │ │ ├── pre.js │ │ └── Makefile │ ├── tsconfig.json │ ├── package.json │ ├── utils.ts │ ├── meta.ts │ ├── CHANGELOG.md │ ├── decode.ts │ └── encode.ts ├── png │ ├── index.ts │ ├── codec │ │ ├── pkg │ │ │ ├── squoosh_png_bg.wasm │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── squoosh_png_bg.wasm.d.ts │ │ │ └── squoosh_png.d.ts │ │ ├── README.md │ │ ├── package.json │ │ ├── Cargo.toml │ │ ├── pre.js │ │ └── LICENSE.codec.md │ ├── .npmignore │ ├── tsconfig.json │ ├── meta.ts │ ├── package.json │ ├── CHANGELOG.md │ ├── decode.ts │ └── encode.ts ├── qoi │ ├── codec │ │ ├── dec │ │ │ ├── qoi_dec.wasm │ │ │ ├── qoi_dec.d.ts │ │ │ └── qoi_dec.cpp │ │ ├── enc │ │ │ ├── qoi_enc.wasm │ │ │ ├── qoi_enc.d.ts │ │ │ └── qoi_enc.cpp │ │ ├── README.md │ │ ├── package.json │ │ ├── pre.js │ │ ├── Makefile │ │ └── LICENSE.codec.md │ ├── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── CHANGELOG.md │ ├── meta.ts │ ├── package.json │ ├── utils.ts │ ├── decode.ts │ └── encode.ts └── resize │ ├── lib │ ├── hqx │ │ ├── README.md │ │ ├── pkg │ │ │ ├── squooshhqx_bg.wasm │ │ │ ├── README.md │ │ │ ├── package.json │ │ │ ├── squooshhqx_bg.wasm.d.ts │ │ │ └── squooshhqx.d.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── utils.rs │ │ │ └── lib.rs │ │ ├── Cargo.toml │ │ ├── pre.js │ │ └── squooshhqx.d.ts │ ├── resize │ │ ├── README.md │ │ ├── pkg │ │ │ ├── README.md │ │ │ ├── squoosh_resize_bg.wasm │ │ │ ├── package.json │ │ │ ├── squoosh_resize_bg.wasm.d.ts │ │ │ └── squoosh_resize.d.ts │ │ ├── package.json │ │ ├── build.rs │ │ ├── src │ │ │ ├── utils.rs │ │ │ ├── srgb.rs │ │ │ └── lut.inc │ │ ├── Cargo.toml │ │ ├── pre.js │ │ └── LICENSE.codec.md │ └── magic-kernel │ │ ├── README.md │ │ ├── pkg │ │ ├── README.md │ │ ├── jsquash_magic_kernel_bg.wasm │ │ ├── jsquash_magic_kernel_bg.wasm.d.ts │ │ └── jsquash_magic_kernel.d.ts │ │ ├── package.json │ │ ├── cargo.toml │ │ ├── pre.js │ │ ├── LICENSE.codec.md │ │ └── src │ │ └── lib.rs │ ├── .npmignore │ ├── tsconfig.json │ ├── package.json │ ├── util.ts │ ├── CHANGELOG.md │ └── meta.ts ├── .prettierrc.json ├── examples ├── cloudflare-worker │ ├── .gitignore │ ├── package.json │ ├── wrangler.toml │ └── README.md ├── cloudflare-worker-esm-format │ ├── .gitignore │ ├── wrangler.toml │ ├── package.json │ └── README.md ├── with-deno │ ├── example.jpg │ └── index.js ├── with-node │ ├── example.jpg │ ├── package.json │ └── index.js ├── web-workers │ ├── _headers │ ├── .gitignore │ ├── vite.config.js │ ├── package.json │ ├── index.html │ ├── main.js │ └── worker.js ├── with-vite │ ├── vite.config.js │ ├── .gitignore │ ├── package.json │ └── index.html ├── with-rollup │ ├── package.json │ ├── rollup.config.js │ ├── index.html │ └── main.js ├── with-webpack │ ├── package.json │ ├── webpack.config.js │ └── index.html └── with-cdn │ └── index.html ├── .eslintignore ├── .prettierignore ├── test ├── fixtures │ ├── test.avif │ ├── test.jpeg │ ├── test.jxl │ ├── test.png │ ├── test.qoi │ ├── test.webp │ ├── test-rgb.png │ ├── test-10bit.avif │ ├── test-12bit.avif │ ├── test-16bit.png │ ├── bad-icc-profile.png │ ├── exif-rotated-90.jpeg │ ├── test-animated.webp │ ├── test-grayscale.png │ ├── test-rgb-16bit.png │ ├── exif-rotated-270.jpeg │ ├── test-grayscale-16bit.png │ ├── test-grayscale-alpha.png │ └── test-grayscale-alpha-16bit.png ├── node │ ├── utils.ts │ ├── qoi.test.ts │ ├── webp.test.ts │ └── oxipng.test.ts ├── tsconfig.json └── package.json ├── .git-blame-ignore-revs ├── .eslintrc.json ├── tools ├── rust.Dockerfile ├── build-rust.sh ├── build-cpp.sh └── cpp.Dockerfile ├── turbo.json ├── .github ├── workflows │ └── ci.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── package.json └── .gitignore /packages/oxipng/codec/rust-toolchain: -------------------------------------------------------------------------------- 1 | nightly 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /examples/cloudflare-worker/.gitignore: -------------------------------------------------------------------------------- 1 | worker.js 2 | .wrangler -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | packages/**/*/codec/* 3 | packages/**/*/lib/* 4 | -------------------------------------------------------------------------------- /examples/cloudflare-worker-esm-format/.gitignore: -------------------------------------------------------------------------------- 1 | worker.js 2 | .wrangler -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | packages/**/*/codec/* 3 | packages/**/*/lib/* 4 | -------------------------------------------------------------------------------- /packages/avif/codec/enc/avif_enc_mt.d.ts: -------------------------------------------------------------------------------- 1 | export { default } from './avif_enc'; 2 | -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc_mt.d.ts: -------------------------------------------------------------------------------- 1 | export { default } from './jxl_enc'; 2 | -------------------------------------------------------------------------------- /packages/oxipng/index.ts: -------------------------------------------------------------------------------- 1 | export { default as optimise } from './optimise.js'; 2 | -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc_mt_simd.d.ts: -------------------------------------------------------------------------------- 1 | export { default } from './jxl_enc'; 2 | -------------------------------------------------------------------------------- /packages/webp/codec/enc/webp_enc_simd.d.ts: -------------------------------------------------------------------------------- 1 | export { default } from './webp_enc.js'; 2 | -------------------------------------------------------------------------------- /test/fixtures/test.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test.avif -------------------------------------------------------------------------------- /test/fixtures/test.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test.jpeg -------------------------------------------------------------------------------- /test/fixtures/test.jxl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test.jxl -------------------------------------------------------------------------------- /test/fixtures/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test.png -------------------------------------------------------------------------------- /test/fixtures/test.qoi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test.qoi -------------------------------------------------------------------------------- /test/fixtures/test.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test.webp -------------------------------------------------------------------------------- /test/fixtures/test-rgb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-rgb.png -------------------------------------------------------------------------------- /test/fixtures/test-10bit.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-10bit.avif -------------------------------------------------------------------------------- /test/fixtures/test-12bit.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-12bit.avif -------------------------------------------------------------------------------- /test/fixtures/test-16bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-16bit.png -------------------------------------------------------------------------------- /examples/cloudflare-worker-esm-format/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "upgrade-to-webp" 2 | compatibility_date = "2023-05-06" 3 | -------------------------------------------------------------------------------- /examples/with-deno/example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/examples/with-deno/example.jpg -------------------------------------------------------------------------------- /examples/with-node/example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/examples/with-node/example.jpg -------------------------------------------------------------------------------- /test/fixtures/bad-icc-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/bad-icc-profile.png -------------------------------------------------------------------------------- /test/fixtures/exif-rotated-90.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/exif-rotated-90.jpeg -------------------------------------------------------------------------------- /test/fixtures/test-animated.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-animated.webp -------------------------------------------------------------------------------- /test/fixtures/test-grayscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-grayscale.png -------------------------------------------------------------------------------- /test/fixtures/test-rgb-16bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-rgb-16bit.png -------------------------------------------------------------------------------- /examples/web-workers/_headers: -------------------------------------------------------------------------------- 1 | /* 2 | Cross-Origin-Opener-Policy: same-origin 3 | Cross-Origin-Embedder-Policy: require-corp -------------------------------------------------------------------------------- /packages/avif/index.ts: -------------------------------------------------------------------------------- 1 | export { default as encode } from './encode.js'; 2 | export { default as decode } from './decode.js'; 3 | -------------------------------------------------------------------------------- /packages/jpeg/.npmignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | Makefile 3 | node_modules 4 | codec/*package.json 5 | *.d.ts.map 6 | tsconfig.tsbuildinfo 7 | -------------------------------------------------------------------------------- /packages/jpeg/index.ts: -------------------------------------------------------------------------------- 1 | export { default as encode } from './encode.js'; 2 | export { default as decode } from './decode.js'; 3 | -------------------------------------------------------------------------------- /packages/jxl/.npmignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | Makefile 3 | node_modules 4 | codec/*package.json 5 | *.d.ts.map 6 | tsconfig.tsbuildinfo 7 | -------------------------------------------------------------------------------- /packages/jxl/codec/dec/jxl_dec.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/jxl/codec/dec/jxl_dec.wasm -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/jxl/codec/enc/jxl_enc.wasm -------------------------------------------------------------------------------- /packages/png/index.ts: -------------------------------------------------------------------------------- 1 | export { default as encode } from './encode.js'; 2 | export { default as decode } from './decode.js'; 3 | -------------------------------------------------------------------------------- /packages/qoi/codec/dec/qoi_dec.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/qoi/codec/dec/qoi_dec.wasm -------------------------------------------------------------------------------- /packages/qoi/codec/enc/qoi_enc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/qoi/codec/enc/qoi_enc.wasm -------------------------------------------------------------------------------- /packages/qoi/index.ts: -------------------------------------------------------------------------------- 1 | export { default as encode } from './encode.js'; 2 | export { default as decode } from './decode.js'; 3 | -------------------------------------------------------------------------------- /packages/webp/index.ts: -------------------------------------------------------------------------------- 1 | export { default as encode } from './encode.js'; 2 | export { default as decode } from './decode.js'; 3 | -------------------------------------------------------------------------------- /test/fixtures/exif-rotated-270.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/exif-rotated-270.jpeg -------------------------------------------------------------------------------- /packages/avif/.npmignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *Makefile 3 | node_modules 4 | codec/*package.json 5 | *.d.ts.map 6 | tsconfig.tsbuildinfo 7 | -------------------------------------------------------------------------------- /packages/avif/codec/dec/avif_dec.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/avif/codec/dec/avif_dec.wasm -------------------------------------------------------------------------------- /packages/avif/codec/enc/avif_enc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/avif/codec/enc/avif_enc.wasm -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc_mt.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/jxl/codec/enc/jxl_enc_mt.wasm -------------------------------------------------------------------------------- /packages/qoi/codec/README.md: -------------------------------------------------------------------------------- 1 | # QOI 2 | 3 | - Source: 4 | - Version: N/A 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/webp/codec/dec/webp_dec.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/webp/codec/dec/webp_dec.wasm -------------------------------------------------------------------------------- /packages/webp/codec/enc/webp_enc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/webp/codec/enc/webp_enc.wasm -------------------------------------------------------------------------------- /test/fixtures/test-grayscale-16bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-grayscale-16bit.png -------------------------------------------------------------------------------- /test/fixtures/test-grayscale-alpha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-grayscale-alpha.png -------------------------------------------------------------------------------- /packages/avif/codec/enc/avif_enc_mt.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/avif/codec/enc/avif_enc_mt.wasm -------------------------------------------------------------------------------- /packages/jpeg/codec/dec/mozjpeg_dec.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/jpeg/codec/dec/mozjpeg_dec.wasm -------------------------------------------------------------------------------- /packages/jpeg/codec/enc/mozjpeg_enc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/jpeg/codec/enc/mozjpeg_enc.wasm -------------------------------------------------------------------------------- /packages/webp/.npmignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.o 3 | Makefile 4 | node_modules 5 | codec/*package.json 6 | *.d.ts.map 7 | tsconfig.tsbuildinfo 8 | -------------------------------------------------------------------------------- /packages/webp/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "../../../tools/build-cpp.sh" 4 | }, 5 | "type": "module" 6 | } -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc_mt_simd.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/jxl/codec/enc/jxl_enc_mt_simd.wasm -------------------------------------------------------------------------------- /packages/png/codec/pkg/squoosh_png_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/png/codec/pkg/squoosh_png_bg.wasm -------------------------------------------------------------------------------- /packages/webp/codec/README.md: -------------------------------------------------------------------------------- 1 | # WebP 2 | 3 | - Source: https://github.com/webmproject/libwebp 4 | - Version: v1.0.2 5 | - License: BSD 6 | -------------------------------------------------------------------------------- /packages/webp/codec/enc/webp_enc_simd.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/webp/codec/enc/webp_enc_simd.wasm -------------------------------------------------------------------------------- /test/fixtures/test-grayscale-alpha-16bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/test/fixtures/test-grayscale-alpha-16bit.png -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # .git-blame-ignore-revs 2 | # Ran prettier across all files in packages/ 3 | 7d8977b3a45b17bffdf8b2d46e3597391ba3bfe3 4 | -------------------------------------------------------------------------------- /packages/oxipng/codec/README.md: -------------------------------------------------------------------------------- 1 | # OxiPNG 2 | 3 | - Source: 4 | - Version: v3.0.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg/README.md: -------------------------------------------------------------------------------- 1 | # OxiPNG 2 | 3 | - Source: 4 | - Version: v3.0.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/README.md: -------------------------------------------------------------------------------- 1 | # HQX 2 | 3 | - Source: 4 | - Version: v0.1.2 5 | - License: Apache 2.0 6 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/pkg/squooshhqx_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/resize/lib/hqx/pkg/squooshhqx_bg.wasm -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg/squoosh_oxipng_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/oxipng/codec/pkg/squoosh_oxipng_bg.wasm -------------------------------------------------------------------------------- /packages/png/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | codec/**/*package.json 3 | *.d.ts.map 4 | tsconfig.tsbuildinfo 5 | target 6 | src 7 | Cargo.lock 8 | Cargo.toml -------------------------------------------------------------------------------- /packages/png/codec/README.md: -------------------------------------------------------------------------------- 1 | # PNG 2 | 3 | - Source: https://github.com/GoogleChromeLabs/squoosh 4 | - Version: v1.12.0 5 | - License: Apache-2.0 6 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/pkg/README.md: -------------------------------------------------------------------------------- 1 | # HQX 2 | 3 | - Source: 4 | - Version: v0.1.2 5 | - License: Apache 2.0 6 | -------------------------------------------------------------------------------- /packages/jpeg/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "EMSDK_VERSION=3.1.57 ../../../tools/build-cpp.sh" 4 | }, 5 | "type": "module" 6 | } -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg-parallel/README.md: -------------------------------------------------------------------------------- 1 | # OxiPNG 2 | 3 | - Source: 4 | - Version: v3.0.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/png/codec/pkg/README.md: -------------------------------------------------------------------------------- 1 | # PNG 2 | 3 | - Source: https://github.com/GoogleChromeLabs/squoosh 4 | - Version: v1.12.0 5 | - License: Apache-2.0 6 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/README.md: -------------------------------------------------------------------------------- 1 | # Resize 2 | 3 | - Source: 4 | - Version: v0.3.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Resize 2 | 3 | - Source: 4 | - Version: v0.3.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/jxl/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jxl", 3 | "scripts": { 4 | "build": "../../../tools/build-cpp.sh" 5 | }, 6 | "type": "module" 7 | } 8 | -------------------------------------------------------------------------------- /packages/qoi/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "EMSDK_VERSION=3.1.57 ../../../tools/build-cpp.sh" 4 | }, 5 | "type": "module" 6 | } 7 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/pkg/squoosh_resize_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/resize/lib/resize/pkg/squoosh_resize_bg.wasm -------------------------------------------------------------------------------- /packages/qoi/.npmignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.o 3 | Makefile 4 | node_modules 5 | codec/*package.json 6 | codec/*package-lock.json 7 | *.d.ts.map 8 | tsconfig.tsbuildinfo 9 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/README.md: -------------------------------------------------------------------------------- 1 | # Magic Kernel 2 | 3 | - Source: https://github.com/SevInf/magic-kernel-rust 4 | - Version: v0.1.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg-parallel/squoosh_oxipng_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/oxipng/codec/pkg-parallel/squoosh_oxipng_bg.wasm -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/pkg/README.md: -------------------------------------------------------------------------------- 1 | # Magic Kernel 2 | 3 | - Source: https://github.com/SevInf/magic-kernel-rust 4 | - Version: v0.1.0 5 | - License: MIT 6 | -------------------------------------------------------------------------------- /packages/jxl/index.ts: -------------------------------------------------------------------------------- 1 | export { default as encode } from './encode.js'; 2 | export { default as decode } from './decode.js'; 3 | export { EncodeOptions } from './meta.js'; 4 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/pkg/jsquash_magic_kernel_bg.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamsinclair/jSquash/HEAD/packages/resize/lib/magic-kernel/pkg/jsquash_magic_kernel_bg.wasm -------------------------------------------------------------------------------- /packages/avif/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "EMSDK_VERSION=3.1.57 DEFAULT_CFLAGS='-Oz -flto' ../../../tools/build-cpp.sh" 4 | }, 5 | "type": "module" 6 | } 7 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "plugins": ["@typescript-eslint", "import"], 4 | "root": true, 5 | "rules": { 6 | "import/extensions": ["error", "always"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/resize/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.d.ts.map 3 | tsconfig.tsbuildinfo 4 | src 5 | target 6 | *.rs 7 | cargo.toml 8 | Cargo.lock 9 | pkg/package.json 10 | lib/*/package.json 11 | lib/*/pre.js 12 | -------------------------------------------------------------------------------- /packages/png/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squoosh-png", 3 | "scripts": { 4 | "build": "../../../tools/build-rust.sh && npm run patch-pre-script", 5 | "patch-pre-script": "cat pre.js >> pkg/squoosh_png.js" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /examples/with-vite/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | 3 | export default defineConfig({ 4 | optimizeDeps: { 5 | exclude: ["@jsquash/avif", "@jsquash/jpeg", "@jsquash/jxl", "@jsquash/png", "@jsquash/webp"] 6 | } 7 | }) 8 | -------------------------------------------------------------------------------- /packages/oxipng/.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | codec/**/*package.json 4 | !codec/pkg-parallel/package.json 5 | *.d.ts.map 6 | codec/src 7 | codec/rust-toolchain 8 | codec/build.sh 9 | Cargo.lock 10 | Cargo.toml 11 | tsconfig.tsbuildinfo -------------------------------------------------------------------------------- /tools/rust.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG RUST_IMG=rust:1.77 2 | 3 | FROM $RUST_IMG AS rust 4 | ARG RUST_IMG 5 | 6 | RUN cargo install wasm-pack 7 | 8 | WORKDIR /src 9 | CMD ["sh", "-c", "rm -rf pkg && wasm-pack build --target web -- --verbose --locked && rm pkg/.gitignore"] -------------------------------------------------------------------------------- /packages/resize/lib/hqx/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squooshhqx", 3 | "scripts": { 4 | "build": "../../../../tools/build-rust.sh && npm run patch-pre-script", 5 | "patch-pre-script": "cat pre.js >> pkg/squooshhqx.js" 6 | }, 7 | "type": "module" 8 | } -------------------------------------------------------------------------------- /packages/jxl/codec/dec/jxl_dec.d.ts: -------------------------------------------------------------------------------- 1 | export interface JXLModule extends EmscriptenWasm.Module { 2 | decode(data: BufferSource): ImageData | null; 3 | } 4 | 5 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 6 | 7 | export default moduleFactory; 8 | -------------------------------------------------------------------------------- /packages/qoi/codec/dec/qoi_dec.d.ts: -------------------------------------------------------------------------------- 1 | export interface QOIModule extends EmscriptenWasm.Module { 2 | decode(data: BufferSource): ImageData | null; 3 | } 4 | 5 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 6 | 7 | export default moduleFactory; 8 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squoosh-resize", 3 | "scripts": { 4 | "build": "../../../../tools/build-rust.sh && npm run patch-pre-script", 5 | "patch-pre-script": "cat pre.js >> pkg/squoosh_resize.js" 6 | }, 7 | "type": "module" 8 | } -------------------------------------------------------------------------------- /packages/webp/codec/dec/webp_dec.d.ts: -------------------------------------------------------------------------------- 1 | export interface WebPModule extends EmscriptenWasm.Module { 2 | decode(data: BufferSource): ImageData | null; 3 | } 4 | 5 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 6 | 7 | export default moduleFactory; 8 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["./dist"] 7 | }, 8 | "build:codec": { 9 | "outputs": ["./codec"] 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /packages/oxipng/codec/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oxipng", 3 | "scripts": { 4 | "build": "./build.sh && npm run patch-pre-script", 5 | "patch-pre-script": "cat pre.js >> pkg/squoosh_oxipng.js && cat pre.js >> pkg-parallel/squoosh_oxipng.js" 6 | }, 7 | "type": "module" 8 | } 9 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsquash-magic-kernel", 3 | "scripts": { 4 | "build": "../../../tools/build-rust.sh && npm run patch-pre-script", 5 | "patch-pre-script": "cat pre.js >> pkg/jsquash_magic_kernel.js.js" 6 | }, 7 | "type": "module" 8 | } 9 | -------------------------------------------------------------------------------- /packages/jpeg/codec/dec/mozjpeg_dec.d.ts: -------------------------------------------------------------------------------- 1 | export interface MozJPEGModule extends EmscriptenWasm.Module { 2 | decode(data: BufferSource, preserveOrientation: boolean): ImageData | null; 3 | } 4 | 5 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 6 | 7 | export default moduleFactory; 8 | -------------------------------------------------------------------------------- /packages/qoi/codec/enc/qoi_enc.d.ts: -------------------------------------------------------------------------------- 1 | export interface QOIModule extends EmscriptenWasm.Module { 2 | encode( 3 | data: BufferSource, 4 | width: number, 5 | height: number 6 | ): Uint8Array; 7 | } 8 | 9 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 10 | 11 | export default moduleFactory; 12 | -------------------------------------------------------------------------------- /packages/oxipng/codec/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | rm -rf pkg,{-parallel} 6 | export CFLAGS="${CFLAGS} -DUNALIGNED_ACCESS_IS_FAST=1" 7 | wasm-pack build -t web 8 | RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' wasm-pack build -t web -d pkg-parallel . -- -Z build-std=panic_abort,std --features=parallel 9 | rm pkg{,-parallel}/.gitignore 10 | -------------------------------------------------------------------------------- /packages/avif/codec/dec/Readme.md: -------------------------------------------------------------------------------- 1 | # AVIF decoder 2 | 3 | - Source: 4 | - Version: v1.0.1 5 | 6 | ## Example 7 | 8 | See `example.html` 9 | 10 | ## API 11 | 12 | ### `RawImage decode(std::string buffer)` 13 | 14 | Decodes the given avif buffer into raw RGBA. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`. 15 | -------------------------------------------------------------------------------- /examples/with-vite/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/web-workers/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squooshhqx", 3 | "collaborators": [ 4 | "Surma " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "squooshhqx_bg.wasm", 9 | "squooshhqx.js", 10 | "squooshhqx.d.ts" 11 | ], 12 | "module": "squooshhqx.js", 13 | "types": "squooshhqx.d.ts", 14 | "sideEffects": [ 15 | "./snippets/*" 16 | ] 17 | } -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squoosh-oxipng", 3 | "collaborators": [ 4 | "Ingvar Stepanyan " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "squoosh_oxipng_bg.wasm", 9 | "squoosh_oxipng.js", 10 | "squoosh_oxipng.d.ts" 11 | ], 12 | "module": "squoosh_oxipng.js", 13 | "types": "squoosh_oxipng.d.ts", 14 | "type": "module" 15 | } 16 | -------------------------------------------------------------------------------- /packages/png/codec/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squoosh-png", 3 | "type": "module", 4 | "collaborators": [ 5 | "Surma " 6 | ], 7 | "version": "0.1.0", 8 | "files": [ 9 | "squoosh_png_bg.wasm", 10 | "squoosh_png.js", 11 | "squoosh_png.d.ts" 12 | ], 13 | "main": "squoosh_png.js", 14 | "types": "squoosh_png.d.ts", 15 | "sideEffects": [ 16 | "./snippets/*" 17 | ] 18 | } -------------------------------------------------------------------------------- /packages/resize/lib/resize/pkg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squoosh-resize", 3 | "collaborators": [ 4 | "Surma " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "squoosh_resize_bg.wasm", 9 | "squoosh_resize.js", 10 | "squoosh_resize.d.ts" 11 | ], 12 | "module": "squoosh_resize.js", 13 | "types": "squoosh_resize.d.ts", 14 | "sideEffects": [ 15 | "./snippets/*" 16 | ] 17 | } -------------------------------------------------------------------------------- /examples/with-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-node", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "dependencies": { 10 | "@jsquash/jpeg": "^1.3.0", 11 | "@jsquash/png": "^3.0.0" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "type": "module" 17 | } 18 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg-parallel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squoosh-oxipng", 3 | "collaborators": [ 4 | "Ingvar Stepanyan " 5 | ], 6 | "version": "0.1.0", 7 | "files": [ 8 | "squoosh_oxipng_bg.wasm", 9 | "squoosh_oxipng.js", 10 | "squoosh_oxipng.d.ts" 11 | ], 12 | "module": "squoosh_oxipng.js", 13 | "types": "squoosh_oxipng.d.ts", 14 | "sideEffects": false, 15 | "type": "module" 16 | } 17 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/pkg/squooshhqx_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export function resize(a: number, b: number, c: number, d: number, e: number, f: number): void; 5 | export function __wbindgen_add_to_stack_pointer(a: number): number; 6 | export function __wbindgen_malloc(a: number, b: number): number; 7 | export function __wbindgen_free(a: number, b: number, c: number): void; 8 | -------------------------------------------------------------------------------- /tools/build-rust.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | if [ ! -z "$RUST_IMG" ] 7 | then 8 | # Get part after ":" (https://stackoverflow.com/a/15149278/439965). 9 | IMG_SUFFIX=-${RUST_IMG#*:} 10 | fi 11 | IMG_NAME=squoosh-rust$IMG_SUFFIX 12 | docker build -t $IMG_NAME --build-arg RUST_IMG - < "$SCRIPTDIR/rust.Dockerfile" 13 | docker run -it --rm -v $PWD:/src $IMG_NAME "$@" 14 | -------------------------------------------------------------------------------- /packages/avif/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/jpeg/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/jxl/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/png/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/qoi/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/webp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/web-workers/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | 3 | export default defineConfig({ 4 | optimizeDeps: { 5 | exclude: ["@jsquash/avif", "@jsquash/jpeg", "@jsquash/jxl", "@jsquash/png", "@jsquash/webp"] 6 | }, 7 | server: { 8 | headers: { 9 | 'Cross-Origin-Opener-Policy': 'same-origin', 10 | 'Cross-Origin-Embedder-Policy': 'require-corp' 11 | } 12 | }, 13 | worker: { 14 | format: 'es' 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /test/node/utils.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'node:fs'; 2 | import path from 'node:path'; 3 | 4 | export async function importWasmModule(path) { 5 | const fileBuffer = await fs.readFile(path); 6 | return WebAssembly.compile(fileBuffer); 7 | } 8 | 9 | export function getFixturesImage(imagePath: string) { 10 | const filePath = path.resolve(`fixtures/${imagePath}`); 11 | return fs.readFile(filePath).then((buffer) => buffer.buffer as ArrayBuffer); 12 | } 13 | -------------------------------------------------------------------------------- /packages/webp/codec/dec/README.md: -------------------------------------------------------------------------------- 1 | # WebP decoder 2 | 3 | - Source: 4 | - Version: v1.0.2 5 | 6 | ## Example 7 | 8 | See `example.html` 9 | 10 | ## API 11 | 12 | ### `int version()` 13 | 14 | Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c 15 | 16 | ### `RawImage decode(std::string buffer)` 17 | 18 | Decodes the given webp buffer into raw RGBA. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`. 19 | -------------------------------------------------------------------------------- /examples/cloudflare-worker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-worker-upgrade-to-webp", 3 | "version": "1.0.0", 4 | "main": "worker.js", 5 | "scripts": { 6 | "start": "wrangler dev src/index.js" 7 | }, 8 | "dependencies": { 9 | "@jsquash/jpeg": "file:../../packages/jpeg/dist", 10 | "@jsquash/png": "file:../../packages/png/dist", 11 | "@jsquash/webp": "file:../../packages/webp/dist" 12 | }, 13 | "devDependencies": { 14 | "wrangler": "^3.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/pkg/squoosh_resize_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export function resize(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number): void; 5 | export function __wbindgen_add_to_stack_pointer(a: number): number; 6 | export function __wbindgen_malloc(a: number, b: number): number; 7 | export function __wbindgen_free(a: number, b: number, c: number): void; 8 | -------------------------------------------------------------------------------- /examples/cloudflare-worker/wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "upgrade-to-webp" 2 | compatibility_date = "2021-11-06" 3 | 4 | [wasm_modules] 5 | # @Note we need to manually include the wasm modules used for Cloudflare workers 6 | # These modules will be injected as global vars into the worker 7 | JPEG_DEC_WASM = "node_modules/@jsquash/jpeg/codec/dec/mozjpeg_dec.wasm" 8 | PNG_DEC_WASM = "node_modules/@jsquash/png/codec/pkg/squoosh_png_bg.wasm" 9 | WEBP_ENC_WASM = "node_modules/@jsquash/webp/codec/enc/webp_enc_simd.wasm" 10 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/pkg/jsquash_magic_kernel_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export function resize(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number): number; 5 | export function __wbindgen_free(a: number, b: number, c: number): void; 6 | export function __wbindgen_malloc(a: number, b: number): number; 7 | export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number; 8 | -------------------------------------------------------------------------------- /packages/resize/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/cloudflare-worker-esm-format/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloudflare-worker-esm-format-upgrade-to-webp", 3 | "version": "1.0.0", 4 | "main": "worker.js", 5 | "scripts": { 6 | "start": "wrangler dev src/index.js" 7 | }, 8 | "dependencies": { 9 | "@jsquash/jpeg": "file:../../packages/jpeg/dist", 10 | "@jsquash/png": "file:../../packages/png/dist", 11 | "@jsquash/webp": "file:../../packages/webp/dist" 12 | }, 13 | "devDependencies": { 14 | "wrangler": "^3.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/with-rollup/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-rollup-example", 3 | "scripts": { 4 | "start": "rollup -c" 5 | }, 6 | "dependencies": { 7 | "@jsquash/avif": "^1.1.0", 8 | "@jsquash/jpeg": "^1.2.0", 9 | "@jsquash/jxl": "^1.0.0", 10 | "@jsquash/png": "^2.0.0", 11 | "@jsquash/webp": "^1.2.0", 12 | "@rollup/plugin-node-resolve": "^13.0.6", 13 | "@web/rollup-plugin-import-meta-assets": "^1.0.7", 14 | "rollup": "^2.60.0", 15 | "rollup-plugin-serve": "^1.1.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/with-vite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-vite", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@jsquash/avif": "^1.1.0", 13 | "@jsquash/jpeg": "^1.2.0", 14 | "@jsquash/jxl": "^1.0.0", 15 | "@jsquash/png": "^2.0.0", 16 | "@jsquash/webp": "^1.2.0" 17 | }, 18 | "devDependencies": { 19 | "vite": "^4.3.9" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/avif/codec/dec/avif_dec.d.ts: -------------------------------------------------------------------------------- 1 | export interface AVIFModule extends EmscriptenWasm.Module { 2 | decode(data: BufferSource, bitDepth: 10 | 12 | 16): { data: Uint16Array, height: number, width: number } | null; 3 | decode(data: BufferSource, bitDepth: 8): ImageData | null; 4 | decode(data: BufferSource, bitDepth: 8 | 10 | 12 | 16): { data: Uint16Array, height: number, width: number } | ImageData | null; 5 | } 6 | 7 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 8 | 9 | export default moduleFactory; 10 | -------------------------------------------------------------------------------- /packages/oxipng/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2019", 4 | "downlevelIteration": true, 5 | "module": "esnext", 6 | "jsx": "react", 7 | "jsxFactory": "h", 8 | "strict": true, 9 | "moduleResolution": "node", 10 | "composite": true, 11 | "declarationMap": true, 12 | "baseUrl": "./", 13 | "rootDir": "./", 14 | "outDir": "dist", 15 | "allowSyntheticDefaultImports": true, 16 | "lib": [ 17 | "ESNext", 18 | "WebWorker" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/webp/codec/enc/README.md: -------------------------------------------------------------------------------- 1 | # WebP encoder 2 | 3 | - Source: 4 | - Version: v1.0.2 5 | 6 | ## Dependencies 7 | 8 | - Docker 9 | 10 | ## Example 11 | 12 | See `example.html` 13 | 14 | ## API 15 | 16 | ### `int version()` 17 | 18 | Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c 19 | 20 | ### `UInt8Array encode(uint8_t* image_buffer, int image_width, int image_height, WebPConfig config)` 21 | 22 | Encodes the given image with given dimension to WebP. 23 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "lib": ["ESNext", "DOM"], 11 | "noImplicitAny": false, 12 | "typeRoots": ["./node_modules/@types", "./node_modules"], 13 | "types": ["node"], 14 | "outDir": "./dist/node" 15 | }, 16 | "include": ["node/**/*"], 17 | "exclude": ["node_modules"] 18 | } 19 | -------------------------------------------------------------------------------- /examples/web-workers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "web-workers", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build && cp _headers dist/", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@jsquash/avif": "^2.1.0", 13 | "@jsquash/jpeg": "^1.6.0", 14 | "@jsquash/jxl": "^1.1.0", 15 | "@jsquash/png": "^3.0.1", 16 | "@jsquash/webp": "^1.5.0" 17 | }, 18 | "devDependencies": { 19 | "vite": "^6.3.5" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/png/codec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squoosh-png" 3 | version = "0.1.0" 4 | authors = ["Surma "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [package.metadata.wasm-pack.profile.release] 9 | wasm-opt = ["-O", "--no-validation"] 10 | 11 | [lib] 12 | crate-type = ["cdylib"] 13 | 14 | [dependencies] 15 | png = "0.17.10" 16 | wasm-bindgen = "0.2.89" 17 | "js-sys" = "0.3.66" 18 | web-sys = { version = "0.3.66", features = ["ImageData"] } 19 | rgb = "0.8.37" 20 | 21 | [profile.release] 22 | lto = true 23 | opt-level = "s" 24 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "jsquash-magic-kernel" 3 | version = "0.1.0" 4 | authors = ["Jamie "] 5 | edition = "2021" 6 | publish = false 7 | 8 | [package.metadata.wasm-pack.profile.release] 9 | wasm-opt = ["-O", "--no-validation"] 10 | 11 | [lib] 12 | crate-type = ["cdylib"] 13 | 14 | [dependencies] 15 | magic-kernel = "0.1.0" 16 | wasm-bindgen = "0.2.95" 17 | js-sys = "0.3.72" 18 | web-sys = { version = "0.3.72", features = ["ImageData"] } 19 | 20 | [profile.release] 21 | lto = true 22 | opt-level = "s" 23 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg/squoosh_oxipng_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export function optimise(a: number, b: number, c: number, d: number, e: number, f: number): void; 5 | export function optimise_raw(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number): void; 6 | export function __wbindgen_add_to_stack_pointer(a: number): number; 7 | export function __wbindgen_malloc(a: number, b: number): number; 8 | export function __wbindgen_free(a: number, b: number, c: number): void; 9 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ['main'] 6 | pull_request: 7 | types: [opened, synchronize] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 22 17 | - name: Install 18 | run: npm install 19 | - name: Lint 20 | run: npm run lint 21 | - name: Build 22 | run: npm run build 23 | - name: Integration Tests 24 | run: cd test && npm install && npm test 25 | -------------------------------------------------------------------------------- /examples/with-rollup/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { nodeResolve } from '@rollup/plugin-node-resolve'; 2 | import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets'; 3 | import serve from 'rollup-plugin-serve'; 4 | 5 | export default { 6 | input: 'main.js', 7 | output: { 8 | dir: 'dist', 9 | format: 'es' 10 | }, 11 | plugins: [ 12 | nodeResolve(), // Needed to bundle the assets from node_modules 13 | importMetaAssets(), // Needed to resolve Wasm imports 14 | serve({ 15 | open: true 16 | }) // Optional, for convenience when testing example 17 | ] 18 | }; 19 | -------------------------------------------------------------------------------- /examples/with-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "with-webpack-example", 3 | "scripts": { 4 | "start": "webpack serve" 5 | }, 6 | "dependencies": { 7 | "@jsquash/avif": "file:../../packages/avif/dist", 8 | "@jsquash/jpeg": "file:../../packages/jpeg/dist", 9 | "@jsquash/jxl": "file:../../packages/jxl/dist", 10 | "@jsquash/png": "file:../../packages/png/dist", 11 | "@jsquash/webp": "file:../../packages/webp/dist", 12 | "html-webpack-plugin": "^5.5.0", 13 | "webpack": "^5.64.1", 14 | "webpack-cli": "^4.9.1", 15 | "webpack-dev-server": "^4.5.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tools/build-cpp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ -z "$EMSDK_VERSION" ]; then 5 | EMSDK_VERSION=2.0.34 6 | fi 7 | 8 | if [ -z "$DEFAULT_CFLAGS" ]; then 9 | DEFAULT_CFLAGS="-O3 -flto" 10 | fi 11 | 12 | BUILD_DIR=$(pwd) 13 | SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 14 | echo "EMSDK_VERSION: $EMSDK_VERSION" 15 | echo "BUILD_DIR: $BUILD_DIR" 16 | echo "SCRIPTDIR: $SCRIPTDIR" 17 | docker build --build-arg EMSDK_VERSION=$EMSDK_VERSION --build-arg DEFAULT_CFLAGS="$DEFAULT_CFLAGS" -t jsquash-cpp-build - < $SCRIPTDIR/cpp.Dockerfile 18 | docker run --rm -v $BUILD_DIR:/src jsquash-cpp-build "$@" 19 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/build.rs: -------------------------------------------------------------------------------- 1 | include!("./src/srgb.rs"); 2 | 3 | use std::io::Write; 4 | 5 | fn main() -> std::io::Result<()> { 6 | let mut srgb_to_linear_lut = String::from("static SRGB_TO_LINEAR_LUT: [f32; 256] = ["); 7 | for i in 0..256 { 8 | srgb_to_linear_lut.push_str(&format!("{0:.7}", srgb_to_linear((i as f32) / 255.0))); 9 | srgb_to_linear_lut.push_str(","); 10 | } 11 | srgb_to_linear_lut.pop().unwrap(); 12 | srgb_to_linear_lut.push_str("];"); 13 | 14 | let mut file = std::fs::File::create("src/lut.inc")?; 15 | file.write_all(srgb_to_linear_lut.as_bytes())?; 16 | Ok(()) 17 | } 18 | -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc.d.ts: -------------------------------------------------------------------------------- 1 | export interface EncodeOptions { 2 | effort: number; 3 | quality: number; 4 | progressive: boolean; 5 | epf: number; 6 | lossyPalette: boolean; 7 | decodingSpeedTier: number; 8 | photonNoiseIso: number; 9 | lossyModular: boolean; 10 | lossless: boolean; 11 | } 12 | 13 | export interface JXLModule extends EmscriptenWasm.Module { 14 | encode( 15 | data: BufferSource, 16 | width: number, 17 | height: number, 18 | options: EncodeOptions, 19 | ): Uint8Array | null; 20 | } 21 | 22 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 23 | 24 | export default moduleFactory; 25 | -------------------------------------------------------------------------------- /examples/with-deno/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * To run this example with Deno, run the following command: 3 | * deno run --allow-net --allow-read --allow-write index.js 4 | * 5 | * Note: Requires Deno versions greater than v1.39.0, which introduced the ImageData Web API 6 | */ 7 | import { decode } from 'https://unpkg.com/@jsquash/jpeg@latest?module'; 8 | import { encode } from 'https://unpkg.com/@jsquash/webp@latest?module'; 9 | 10 | const jpegBuffer = await Deno.readFile('example.jpg'); 11 | const imageData = await decode(jpegBuffer); 12 | const webpBuffer = await encode(imageData); 13 | 14 | // Deno writeFile requires a Uint8Array as input 15 | Deno.writeFile('example.webp', new Uint8Array(webpBuffer)); 16 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/src/utils.rs: -------------------------------------------------------------------------------- 1 | use cfg_if::cfg_if; 2 | 3 | cfg_if! { 4 | // When the `console_error_panic_hook` feature is enabled, we can call the 5 | // `set_panic_hook` function at least once during initialization, and then 6 | // we will get better error messages if our code ever panics. 7 | // 8 | // For more details see 9 | // https://github.com/rustwasm/console_error_panic_hook#readme 10 | if #[cfg(feature = "console_error_panic_hook")] { 11 | extern crate console_error_panic_hook; 12 | pub use self::console_error_panic_hook::set_once as set_panic_hook; 13 | } else { 14 | #[inline] 15 | pub fn set_panic_hook() {} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/src/utils.rs: -------------------------------------------------------------------------------- 1 | use cfg_if::cfg_if; 2 | 3 | cfg_if! { 4 | // When the `console_error_panic_hook` feature is enabled, we can call the 5 | // `set_panic_hook` function at least once during initialization, and then 6 | // we will get better error messages if our code ever panics. 7 | // 8 | // For more details see 9 | // https://github.com/rustwasm/console_error_panic_hook#readme 10 | if #[cfg(feature = "console_error_panic_hook")] { 11 | extern crate console_error_panic_hook; 12 | pub use self::console_error_panic_hook::set_once as set_panic_hook; 13 | } else { 14 | #[inline] 15 | pub fn set_panic_hook() {} 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: feature-request 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /packages/qoi/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/qoi@1.1.0 4 | 5 | ### Adds 6 | 7 | - Adds support for only providing a module option override to the `init` function directly 8 | 9 | **Example:** 10 | ```ts 11 | import encode, { init } from '@jsquash/qoi/encode'; 12 | await init({ 13 | locateFile: (path) => { 14 | const remoteLocation = 'https://cdn.mydomain.com/wasm'; 15 | return remoteLocation + path; 16 | } 17 | }); 18 | const buffer = await encode(/* image data */); 19 | ``` 20 | 21 | ### Fixes 22 | 23 | - Updates `locateFile` emscripten module option type to support prefix parameter. 24 | 25 | ## @jsquash/qoi@1.0.0 26 | 27 | ### Adds 28 | 29 | - Initial release of the QOI codec 30 | -------------------------------------------------------------------------------- /packages/oxipng/codec/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squoosh-oxipng" 3 | version = "0.1.0" 4 | authors = ["Ingvar Stepanyan "] 5 | edition = "2018" 6 | publish = false 7 | 8 | [package.metadata.wasm-pack.profile.release] 9 | wasm-opt = ["-O", "--no-validation"] 10 | 11 | [lib] 12 | crate-type = ["cdylib"] 13 | 14 | [dependencies] 15 | oxipng = { version = "9.0", default-features = false, features = ["freestanding"] } 16 | wasm-bindgen = "0.2.92" 17 | log = { version = "0.4.11", features = ["release_max_level_off"] } 18 | wasm-bindgen-rayon = { version = "1.2.1", optional = true } 19 | 20 | [profile.release] 21 | lto = true 22 | opt-level = "s" 23 | 24 | [features] 25 | parallel = ["oxipng/parallel", "wasm-bindgen-rayon"] 26 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/src/srgb.rs: -------------------------------------------------------------------------------- 1 | pub trait Clamp: std::cmp::PartialOrd + Sized { 2 | fn clamp(self, min: Self, max: Self) -> Self { 3 | if self.lt(&min) { 4 | min 5 | } else if self.gt(&max) { 6 | max 7 | } else { 8 | self 9 | } 10 | } 11 | } 12 | 13 | impl Clamp for f32 {} 14 | 15 | pub fn srgb_to_linear(v: f32) -> f32 { 16 | if v < 0.04045 { 17 | v / 12.92 18 | } else { 19 | ((v + 0.055) / 1.055).powf(2.4).clamp(0.0, 1.0) 20 | } 21 | } 22 | 23 | pub fn linear_to_srgb(v: f32) -> f32 { 24 | if v < 0.0031308 { 25 | v * 12.92 26 | } else { 27 | (1.055 * v.powf(1.0 / 2.4) - 0.055).clamp(0.0, 1.0) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "integration-tests", 3 | "scripts": { 4 | "test": "rm -rf dist && tsc && ava dist/node/*.test.js" 5 | }, 6 | "devDependencies": { 7 | "@jsquash/avif": "file:../packages/avif/dist", 8 | "@jsquash/jpeg": "file:../packages/jpeg/dist", 9 | "@jsquash/jxl": "file:../packages/jxl/dist", 10 | "@jsquash/oxipng": "file:../packages/oxipng/dist", 11 | "@jsquash/png": "file:../packages/png/dist", 12 | "@jsquash/qoi": "file:../packages/qoi/dist", 13 | "@jsquash/resize": "file:../packages/resize/dist", 14 | "@jsquash/webp": "file:../packages/webp/dist", 15 | "@types/node": "^22.15.19", 16 | "ava": "^6.3.0", 17 | "typescript": "^5.8.3" 18 | }, 19 | "private": true, 20 | "type": "module" 21 | } 22 | -------------------------------------------------------------------------------- /packages/qoi/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | export const label = 'QOI'; 14 | export const mimeType = 'image/qoi'; 15 | export const extension = 'qoi'; 16 | -------------------------------------------------------------------------------- /packages/png/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | export const label = 'PNG'; 15 | export const mimeType = 'image/png'; 16 | export const extension = 'png'; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsquash", 3 | "version": "1.0.0", 4 | "private": true, 5 | "repository": "git@github.com:jamsinclair/jSquash.git", 6 | "workspaces": [ 7 | "packages/*" 8 | ], 9 | "scripts": { 10 | "build": "turbo run build", 11 | "lint": "prettier -l \"packages/**/*.{js,ts}\" test/**/*.ts && eslint \"packages/**/*.{js,ts}\"", 12 | "format": "prettier -lw \"packages/**/*.{js,ts}\" test/**/*.ts" 13 | }, 14 | "license": "Apache-2.0", 15 | "devDependencies": { 16 | "@typescript-eslint/eslint-plugin": "^6.11.0", 17 | "@typescript-eslint/parser": "^6.11.0", 18 | "eslint": "^8.54.0", 19 | "eslint-plugin-import": "^2.29.0", 20 | "prettier": "^3.1.0", 21 | "turbo": "^1.10.2", 22 | "typescript": "^5.8.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/avif/codec/enc/README.md: -------------------------------------------------------------------------------- 1 | # AVIF encoder 2 | 3 | - Source: 4 | - Version: v1.0.1 5 | 6 | ## Example 7 | 8 | Run example.js 9 | 10 | ## API 11 | 12 | ### `Uint8Array encode(std::string image_in, int image_width, int image_height, AvifOptions opts)` 13 | 14 | Encodes the given image with given dimension to AVIF. Options looks like this: 15 | 16 | ```c++ 17 | struct AvifOptions { 18 | // 0 = lossless 19 | // 63 = worst quality 20 | int minQuantizer; 21 | int maxQuantizer; 22 | 23 | // [0 - 6] 24 | // Creates 2^n tiles in that dimension 25 | int tileRowsLog2; 26 | int tileColsLog2; 27 | 28 | // 0 = slowest 29 | // 10 = fastest 30 | int speed; 31 | 32 | // 0 = 4:2:0 33 | // 1 = 4:2:2 34 | // 2 = 4:4:4 35 | int subsample; 36 | }; 37 | ``` 38 | -------------------------------------------------------------------------------- /packages/avif/codec/enc/avif_enc.d.ts: -------------------------------------------------------------------------------- 1 | export const enum AVIFTune { 2 | auto, 3 | psnr, 4 | ssim, 5 | } 6 | 7 | export interface EncodeOptions { 8 | quality: number; 9 | qualityAlpha: number; 10 | denoiseLevel: number; 11 | tileRowsLog2: number; 12 | tileColsLog2: number; 13 | speed: number; 14 | subsample: number; 15 | chromaDeltaQ: boolean; 16 | sharpness: number; 17 | enableSharpYUV: boolean; 18 | tune: AVIFTune; 19 | bitDepth: number; 20 | } 21 | 22 | export interface AVIFModule extends EmscriptenWasm.Module { 23 | encode( 24 | data: BufferSource, 25 | width: number, 26 | height: number, 27 | options: EncodeOptions, 28 | ): Uint8Array | null; 29 | } 30 | 31 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 32 | 33 | export default moduleFactory; 34 | -------------------------------------------------------------------------------- /packages/png/codec/pkg/squoosh_png_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export const memory: WebAssembly.Memory; 4 | export function __wbg_imagedatargba16_free(a: number): void; 5 | export function imagedatargba16_width(a: number): number; 6 | export function imagedatargba16_height(a: number): number; 7 | export function imagedatargba16_data(a: number): number; 8 | export function encode(a: number, b: number, c: number, d: number, e: number, f: number): void; 9 | export function decode(a: number, b: number): number; 10 | export function decode_rgba16(a: number, b: number): number; 11 | export function __wbindgen_free(a: number, b: number, c: number): void; 12 | export function __wbindgen_add_to_stack_pointer(a: number): number; 13 | export function __wbindgen_malloc(a: number, b: number): number; 14 | -------------------------------------------------------------------------------- /examples/with-webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | 5 | module.exports = { 6 | entry: './main.js', 7 | output: { 8 | path: path.resolve(__dirname, 'dist'), 9 | }, 10 | mode: 'development', 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.m?js/, 15 | resolve: { 16 | fullySpecified: false 17 | } 18 | } 19 | ] 20 | }, 21 | plugins: [ 22 | new webpack.IgnorePlugin({ 23 | resourceRegExp: /avif_enc_mt.worker/, 24 | }), 25 | new HtmlWebpackPlugin({ 26 | template: 'index.html' 27 | }) 28 | ], 29 | devServer: { 30 | static: path.resolve(__dirname, './'), 31 | port: 9000, 32 | open: true, 33 | }, 34 | }; 35 | -------------------------------------------------------------------------------- /tools/cpp.Dockerfile: -------------------------------------------------------------------------------- 1 | ARG EMSDK_VERSION=2.0.34 2 | 3 | FROM emscripten/emsdk:${EMSDK_VERSION} 4 | 5 | ARG DEFAULT_CFLAGS="-O3 -flto" 6 | ARG DEFAULT_CXX_FLAGS="-std=c++17" 7 | ARG DEFAULT_EMSCRIPTEN_SETTINGS="\ 8 | -s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \ 9 | -s FILESYSTEM=0 \ 10 | -s ALLOW_MEMORY_GROWTH=1 \ 11 | -s TEXTDECODER=0 \ 12 | " 13 | 14 | RUN apt-get update && apt-get install -qqy autoconf libtool pkg-config 15 | 16 | ENV CFLAGS="${DEFAULT_CFLAGS}" 17 | ENV CXXFLAGS="${CFLAGS} ${DEFAULT_CXX_FLAGS}" 18 | ENV LDFLAGS="${CFLAGS} ${DEFAULT_EMSCRIPTEN_SETTINGS}" 19 | 20 | # Build and cache standard libraries with these flags + Embind. 21 | RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -xc++ /dev/null -o /dev/null 22 | # And another set for the pthread variant. 23 | RUN emcc ${CXXFLAGS} ${LDFLAGS} --bind -pthread -xc++ /dev/null -o /dev/null 24 | 25 | WORKDIR /src 26 | CMD ["sh", "-c", "emmake make -j`nproc`"] 27 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squoosh-resize" 3 | version = "0.1.0" 4 | authors = ["Surma "] 5 | publish = false 6 | 7 | [lib] 8 | #crate-type = ["cdylib", "rlib"] 9 | crate-type = ["cdylib"] 10 | 11 | [features] 12 | default = ["console_error_panic_hook"] 13 | 14 | [dependencies] 15 | cfg-if = "0.1.2" 16 | wasm-bindgen = "0.2.38" 17 | resize = "0.5.5" 18 | 19 | # The `console_error_panic_hook` crate provides better debugging of panics by 20 | # logging them with `console.error`. This is great for development, but requires 21 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 22 | # code size when deploying. 23 | console_error_panic_hook = { version = "0.1.1", optional = true } 24 | 25 | [dev-dependencies] 26 | wasm-bindgen-test = "0.2" 27 | 28 | [profile.release] 29 | # Tell `rustc` to optimize for small code size. 30 | opt-level = "s" 31 | lto = true -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: jamsinclair 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Reproduction URL** 21 | Providing a minimal reproduction in a code playground, like [CodeSandbox](https://codesandbox.io/), is incredibly helpful and speeds up the progress of a solution being found. 22 | 23 | **Expected behavior** 24 | A clear and concise description of what you expected to happen. 25 | 26 | **Module Versions** 27 | Which versions of the jSquash packages are you using? Have you tried the latest version? 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /packages/qoi/codec/enc/qoi_enc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define QOI_IMPLEMENTATION 5 | #include "qoi.h" 6 | 7 | using namespace emscripten; 8 | 9 | thread_local const val Uint8Array = val::global("Uint8Array"); 10 | 11 | val encode(std::string buffer, int width, int height) { 12 | int compressedSizeInBytes; 13 | qoi_desc desc; 14 | desc.width = width; 15 | desc.height = height; 16 | desc.channels = 4; 17 | desc.colorspace = QOI_SRGB; 18 | 19 | uint8_t* encodedData = (uint8_t*)qoi_encode(buffer.c_str(), &desc, &compressedSizeInBytes); 20 | if (encodedData == NULL) 21 | return val::null(); 22 | 23 | auto js_result = 24 | Uint8Array.new_(typed_memory_view(compressedSizeInBytes, (const uint8_t*)encodedData)); 25 | free(encodedData); 26 | 27 | return js_result; 28 | } 29 | 30 | EMSCRIPTEN_BINDINGS(my_module) { 31 | function("encode", &encode); 32 | } 33 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "squooshhqx" 3 | version = "0.1.0" 4 | authors = ["Surma "] 5 | 6 | [lib] 7 | crate-type = ["cdylib"] 8 | 9 | [features] 10 | default = ["console_error_panic_hook"] 11 | 12 | [dependencies] 13 | cfg-if = "0.1.2" 14 | wasm-bindgen = "0.2.38" 15 | # lazy_static = "1.0.0" 16 | hqx = {git = "https://github.com/CryZe/wasmboy-rs", tag="v0.1.3"} 17 | 18 | # The `console_error_panic_hook` crate provides better debugging of panics by 19 | # logging them with `console.error`. This is great for development, but requires 20 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 21 | # code size when deploying. 22 | console_error_panic_hook = { version = "0.1.1", optional = true } 23 | 24 | [dev-dependencies] 25 | wasm-bindgen-test = "0.2" 26 | 27 | [profile.release] 28 | # Tell `rustc` to optimize for small code size. 29 | opt-level = "s" 30 | lto = true 31 | -------------------------------------------------------------------------------- /packages/qoi/codec/dec/qoi_dec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define QOI_IMPLEMENTATION 5 | #include "qoi.h" 6 | 7 | using namespace emscripten; 8 | 9 | thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); 10 | thread_local const val ImageData = val::global("ImageData"); 11 | 12 | val decode(std::string qoiimage) { 13 | qoi_desc desc; 14 | uint8_t* rgba = (uint8_t*)qoi_decode(qoiimage.c_str(), qoiimage.length(), &desc, 4); 15 | 16 | // Resultant width and height stored in descriptor 17 | int decodedWidth = desc.width; 18 | int decodedHeight = desc.height; 19 | 20 | val result = ImageData.new_( 21 | Uint8ClampedArray.new_(typed_memory_view(4 * decodedWidth * decodedHeight, rgba)), 22 | decodedWidth, decodedHeight); 23 | free(rgba); 24 | 25 | return result; 26 | } 27 | 28 | EMSCRIPTEN_BINDINGS(my_module) { 29 | function("decode", &decode); 30 | } 31 | -------------------------------------------------------------------------------- /packages/jxl/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/png/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/qoi/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/avif/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/jpeg/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/webp/codec/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/pre.js: -------------------------------------------------------------------------------- 1 | const isServiceWorker = globalThis.ServiceWorkerGlobalScope !== undefined; 2 | const isRunningInCloudFlareWorkers = isServiceWorker && typeof self !== 'undefined' && globalThis.caches && globalThis.caches.default !== undefined; 3 | const isRunningInNode = typeof process === 'object' && process.release && process.release.name === 'node'; 4 | 5 | if (isRunningInCloudFlareWorkers || isRunningInNode) { 6 | if (!globalThis.ImageData) { 7 | // Simple Polyfill for ImageData Object 8 | globalThis.ImageData = class ImageData { 9 | constructor(data, width, height) { 10 | this.data = data; 11 | this.width = width; 12 | this.height = height; 13 | } 14 | }; 15 | } 16 | 17 | if (import.meta.url === undefined) { 18 | import.meta.url = 'https://localhost'; 19 | } 20 | 21 | if (typeof self !== 'undefined' && self.location === undefined) { 22 | self.location = { href: '' }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/webp/codec/dec/webp_dec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "emscripten/bind.h" 3 | #include "emscripten/val.h" 4 | #include "src/webp/decode.h" 5 | #include "src/webp/demux.h" 6 | 7 | using namespace emscripten; 8 | 9 | int version() { 10 | return WebPGetDecoderVersion(); 11 | } 12 | 13 | thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); 14 | thread_local const val ImageData = val::global("ImageData"); 15 | 16 | val decode(std::string buffer) { 17 | int width, height; 18 | std::unique_ptr rgba( 19 | WebPDecodeRGBA((const uint8_t*)buffer.c_str(), buffer.size(), &width, &height)); 20 | return rgba ? ImageData.new_( 21 | Uint8ClampedArray.new_(typed_memory_view(width * height * 4, rgba.get())), 22 | width, height) 23 | : val::null(); 24 | } 25 | 26 | EMSCRIPTEN_BINDINGS(my_module) { 27 | function("decode", &decode); 28 | function("version", &version); 29 | } 30 | -------------------------------------------------------------------------------- /packages/jpeg/codec/enc/mozjpeg_enc.d.ts: -------------------------------------------------------------------------------- 1 | export const enum MozJpegColorSpace { 2 | GRAYSCALE = 1, 3 | RGB, 4 | YCbCr, 5 | } 6 | 7 | export interface EncodeOptions { 8 | quality: number; 9 | baseline: boolean; 10 | arithmetic: boolean; 11 | progressive: boolean; 12 | optimize_coding: boolean; 13 | smoothing: number; 14 | color_space: MozJpegColorSpace; 15 | quant_table: number; 16 | trellis_multipass: boolean; 17 | trellis_opt_zero: boolean; 18 | trellis_opt_table: boolean; 19 | trellis_loops: number; 20 | auto_subsample: boolean; 21 | chroma_subsample: number; 22 | separate_chroma_quality: boolean; 23 | chroma_quality: number; 24 | } 25 | 26 | export interface MozJPEGModule extends EmscriptenWasm.Module { 27 | encode( 28 | data: BufferSource, 29 | width: number, 30 | height: number, 31 | options: EncodeOptions, 32 | ): Uint8Array; 33 | } 34 | 35 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 36 | 37 | export default moduleFactory; 38 | -------------------------------------------------------------------------------- /examples/with-node/index.js: -------------------------------------------------------------------------------- 1 | import decodeJpeg, { init as initJpegDecode } from '@jsquash/jpeg/decode.js'; 2 | import encodePng, { init as initPngEncode } from '@jsquash/png/encode.js'; 3 | import fs from 'fs'; 4 | 5 | // Load the Jpeg Decode WebAssembly Module and initialize the decoder 6 | const jpegWasmBuffer = fs.readFileSync('node_modules/@jsquash/jpeg/codec/dec/mozjpeg_dec.wasm'); 7 | const jpegWasmModule = await WebAssembly.compile(jpegWasmBuffer); 8 | await initJpegDecode(jpegWasmModule); 9 | 10 | // Load the Png Encode WebAssembly Module and initialize the encoder 11 | const pngWasmBuffer = fs.readFileSync('node_modules/@jsquash/png/codec/pkg/squoosh_png_bg.wasm'); 12 | const pngWasmModule = await WebAssembly.compile(pngWasmBuffer); 13 | await initPngEncode(pngWasmModule); 14 | 15 | // Decode the Jpeg image to ImageData format 16 | const jpegBuffer = fs.readFileSync('example.jpg'); 17 | const imageData = await decodeJpeg(jpegBuffer); 18 | 19 | // Encode the ImageData to Png file 20 | fs.writeFileSync('example.png', await encodePng(imageData)); 21 | -------------------------------------------------------------------------------- /packages/jpeg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/jpeg", 3 | "version": "1.6.0", 4 | "main": "index.js", 5 | "description": "Wasm jpeg encoder and decoder supporting the browser. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "optimisation", 14 | "optimization", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "jpeg" 19 | ], 20 | "license": "Apache-2.0", 21 | "scripts": { 22 | "clean": "rm -rf dist", 23 | "build:codec": "cd codec && npm run build", 24 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md *.d.ts .npmignore ../../LICENSE dist", 25 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 26 | }, 27 | "devDependencies": { 28 | "typescript": "^4.4.4" 29 | }, 30 | "type": "module", 31 | "sideEffects": false 32 | } 33 | -------------------------------------------------------------------------------- /packages/qoi/codec/Makefile: -------------------------------------------------------------------------------- 1 | CODEC_URL = https://github.com/phoboslab/qoi/archive/8d35d93cdca85d2868246c2a8a80a1e2c16ba2a8.tar.gz 2 | 3 | CODEC_DIR = node_modules/qoi 4 | CODEC_BUILD_DIR:= $(CODEC_DIR)/build 5 | ENVIRONMENT = web,worker 6 | 7 | PRE_JS = pre.js 8 | OUT_JS = enc/qoi_enc.js dec/qoi_dec.js 9 | OUT_WASM := $(OUT_JS:.js=.wasm) 10 | 11 | .PHONY: all clean 12 | 13 | all: $(OUT_JS) 14 | 15 | $(filter enc/%,$(OUT_JS)): enc/qoi_enc.o 16 | $(filter dec/%,$(OUT_JS)): dec/qoi_dec.o 17 | 18 | # ALL .js FILES 19 | $(OUT_JS): 20 | $(LD) \ 21 | $(LDFLAGS) \ 22 | --pre-js $(PRE_JS) \ 23 | --bind \ 24 | -s ENVIRONMENT=$(ENVIRONMENT) \ 25 | -s EXPORT_ES6=1 \ 26 | -s DYNAMIC_EXECUTION=0 \ 27 | -s MODULARIZE=1 \ 28 | -o $@ \ 29 | $+ 30 | 31 | # ALL .o FILES 32 | %.o: %.cpp $(CODEC_DIR) 33 | $(CXX) -c \ 34 | $(CXXFLAGS) \ 35 | -I $(CODEC_DIR) \ 36 | -o $@ \ 37 | $< 38 | 39 | # CREATE DIRECTORY 40 | $(CODEC_DIR): 41 | mkdir -p $(CODEC_DIR) 42 | curl -sL $(CODEC_URL) | tar xz --strip 1 -C $(CODEC_DIR) 43 | 44 | clean: 45 | $(RM) $(OUT_JS) $(OUT_WASM) 46 | $(MAKE) -C $(CODEC_DIR) clean 47 | -------------------------------------------------------------------------------- /packages/qoi/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/qoi", 3 | "version": "1.1.0", 4 | "main": "index.js", 5 | "description": "Wasm Quite Ok Image Format (qoi) encoder and decoder supporting the browser. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "encoder", 14 | "decoder", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "qoi", 19 | "quite-ok-image-format" 20 | ], 21 | "license": "Apache-2.0", 22 | "scripts": { 23 | "clean": "rm -rf dist", 24 | "build:codec": "cd codec && npm run build", 25 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md *.d.ts .npmignore ../../LICENSE dist", 26 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 27 | }, 28 | "devDependencies": { 29 | "typescript": "^4.4.4" 30 | }, 31 | "type": "module", 32 | "sideEffects": false 33 | } 34 | -------------------------------------------------------------------------------- /packages/png/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/png", 3 | "version": "3.1.1", 4 | "main": "index.js", 5 | "description": "Wasm png encoder and decoder supporting the browser. Repackaged from Squoosh App.", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/jamsinclair/jSquash.git" 9 | }, 10 | "author": { 11 | "name": "Jamie Sinclair", 12 | "email": "jamsinclairnz+npm@gmail.com" 13 | }, 14 | "keywords": [ 15 | "image", 16 | "optimisation", 17 | "optimization", 18 | "squoosh", 19 | "wasm", 20 | "webassembly", 21 | "png" 22 | ], 23 | "license": "Apache-2.0", 24 | "scripts": { 25 | "clean": "rm -rf dist", 26 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md .npmignore ../../LICENSE dist && (rm dist/codec/pkg/.gitignore || true)", 27 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 28 | }, 29 | "devDependencies": { 30 | "typescript": "^4.4.4" 31 | }, 32 | "type": "module", 33 | "sideEffects": false 34 | } 35 | -------------------------------------------------------------------------------- /packages/oxipng/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/oxipng", 3 | "version": "2.3.0", 4 | "main": "index.js", 5 | "description": "Wasm png optimiser supporting the browser. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash/packages/oxipng", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "optimisation", 14 | "optimization", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "png", 19 | "oxipng" 20 | ], 21 | "license": "Apache-2.0", 22 | "scripts": { 23 | "clean": "rm -rf dist", 24 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md .npmignore ../../LICENSE dist && rm -rf dist/codec/target", 25 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 26 | }, 27 | "dependencies": { 28 | "wasm-feature-detect": "^1.2.11" 29 | }, 30 | "devDependencies": { 31 | "typescript": "^4.4.4" 32 | }, 33 | "type": "module", 34 | "sideEffects": false 35 | } 36 | -------------------------------------------------------------------------------- /packages/webp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/webp", 3 | "version": "1.5.0", 4 | "main": "index.js", 5 | "description": "Wasm webp encoder and decoder supporting the browser. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "optimisation", 14 | "optimization", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "webp" 19 | ], 20 | "license": "Apache-2.0", 21 | "scripts": { 22 | "clean": "rm -rf dist", 23 | "build:codec": "cd codec && npm run build", 24 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md *.d.ts .npmignore ../../LICENSE dist", 25 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 26 | }, 27 | "dependencies": { 28 | "wasm-feature-detect": "^1.2.11" 29 | }, 30 | "devDependencies": { 31 | "typescript": "^4.4.4" 32 | }, 33 | "type": "module", 34 | "sideEffects": false 35 | } 36 | -------------------------------------------------------------------------------- /packages/resize/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/resize", 3 | "version": "2.1.0", 4 | "main": "index.js", 5 | "description": "Wasm image resize methods supporting the browser and V8 environments. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash/packages/resize", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "resize", 14 | "hqx", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "lanczos3", 19 | "crop", 20 | "magic-kernel", 21 | "magic kernel" 22 | ], 23 | "license": "Apache-2.0", 24 | "scripts": { 25 | "clean": "rm -rf dist", 26 | "build": "npm run clean && tsc && cp -r lib package.json README.md .npmignore ../../LICENSE dist && (rm dist/lib/*/pkg/package.json dist/lib/*/pkg/.gitignore || true)", 27 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 28 | }, 29 | "devDependencies": { 30 | "typescript": "^4.4.4" 31 | }, 32 | "type": "module", 33 | "sideEffects": false 34 | } 35 | -------------------------------------------------------------------------------- /test/node/qoi.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { importWasmModule, getFixturesImage } from './utils.js'; 3 | 4 | import decode, { init as initDecode } from '@jsquash/qoi/decode.js'; 5 | import encode, { init as initEncode } from '@jsquash/qoi/encode.js'; 6 | 7 | test('can successfully decode image', async (t) => { 8 | const [testImage, decodeWasmModule] = await Promise.all([ 9 | getFixturesImage('test.qoi'), 10 | importWasmModule('node_modules/@jsquash/qoi/codec/dec/qoi_dec.wasm'), 11 | ]); 12 | initDecode(decodeWasmModule); 13 | const data = await decode(testImage); 14 | t.is(data.width, 50); 15 | t.is(data.height, 50); 16 | t.is(data.data.length, 4 * 50 * 50); 17 | }); 18 | 19 | test('can successfully encode image', async (t) => { 20 | const encodeWasmModule = await importWasmModule( 21 | 'node_modules/@jsquash/qoi/codec/enc/qoi_enc.wasm', 22 | ); 23 | await initEncode(encodeWasmModule); 24 | const data = await encode({ 25 | data: new Uint8ClampedArray(4 * 50 * 50), 26 | height: 50, 27 | width: 50, 28 | colorSpace: 'srgb' as const, 29 | }); 30 | t.assert(data instanceof ArrayBuffer); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/jxl/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import type { EncodeOptions } from './codec/enc/jxl_enc.js'; 14 | 15 | export { EncodeOptions }; 16 | 17 | export const label = 'JPEG XL (beta)'; 18 | export const mimeType = 'image/jxl'; 19 | export const extension = 'jxl'; 20 | export const defaultOptions: EncodeOptions = { 21 | effort: 7, 22 | quality: 75, 23 | progressive: false, 24 | epf: -1, 25 | lossyPalette: false, 26 | decodingSpeedTier: 0, 27 | photonNoiseIso: 0, 28 | lossyModular: false, 29 | lossless: false, 30 | }; 31 | -------------------------------------------------------------------------------- /packages/oxipng/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | /** 14 | * Changes from source code: 15 | * - Added defaultOptions 16 | * - Added `optimiseAlpha` option 17 | */ 18 | export interface OptimiseOptions { 19 | level: number; 20 | interlace: boolean; 21 | optimiseAlpha: boolean; 22 | } 23 | 24 | export const label = 'OXIPNG'; 25 | export const mimeType = 'image/png'; 26 | export const extension = 'png'; 27 | export const defaultOptions: OptimiseOptions = { 28 | level: 2, 29 | interlace: false, 30 | optimiseAlpha: false, 31 | }; 32 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg-parallel/squoosh_oxipng_bg.wasm.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | export function optimise(a: number, b: number, c: number, d: number, e: number, f: number): void; 4 | export function optimise_raw(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number): void; 5 | export function __wbg_wbg_rayon_poolbuilder_free(a: number): void; 6 | export function wbg_rayon_poolbuilder_numThreads(a: number): number; 7 | export function wbg_rayon_poolbuilder_receiver(a: number): number; 8 | export function wbg_rayon_poolbuilder_build(a: number): void; 9 | export function initThreadPool(a: number): number; 10 | export function wbg_rayon_start_worker(a: number): void; 11 | export const memory: WebAssembly.Memory; 12 | export function __wbindgen_add_to_stack_pointer(a: number): number; 13 | export function __wbindgen_malloc(a: number, b: number): number; 14 | export function __wbindgen_free(a: number, b: number, c: number): void; 15 | export function __wbindgen_exn_store(a: number): void; 16 | export function __wbindgen_thread_destroy(a: number, b: number): void; 17 | export function __wbindgen_start(): void; 18 | -------------------------------------------------------------------------------- /test/node/webp.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { importWasmModule, getFixturesImage } from './utils.js'; 3 | 4 | import decode, { init as initDecode } from '@jsquash/webp/decode.js'; 5 | import encode, { init as initEncode } from '@jsquash/webp/encode.js'; 6 | 7 | test('can successfully decode image', async (t) => { 8 | const [testImage, decodeWasmModule] = await Promise.all([ 9 | getFixturesImage('test.webp'), 10 | importWasmModule('node_modules/@jsquash/webp/codec/dec/webp_dec.wasm'), 11 | ]); 12 | initDecode(decodeWasmModule); 13 | const data = await decode(testImage); 14 | t.is(data.width, 50); 15 | t.is(data.height, 50); 16 | t.is(data.data.length, 4 * 50 * 50); 17 | }); 18 | 19 | test('can successfully encode image', async (t) => { 20 | const encodeWasmModule = await importWasmModule( 21 | 'node_modules/@jsquash/webp/codec/enc/webp_enc.wasm', 22 | ); 23 | await initEncode(encodeWasmModule); 24 | const data = await encode({ 25 | data: new Uint8ClampedArray(4 * 50 * 50), 26 | height: 50, 27 | width: 50, 28 | colorSpace: 'srgb' as const, 29 | }); 30 | t.assert(data instanceof ArrayBuffer); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/oxipng/codec/LICENSE.codec.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Joshua Holmer 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 | of the Software, and to permit persons to whom the Software is furnished to do 9 | so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. -------------------------------------------------------------------------------- /packages/webp/codec/enc/webp_enc.d.ts: -------------------------------------------------------------------------------- 1 | export interface EncodeOptions { 2 | quality: number; 3 | target_size: number; 4 | target_PSNR: number; 5 | method: number; 6 | sns_strength: number; 7 | filter_strength: number; 8 | filter_sharpness: number; 9 | filter_type: number; 10 | partitions: number; 11 | segments: number; 12 | pass: number; 13 | show_compressed: number; 14 | preprocessing: number; 15 | autofilter: number; 16 | partition_limit: number; 17 | alpha_compression: number; 18 | alpha_filtering: number; 19 | alpha_quality: number; 20 | lossless: number; 21 | exact: number; 22 | image_hint: number; 23 | emulate_jpeg_size: number; 24 | thread_level: number; 25 | low_memory: number; 26 | near_lossless: number; 27 | use_delta_palette: number; 28 | use_sharp_yuv: number; 29 | } 30 | 31 | export interface WebPModule extends EmscriptenWasm.Module { 32 | encode( 33 | data: BufferSource, 34 | width: number, 35 | height: number, 36 | options: EncodeOptions, 37 | ): Uint8Array | null; 38 | } 39 | 40 | declare var moduleFactory: EmscriptenWasm.ModuleFactory; 41 | 42 | export default moduleFactory; 43 | -------------------------------------------------------------------------------- /packages/qoi/codec/LICENSE.codec.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Dominic Szablewski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/resize/util.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | export function getContainOffsets( 15 | sw: number, 16 | sh: number, 17 | dw: number, 18 | dh: number, 19 | ) { 20 | const currentAspect = sw / sh; 21 | const endAspect = dw / dh; 22 | 23 | if (endAspect > currentAspect) { 24 | const newSh = sw / endAspect; 25 | const newSy = (sh - newSh) / 2; 26 | return { sw, sh: newSh, sx: 0, sy: newSy }; 27 | } 28 | 29 | const newSw = sh * endAspect; 30 | const newSx = (sw - newSw) / 2; 31 | return { sh, sw: newSw, sx: newSx, sy: 0 }; 32 | } 33 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/LICENSE.codec.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 PistonDevelopers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/avif/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/avif", 3 | "version": "2.1.1", 4 | "main": "index.js", 5 | "description": "Wasm AVIF encoder and decoder supporting the browser. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "optimisation", 14 | "optimization", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "avif" 19 | ], 20 | "license": "Apache-2.0", 21 | "scripts": { 22 | "clean": "rm -rf dist", 23 | "build:codec": "cd codec && npm run build", 24 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md *.d.ts .npmignore ../../LICENSE dist && cd dist/codec", 25 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 26 | }, 27 | "devDependencies": { 28 | "@types/node": "^20.9.2", 29 | "typescript": "^4.4.4" 30 | }, 31 | "type": "module", 32 | "sideEffects": false, 33 | "dependencies": { 34 | "wasm-feature-detect": "^1.2.11" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/LICENSE.codec.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Serhii Tatarintsev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/jxl/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jsquash/jxl", 3 | "version": "1.3.0", 4 | "main": "index.js", 5 | "description": "Wasm JPEG XL encoder and decoder supporting the browser. Repackaged from Squoosh App.", 6 | "repository": "jamsinclair/jSquash", 7 | "author": { 8 | "name": "Jamie Sinclair", 9 | "email": "jamsinclairnz+npm@gmail.com" 10 | }, 11 | "keywords": [ 12 | "image", 13 | "optimisation", 14 | "optimization", 15 | "squoosh", 16 | "wasm", 17 | "webassembly", 18 | "jpegxl", 19 | "jpeg xl", 20 | "jxl" 21 | ], 22 | "license": "Apache-2.0", 23 | "scripts": { 24 | "clean": "rm -rf dist", 25 | "build:codec": "cd codec && npm run build", 26 | "build": "npm run clean && tsc && cp -r codec package.json README.md CHANGELOG.md *.d.ts .npmignore ../../LICENSE dist", 27 | "prepublishOnly": "[[ \"$PWD\" == *'/dist' ]] && exit 0 || (echo 'Please run npm publish from the dist directory' && exit 1)" 28 | }, 29 | "dependencies": { 30 | "wasm-feature-detect": "^1.5.1" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "^20.9.2", 34 | "typescript": "^4.4.4" 35 | }, 36 | "type": "module", 37 | "sideEffects": false 38 | } 39 | -------------------------------------------------------------------------------- /test/node/oxipng.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import { importWasmModule, getFixturesImage } from './utils.js'; 3 | 4 | import optimise, { init } from '@jsquash/oxipng/optimise.js'; 5 | 6 | test('can successfully optimise png image', async (t) => { 7 | const [testImage, optimiseWasmModule] = await Promise.all([ 8 | getFixturesImage('test.png'), 9 | importWasmModule( 10 | 'node_modules/@jsquash/oxipng/codec/pkg/squoosh_oxipng_bg.wasm', 11 | ), 12 | ]); 13 | await init(optimiseWasmModule); 14 | const optimisedImage = await optimise(testImage); 15 | t.assert(optimisedImage instanceof ArrayBuffer); 16 | t.assert(optimisedImage.byteLength < testImage.byteLength); 17 | }); 18 | 19 | test('can successfully optimise from raw image data and output png image', async (t) => { 20 | const optimiseWasmModule = await importWasmModule( 21 | 'node_modules/@jsquash/oxipng/codec/pkg/squoosh_oxipng_bg.wasm', 22 | ); 23 | await init(optimiseWasmModule); 24 | 25 | const testRawImageData = new ImageData( 26 | new Uint8ClampedArray(4 * 50 * 50), 27 | 50, 28 | 50, 29 | ); 30 | const optimisedImage = await optimise(testRawImageData); 31 | t.assert(optimisedImage instanceof ArrayBuffer); 32 | }); 33 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/squooshhqx.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint32Array} input_image 5 | * @param {number} input_width 6 | * @param {number} input_height 7 | * @param {number} factor 8 | * @returns {Uint32Array} 9 | */ 10 | export function resize(input_image: Uint32Array, input_width: number, input_height: number, factor: number): Uint32Array; 11 | 12 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 13 | 14 | export interface InitOutput { 15 | readonly memory: WebAssembly.Memory; 16 | readonly resize: (a: number, b: number, c: number, d: number, e: number, f: number) => void; 17 | readonly __wbindgen_add_to_stack_pointer: (a: number) => number; 18 | readonly __wbindgen_malloc: (a: number) => number; 19 | readonly __wbindgen_free: (a: number, b: number) => void; 20 | } 21 | 22 | /** 23 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 24 | * for everything else, calls `WebAssembly.instantiate` directly. 25 | * 26 | * @param {InitInput | Promise} module_or_path 27 | * 28 | * @returns {Promise} 29 | */ 30 | export default function init (module_or_path?: InitInput | Promise): Promise; 31 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate cfg_if; 2 | extern crate hqx; 3 | extern crate wasm_bindgen; 4 | 5 | mod utils; 6 | 7 | use wasm_bindgen::prelude::*; 8 | 9 | #[wasm_bindgen] 10 | #[no_mangle] 11 | pub fn resize( 12 | input_image: Vec, 13 | input_width: usize, 14 | input_height: usize, 15 | factor: usize, 16 | ) -> Vec { 17 | let num_output_pixels = input_width * input_height * factor * factor; 18 | let mut output_image = Vec::::with_capacity(num_output_pixels * 4); 19 | output_image.resize(num_output_pixels, 0); 20 | 21 | match factor { 22 | 2 => hqx::hq2x( 23 | input_image.as_slice(), 24 | output_image.as_mut_slice(), 25 | input_width, 26 | input_height, 27 | ), 28 | 3 => hqx::hq3x( 29 | input_image.as_slice(), 30 | output_image.as_mut_slice(), 31 | input_width, 32 | input_height, 33 | ), 34 | 4 => hqx::hq4x( 35 | input_image.as_slice(), 36 | output_image.as_mut_slice(), 37 | input_width, 38 | input_height, 39 | ), 40 | _ => unreachable!(), 41 | }; 42 | 43 | return output_image; 44 | } 45 | -------------------------------------------------------------------------------- /packages/webp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/webp@1.5.0 4 | 5 | ### Adds 6 | 7 | - Adds support for only providing a module option override to the `init` function directly 8 | 9 | **Example:** 10 | ```ts 11 | import encode, { init } from '@jsquash/webp/encode'; 12 | await init({ 13 | locateFile: (path) => { 14 | const remoteLocation = 'https://cdn.mydomain.com/wasm'; 15 | return remoteLocation + path; 16 | } 17 | }); 18 | const buffer = await encode(/* image data */); 19 | ``` 20 | 21 | ### Fixes 22 | 23 | - Updates `locateFile` emscripten module option type to support prefix parameter. 24 | 25 | ## @jsquash/webp@1.4.0 26 | 27 | ### Adds 28 | 29 | - Adds ability to customise Emscripten module options, e.g. define your own `locateFile` method. 30 | 31 | ## @jsquash/webp@1.3.0 32 | 33 | ### Adds 34 | 35 | - Adds Node.js ESM support 36 | - Updates relative imports to use file extensions 37 | - Adds `module` field to relevant `package.json` 38 | - Updates pre.js to polyfill ImageData for Node.js 39 | 40 | ### Misc. 41 | 42 | - Removes *.d.ts.map files from the package 43 | 44 | ## @jsquash/webp@1.2.0 45 | 46 | ### Added 47 | 48 | - Include polyfills for Cloudflare Worker environment for easier compatibility 49 | -------------------------------------------------------------------------------- /packages/resize/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/resize@2.1.0 4 | 5 | ### Adds 6 | 7 | - Adds initial Magic Kernel resizing method support ([Using the Rust library](https://github.com/SevInf/magic-kernel-rust)) 8 | - `magicKernel` - The original Magic Kernel algorithm 9 | - `magicKernelSharp2013` - A sharpened version of the Magic Kernel algorithm 10 | - `magicKernelSharp2021` - A further sharpened version of the Magic Kernel algorithm 11 | 12 | ## @jsquash/resize@2.0.0 13 | 14 | ### Breaking Changes 15 | 16 | - Moves compiled wasm and js files to the 'lib/*/pkg' directory. If you were using the wasm file directly you will need to update your paths to reference the following 17 | - `node_modules/@jsquash/resize/lib/hqx/pkg/squooshhqx_bg.wasm` 18 | - `node_modules/@jsquash/resize/lib/resize/pkg/squoosh_resize_bg.wasm` 19 | 20 | ### Fixes 21 | 22 | - Fixes memory leak caused by a bug with wee_alloc 23 | 24 | ## @jsquash/resize@1.1.1 25 | 26 | ### Fixes 27 | 28 | - Add same ImageData polyfill and tweaks to better support Cloudflare Workers and Node.js 29 | 30 | ### Misc 31 | 32 | - Ensures license is properly included in the package 33 | 34 | ## @jsquash/resize@1.1.0 35 | 36 | ### Adds 37 | 38 | - Adds Node.js ESM support 39 | 40 | ### Misc. 41 | 42 | - Removes *.d.ts.map files from the package 43 | -------------------------------------------------------------------------------- /examples/with-cdn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | jSquash with Rollup example 8 | 9 | 10 |

Image Converter

11 |
12 | 16 |

Choose output image type:

17 |
18 | 21 | 24 | 27 | 30 | 33 |
34 | 35 |
36 |

Output Image (Right click to save)

37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /examples/with-vite/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | jSquash with Vite example 8 | 9 | 10 |

Image Converter

11 |
12 | 16 |

Choose output image type:

17 |
18 | 21 | 24 | 27 | 30 | 33 |
34 | 35 |
36 |

Output Image (Right click to save)

37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /examples/with-rollup/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | jSquash with Rollup example 8 | 9 | 10 |

Image Converter

11 |
12 | 16 |

Choose output image type:

17 |
18 | 21 | 24 | 27 | 30 | 33 |
34 | 35 |
36 |

Output Image (Right click to save)

37 |
38 | 39 | 40 | -------------------------------------------------------------------------------- /packages/oxipng/codec/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "parallel")] 2 | pub use wasm_bindgen_rayon::init_thread_pool; 3 | 4 | use oxipng::{BitDepth, ColorType, Interlacing}; 5 | use wasm_bindgen::prelude::*; 6 | use wasm_bindgen::Clamped; 7 | 8 | #[wasm_bindgen] 9 | pub fn optimise(data: &[u8], level: u8, interlace: bool, optimize_alpha: bool) -> Vec { 10 | let mut options = oxipng::Options::from_preset(level); 11 | options.interlace = Some(if interlace { 12 | Interlacing::Adam7 13 | } else { 14 | Interlacing::None 15 | }); 16 | options.optimize_alpha = optimize_alpha; 17 | 18 | oxipng::optimize_from_memory(data, &options).unwrap_throw() 19 | } 20 | 21 | #[wasm_bindgen] 22 | pub fn optimise_raw( 23 | data: Clamped>, 24 | width: u32, 25 | height: u32, 26 | level: u8, 27 | interlace: bool, 28 | optimize_alpha: bool, 29 | ) -> Vec { 30 | let mut options = oxipng::Options::from_preset(level); 31 | options.interlace = Some(if interlace { 32 | Interlacing::Adam7 33 | } else { 34 | Interlacing::None 35 | }); 36 | options.optimize_alpha = optimize_alpha; 37 | 38 | let raw = oxipng::RawImage::new(width, height, ColorType::RGBA, BitDepth::Eight, data.0) 39 | .unwrap_throw(); 40 | raw.create_optimized_png(&options).unwrap_throw() 41 | } 42 | -------------------------------------------------------------------------------- /examples/with-webpack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | jSquash with Webpack example 8 | <%= htmlWebpackPlugin.tags.headTags %> 9 | 10 | 11 |

Image Converter

12 |
13 | 17 |

Choose output image type:

18 |
19 | 22 | 25 | 28 | 31 | 34 |
35 | 36 |
37 |

Output Image (Right click to save)

38 |
39 | <%= htmlWebpackPlugin.tags.bodyTags %> 40 | 41 | -------------------------------------------------------------------------------- /packages/oxipng/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/oxipng@2.3.0 4 | 5 | ### Adds 6 | 7 | - Better compilation with Vite Bundler. Solves issues with circular dependencies for Vite v5.1.6+. 8 | 9 | ## @jsquash/oxipng@2.2.0 10 | 11 | ### Adds 12 | 13 | - Updates oxipng to v9.0 14 | - Adds support to optimise raw image data directly and output as an optimised PNG. This is useful for when you have raw image data and want to optimise it without having to encode to a PNG first. 15 | 16 | ## @jsquash/oxipng@2.1.0 17 | 18 | ### Adds 19 | 20 | - Adds Node.js ESM support 21 | - Updates relative imports to use file extensions 22 | - Adds `module` field to relevant `package.json` 23 | - Updates pre.js to polyfill ImageData for Node.js 24 | 25 | ## @jsquash/oxipng@2.0.0 26 | 27 | ### Breaking Changes 28 | 29 | - Upgrades several major versions to oxipng 8.0.0 30 | 31 | ### Adds 32 | 33 | - Adds support for `optimiseAlpha` option to control whether alpha channels are optimised or not 34 | 35 | ## @jsquash/oxipng@1.0.2 36 | 37 | ### Fixes 38 | 39 | - Only allow multithreading when running in a WebWorker, otherwise it will throw an error 40 | 41 | ### Misc. 42 | 43 | - Removes *.d.ts.map files from the package 44 | 45 | ## @jsquash/oxipng@1.0.1 46 | 47 | ### Fixes 48 | 49 | - Update the rayon dynamic import path so it can be handled better by bundlers. Particularly Vite. 50 | -------------------------------------------------------------------------------- /examples/cloudflare-worker-esm-format/README.md: -------------------------------------------------------------------------------- 1 | # Cloudflare Worker Example (ES Module Format) 2 | 3 | For this example, we will be using the [Cloudflare Worker](https://workers.cloudflare.com/) platform to upgrade images to WebP. 4 | 5 | The example also uses the ES Module Format which is now the preferred way to use Cloudflare Workers. 6 | 7 | We can use the latest Wrangler CLI to run the example locally and deploy it to Cloudflare Workers. 8 | 9 | ## Running the example locally 10 | 11 | 1. Run `npm install` 12 | 2. Run `npm run start` to start the development server 13 | 14 | ## Usage of jSquash packages in Cloudflare Worker 15 | 16 | One caveat is wrangler won't dynamically bundle the WASM modules with the worker. 17 | 18 | You will need to "import" the correct WASM module manually. Behind the scenes, on deployment, the WASM modules are set as global variables. 19 | 20 | The `encode` and `decode` modules both export an `init` function that can be used to manually load the wasm module. 21 | 22 | ```js 23 | import decode, { init as initJpegDecode } from '@jsquash/jpeg/decode'; 24 | 25 | // Import the correct WASM module from the node_modules folder 26 | import JPEG_DEC_WASM from '../node_modules/@jsquash/jpeg/decode/dist/decode.wasm'; 27 | 28 | await initJpegDecode(JPEG_DEC_WASM); // JPEG_DEC_WASM is the name of the imported file 29 | const image = await fetch('./image.jpeg').then(res => res.arrayBuffer()).then(decode); 30 | ``` 31 | -------------------------------------------------------------------------------- /packages/avif/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { 14 | EncodeOptions as RawEncodeOptions, 15 | AVIFTune, 16 | } from './codec/enc/avif_enc.js'; 17 | 18 | export { AVIFTune }; 19 | 20 | export type EncodeOptions = RawEncodeOptions & { 21 | lossless: boolean; 22 | }; 23 | 24 | export type ImageData16bit = { 25 | data: Uint16Array; 26 | width: number; 27 | height: number; 28 | }; 29 | 30 | export const label = 'AVIF'; 31 | export const mimeType = 'image/avif'; 32 | export const extension = 'avif'; 33 | export const defaultOptions: EncodeOptions = { 34 | quality: 50, 35 | qualityAlpha: -1, 36 | denoiseLevel: 0, 37 | tileColsLog2: 0, 38 | tileRowsLog2: 0, 39 | speed: 6, 40 | subsample: 1, 41 | chromaDeltaQ: false, 42 | sharpness: 0, 43 | tune: AVIFTune.auto, 44 | enableSharpYUV: false, 45 | bitDepth: 8, 46 | lossless: false, 47 | }; 48 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg-parallel/snippets/wasm-bindgen-rayon-3e04391371ad0a8e/src/workerHelpers.worker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | // Note: our JS should have been generated in 15 | // `[out-dir]/snippets/wasm-bindgen-rayon-[hash]/workerHelpers.worker.js`, 16 | // resolve the main module via `../../..`. 17 | // 18 | // This might need updating if the generated structure changes on wasm-bindgen 19 | // side ever in the future, but works well with bundlers today. The whole 20 | // point of this crate, after all, is to abstract away unstable features 21 | // and temporary bugs so that you don't need to deal with them in your code. 22 | import initWbg, { wbg_rayon_start_worker } from '../../../'; 23 | 24 | onmessage = async ({ data: { module, memory, receiver } }) => { 25 | await initWbg(module, memory); 26 | postMessage(true); 27 | wbg_rayon_start_worker(receiver); 28 | }; 29 | -------------------------------------------------------------------------------- /packages/resize/lib/hqx/pkg/squooshhqx.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint32Array} input_image 5 | * @param {number} input_width 6 | * @param {number} input_height 7 | * @param {number} factor 8 | * @returns {Uint32Array} 9 | */ 10 | export function resize(input_image: Uint32Array, input_width: number, input_height: number, factor: number): Uint32Array; 11 | 12 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 13 | 14 | export interface InitOutput { 15 | readonly memory: WebAssembly.Memory; 16 | readonly resize: (a: number, b: number, c: number, d: number, e: number, f: number) => void; 17 | readonly __wbindgen_add_to_stack_pointer: (a: number) => number; 18 | readonly __wbindgen_malloc: (a: number, b: number) => number; 19 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 20 | } 21 | 22 | export type SyncInitInput = BufferSource | WebAssembly.Module; 23 | /** 24 | * Instantiates the given `module`, which can either be bytes or 25 | * a precompiled `WebAssembly.Module`. 26 | * 27 | * @param {SyncInitInput} module 28 | * 29 | * @returns {InitOutput} 30 | */ 31 | export function initSync(module: SyncInitInput): InitOutput; 32 | 33 | /** 34 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 35 | * for everything else, calls `WebAssembly.instantiate` directly. 36 | * 37 | * @param {InitInput | Promise} module_or_path 38 | * 39 | * @returns {Promise} 40 | */ 41 | export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; 42 | -------------------------------------------------------------------------------- /packages/png/codec/LICENSE.codec.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of Google nor the names of its contributors may 16 | be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /packages/webp/codec/LICENSE.codec.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Google Inc. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of Google nor the names of its contributors may 16 | be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /packages/webp/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import type { EncodeOptions } from './codec/enc/webp_enc.js'; 14 | 15 | export { EncodeOptions }; 16 | 17 | export const label = 'WebP'; 18 | export const mimeType = 'image/webp'; 19 | export const extension = 'webp'; 20 | // These come from struct WebPConfig in encode.h. 21 | export const defaultOptions: EncodeOptions = { 22 | quality: 75, 23 | target_size: 0, 24 | target_PSNR: 0, 25 | method: 4, 26 | sns_strength: 50, 27 | filter_strength: 60, 28 | filter_sharpness: 0, 29 | filter_type: 1, 30 | partitions: 0, 31 | segments: 4, 32 | pass: 1, 33 | show_compressed: 0, 34 | preprocessing: 0, 35 | autofilter: 0, 36 | partition_limit: 0, 37 | alpha_compression: 1, 38 | alpha_filtering: 1, 39 | alpha_quality: 100, 40 | lossless: 0, 41 | exact: 0, 42 | image_hint: 0, 43 | emulate_jpeg_size: 0, 44 | thread_level: 0, 45 | low_memory: 0, 46 | near_lossless: 100, 47 | use_delta_palette: 0, 48 | use_sharp_yuv: 0, 49 | }; 50 | -------------------------------------------------------------------------------- /packages/avif/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. 16 | */ 17 | 18 | export function initEmscriptenModule( 19 | moduleFactory: EmscriptenWasm.ModuleFactory, 20 | wasmModule?: WebAssembly.Module, 21 | moduleOptionOverrides: Partial = {}, 22 | ): Promise { 23 | let instantiateWasm; 24 | 25 | if (wasmModule) { 26 | instantiateWasm = ( 27 | imports: WebAssembly.Imports, 28 | callback: (instance: WebAssembly.Instance) => void, 29 | ) => { 30 | const instance = new WebAssembly.Instance(wasmModule, imports); 31 | callback(instance); 32 | return instance.exports; 33 | }; 34 | } 35 | 36 | return moduleFactory({ 37 | // Just to be safe, don't automatically invoke any wasm functions 38 | noInitialRun: true, 39 | instantiateWasm, 40 | ...moduleOptionOverrides, 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /packages/jpeg/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. 16 | */ 17 | 18 | export function initEmscriptenModule( 19 | moduleFactory: EmscriptenWasm.ModuleFactory, 20 | wasmModule?: WebAssembly.Module, 21 | moduleOptionOverrides: Partial = {}, 22 | ): Promise { 23 | let instantiateWasm; 24 | 25 | if (wasmModule) { 26 | instantiateWasm = ( 27 | imports: WebAssembly.Imports, 28 | callback: (instance: WebAssembly.Instance) => void, 29 | ) => { 30 | const instance = new WebAssembly.Instance(wasmModule, imports); 31 | callback(instance); 32 | return instance.exports; 33 | }; 34 | } 35 | 36 | return moduleFactory({ 37 | // Just to be safe, don't automatically invoke any wasm functions 38 | noInitialRun: true, 39 | instantiateWasm, 40 | ...moduleOptionOverrides, 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /packages/qoi/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. 16 | */ 17 | 18 | export function initEmscriptenModule( 19 | moduleFactory: EmscriptenWasm.ModuleFactory, 20 | wasmModule?: WebAssembly.Module, 21 | moduleOptionOverrides: Partial = {}, 22 | ): Promise { 23 | let instantiateWasm; 24 | 25 | if (wasmModule) { 26 | instantiateWasm = ( 27 | imports: WebAssembly.Imports, 28 | callback: (instance: WebAssembly.Instance) => void, 29 | ) => { 30 | const instance = new WebAssembly.Instance(wasmModule, imports); 31 | callback(instance); 32 | return instance.exports; 33 | }; 34 | } 35 | 36 | return moduleFactory({ 37 | // Just to be safe, don't automatically invoke any wasm functions 38 | noInitialRun: true, 39 | instantiateWasm, 40 | ...moduleOptionOverrides, 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /packages/webp/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file to allow manual instantiation of the Wasm Module. 16 | */ 17 | 18 | export function initEmscriptenModule( 19 | moduleFactory: EmscriptenWasm.ModuleFactory, 20 | wasmModule?: WebAssembly.Module, 21 | moduleOptionOverrides: Partial = {}, 22 | ): Promise { 23 | let instantiateWasm; 24 | 25 | if (wasmModule) { 26 | instantiateWasm = ( 27 | imports: WebAssembly.Imports, 28 | callback: (instance: WebAssembly.Instance) => void, 29 | ) => { 30 | const instance = new WebAssembly.Instance(wasmModule, imports); 31 | callback(instance); 32 | return instance.exports; 33 | }; 34 | } 35 | 36 | return moduleFactory({ 37 | // Just to be safe, don't automatically invoke any wasm functions 38 | noInitialRun: true, 39 | instantiateWasm, 40 | ...moduleOptionOverrides, 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /packages/jxl/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file 16 | * - Allows manual instantiation of the Wasm Module. 17 | */ 18 | 19 | export function initEmscriptenModule( 20 | moduleFactory: EmscriptenWasm.ModuleFactory, 21 | wasmModule?: WebAssembly.Module, 22 | moduleOptionOverrides: Partial = {}, 23 | ): Promise { 24 | let instantiateWasm; 25 | 26 | if (wasmModule) { 27 | instantiateWasm = ( 28 | imports: WebAssembly.Imports, 29 | callback: (instance: WebAssembly.Instance) => void, 30 | ) => { 31 | const instance = new WebAssembly.Instance(wasmModule, imports); 32 | callback(instance); 33 | return instance.exports; 34 | }; 35 | } 36 | 37 | return moduleFactory({ 38 | // Just to be safe, don't automatically invoke any wasm functions 39 | noInitialRun: true, 40 | instantiateWasm, 41 | ...moduleOptionOverrides, 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /examples/web-workers/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | jSquash with Web Workers example 8 | 9 | 10 |

Image Converter (powered by Web Workers)

11 |
12 | 16 |

Choose output image type:

17 |
18 | 21 | 24 | 27 | 30 | 33 |
34 | 35 |
36 |

Output Image (Right click to save)

37 |
38 |
39 |
40 |

41 | Example app using jSquash image codecs. 42 | View the source code on GitHub. 43 |

44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /packages/jpeg/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { EncodeOptions, MozJpegColorSpace } from './codec/enc/mozjpeg_enc.js'; 14 | export { EncodeOptions, MozJpegColorSpace }; 15 | 16 | export type DecodeOptions = { 17 | preserveOrientation: boolean; 18 | }; 19 | 20 | export const label = 'MozJPEG'; 21 | export const mimeType = 'image/jpeg'; 22 | export const extension = 'jpg'; 23 | export const defaultOptions: EncodeOptions = { 24 | quality: 75, 25 | baseline: false, 26 | arithmetic: false, 27 | progressive: true, 28 | optimize_coding: true, 29 | smoothing: 0, 30 | color_space: MozJpegColorSpace.YCbCr, 31 | quant_table: 3, 32 | trellis_multipass: false, 33 | trellis_opt_zero: false, 34 | trellis_opt_table: false, 35 | trellis_loops: 1, 36 | auto_subsample: true, 37 | chroma_subsample: 2, 38 | separate_chroma_quality: false, 39 | chroma_quality: 75, 40 | }; 41 | 42 | export const defaultEncodeOptions = defaultOptions; 43 | 44 | export const defaultDecodeOptions: DecodeOptions = { 45 | preserveOrientation: false, 46 | }; 47 | -------------------------------------------------------------------------------- /examples/cloudflare-worker/README.md: -------------------------------------------------------------------------------- 1 | # Cloudflare Worker Example (Service Worker Format) 2 | 3 | For this example, we will be using the [Cloudflare Worker](https://workers.cloudflare.com/) platform to upgrade images to WebP. 4 | 5 | The example uses the legacy "Service Worker Format" which is still supported by Cloudflare Workers. 6 | 7 | We can use the latest Wrangler CLI to run the example locally and deploy it to Cloudflare Workers. 8 | 9 | ## Running the example locally 10 | 11 | 1. Run `npm install` 12 | 2. Run `npm run start` to start the development server 13 | 14 | ## Usage of jSquash packages in Cloudflare Worker 15 | 16 | One caveat is wrangler won't dynamically bundle the WASM modules with the worker. 17 | 18 | You will need to ensure you configure the Worker to set these as global variables in the [wrangler.toml](wrangler.toml) file. 19 | ``` 20 | # wrangler.toml 21 | [wasm_modules] 22 | # Manually specify the path to the WASM module for each codec 23 | JPEG_DEC_WASM = "node_modules/@jsquash/jpeg/codec/dec/mozjpeg_dec.wasm" 24 | ``` 25 | 26 | If using Wrangler v2 or above, you can also import the WASM modules from the node_modules folder [as seen in the ES Module Format example](/examples/cloudflare-worker-esm-format/README.md#usage-of-jsquash-packages-in-cloudflare-worker). 27 | 28 | The `encode` and `decode` modules both export an `init` function that can be used to manually load the wasm module. 29 | 30 | ```js 31 | import decode, { init as initJpegDecode } from '@jsquash/jpeg/decode'; 32 | 33 | await initJpegDecode(JPEG_DEC_WASM); // The global variable of the wasm module needs to be defined in the wrangler.toml file 34 | const image = await fetch('./image.jpeg').then(res => res.arrayBuffer()).then(decode); 35 | ``` 36 | -------------------------------------------------------------------------------- /packages/jpeg/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/jpeg@1.6.0 4 | 5 | ### Adds 6 | 7 | - Adds support for only providing a module option override to the `init` function directly 8 | 9 | **Example:** 10 | ```ts 11 | import encode, { init } from '@jsquash/jpeg/encode'; 12 | await init({ 13 | locateFile: (path) => { 14 | const remoteLocation = 'https://cdn.mydomain.com/wasm'; 15 | return remoteLocation + path; 16 | } 17 | }); 18 | const buffer = await encode(/* image data */); 19 | ``` 20 | 21 | ### Fixes 22 | 23 | - Updates `locateFile` emscripten module option type to support prefix parameter. 24 | 25 | ## @jsquash/jpeg@1.5.0 26 | 27 | ### Adds 28 | 29 | - Adds ability to preserve the orientation of the image when decoding. When set to `true`, the image will be rotated to the correct orientation. This is useful when the image has an orientation metadata tag that needs to be respected. By default, this is set to `false`. Note: if you are constrained on memory usage, you may want to consider rotating the image yourself either before or after decoding. 30 | 31 | ## @jsquash/jpeg@1.4.0 32 | 33 | ### Adds 34 | 35 | - Adds ability to customise Emscripten module options, e.g. define your own `locateFile` method. 36 | 37 | ## @jsquash/jpeg@1.3.0 38 | 39 | ### Adds 40 | 41 | - Adds Node.js ESM support 42 | - Updates relative imports to use file extensions 43 | - Adds `module` field to relevant `package.json` 44 | - Updates pre.js to polyfill ImageData for Node.js 45 | 46 | ### Misc. 47 | 48 | - Removes *.d.ts.map files from the package 49 | 50 | ## @jsquash/jpeg@1.2.0 51 | 52 | ### Added 53 | 54 | - Include polyfills for Cloudflare Worker environment for easier compatibility 55 | -------------------------------------------------------------------------------- /packages/jxl/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/jxl@1.3.0 4 | 5 | ### Adds 6 | 7 | - Adds a convenience option to set lossless encoding (`encode(imageData, { lossless: true })`) 8 | 9 | ## @jsquash/jxl@1.2.0 10 | 11 | ### Adds 12 | - Adds support for only providing a module option override to the `init` function directly 13 | 14 | **Example:** 15 | ```ts 16 | import encode, { init } from '@jsquash/jxl/encode'; 17 | await init({ 18 | locateFile: (path) => { 19 | const remoteLocation = 'https://cdn.mydomain.com/wasm'; 20 | return remoteLocation + path; 21 | } 22 | }); 23 | const buffer = await encode(/* image data */); 24 | ``` 25 | 26 | ### Fixes 27 | 28 | - Updates `locateFile` emscripten module option type to support prefix parameter. 29 | 30 | ## @jsquash/jxl@1.1.0 31 | 32 | ### Adds 33 | 34 | - Adds Node.js ESM support 35 | - Updates relative imports to use file extensions 36 | - Adds `module` field to relevant `package.json` 37 | - Updates pre.js to polyfill ImageData for Node.js 38 | - Correctly exports init method from encode module 39 | 40 | ### Misc. 41 | 42 | - Removes *.d.ts.map files from the package 43 | 44 | ## @jsquash/jxl@1.0.3 45 | 46 | ### Fixes 47 | 48 | - Add missing `wasm-feature-detect` dependency 49 | 50 | ## @jsquash/jxl@1.0.2 51 | 52 | ### Fixes 53 | 54 | - Stops the WebWorker module code from being instantiated when running in a Cloudflare Worker environment 55 | 56 | ## @jsquash/jxl@1.0.1 57 | 58 | ### Fixes 59 | 60 | - Removed check threads util method that would have prevented threads not working outside of a worker context. That util was specific to the Squoosh app use case. 61 | 62 | ## @jsquash/jxl@1.0.0 63 | 64 | Initial Release. 65 | -------------------------------------------------------------------------------- /packages/resize/lib/resize/pkg/squoosh_resize.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint8Array} input_image 5 | * @param {number} input_width 6 | * @param {number} input_height 7 | * @param {number} output_width 8 | * @param {number} output_height 9 | * @param {number} typ_idx 10 | * @param {boolean} premultiply 11 | * @param {boolean} color_space_conversion 12 | * @returns {Uint8ClampedArray} 13 | */ 14 | export function resize(input_image: Uint8Array, input_width: number, input_height: number, output_width: number, output_height: number, typ_idx: number, premultiply: boolean, color_space_conversion: boolean): Uint8ClampedArray; 15 | 16 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 17 | 18 | export interface InitOutput { 19 | readonly memory: WebAssembly.Memory; 20 | readonly resize: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => void; 21 | readonly __wbindgen_add_to_stack_pointer: (a: number) => number; 22 | readonly __wbindgen_malloc: (a: number, b: number) => number; 23 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 24 | } 25 | 26 | export type SyncInitInput = BufferSource | WebAssembly.Module; 27 | /** 28 | * Instantiates the given `module`, which can either be bytes or 29 | * a precompiled `WebAssembly.Module`. 30 | * 31 | * @param {SyncInitInput} module 32 | * 33 | * @returns {InitOutput} 34 | */ 35 | export function initSync(module: SyncInitInput): InitOutput; 36 | 37 | /** 38 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 39 | * for everything else, calls `WebAssembly.instantiate` directly. 40 | * 41 | * @param {InitInput | Promise} module_or_path 42 | * 43 | * @returns {Promise} 44 | */ 45 | export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; 46 | -------------------------------------------------------------------------------- /examples/web-workers/main.js: -------------------------------------------------------------------------------- 1 | async function convert(sourceType, outputType, fileBuffer) { 2 | const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' }); 3 | // Send data to the worker to convert to the desired output type 4 | worker.postMessage({ sourceType, outputType, fileBuffer }); 5 | 6 | return new Promise((resolve, reject) => { 7 | worker.addEventListener('message', (event) => { 8 | // The event data will contain the converted image from the worker 9 | resolve(event.data); 10 | }); 11 | worker.addEventListener('error', reject); 12 | }); 13 | } 14 | 15 | function blobToBase64(blob) { 16 | return new Promise((resolve, _) => { 17 | const reader = new FileReader(); 18 | reader.onloadend = () => resolve(reader.result); 19 | reader.readAsDataURL(blob); 20 | }); 21 | } 22 | 23 | async function showOutput (imageBuffer, outputType) { 24 | const preview = document.querySelector('#preview'); 25 | const imageBlob = new Blob([imageBuffer], { type: `image/${outputType}` }); 26 | const base64String = await blobToBase64(imageBlob); 27 | const previewImg = document.createElement('img'); 28 | previewImg.src = base64String; 29 | preview.innerHTML = ''; 30 | preview.appendChild(previewImg); 31 | } 32 | 33 | async function initForm () { 34 | const form = document.querySelector('form'); 35 | 36 | form.addEventListener('submit', async (event) => { 37 | event.preventDefault(); 38 | const formData = new FormData(form); 39 | const file = formData.get('file'); 40 | const sourceType = file.name.endsWith('jxl') ? 'jxl' : file.type.replace('image/', ''); 41 | const outputType = formData.get('outputType'); 42 | const fileBuffer = await file.arrayBuffer(); 43 | const imageBuffer = await convert(sourceType, outputType, fileBuffer); 44 | showOutput(imageBuffer, outputType); 45 | }); 46 | } 47 | 48 | async function main () { 49 | initForm(); 50 | } 51 | 52 | main(); 53 | -------------------------------------------------------------------------------- /packages/resize/meta.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | type WorkerResizeMethods = 15 | | 'triangle' 16 | | 'catrom' 17 | | 'mitchell' 18 | | 'lanczos3' 19 | | 'hqx' 20 | | 'magicKernel' 21 | | 'magicKernelSharp2013' 22 | | 'magicKernelSharp2021'; 23 | 24 | export const workerResizeMethods: WorkerResizeMethods[] = [ 25 | 'triangle', 26 | 'catrom', 27 | 'mitchell', 28 | 'lanczos3', 29 | 'hqx', 30 | 'magicKernel', 31 | 'magicKernelSharp2013', 32 | 'magicKernelSharp2021', 33 | ]; 34 | 35 | export type Options = WorkerResizeOptions | VectorResizeOptions; 36 | 37 | export interface ResizeOptionsCommon { 38 | width: number; 39 | height: number; 40 | fitMethod: 'stretch' | 'contain'; 41 | } 42 | 43 | export interface WorkerResizeOptions extends ResizeOptionsCommon { 44 | method: WorkerResizeMethods; 45 | premultiply: boolean; 46 | linearRGB: boolean; 47 | } 48 | 49 | export interface VectorResizeOptions extends ResizeOptionsCommon { 50 | method: 'vector'; 51 | } 52 | 53 | export const defaultOptions: Options = { 54 | // Width and height will always default to the image size. 55 | // This is set elsewhere. 56 | width: 1, 57 | height: 1, 58 | // This will be set to 'vector' if the input is SVG. 59 | method: 'lanczos3', 60 | fitMethod: 'stretch', 61 | premultiply: true, 62 | linearRGB: true, 63 | }; 64 | -------------------------------------------------------------------------------- /packages/resize/lib/magic-kernel/pkg/jsquash_magic_kernel.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint8Array} data 5 | * @param {number} input_width 6 | * @param {number} input_height 7 | * @param {number} output_width 8 | * @param {number} output_height 9 | * @param {string} version 10 | * @returns {ImageData} 11 | */ 12 | export function resize(data: Uint8Array, input_width: number, input_height: number, output_width: number, output_height: number, version: string): ImageData; 13 | 14 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 15 | 16 | export interface InitOutput { 17 | readonly memory: WebAssembly.Memory; 18 | readonly resize: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => number; 19 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 20 | readonly __wbindgen_malloc: (a: number, b: number) => number; 21 | readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number; 22 | } 23 | 24 | export type SyncInitInput = BufferSource | WebAssembly.Module; 25 | /** 26 | * Instantiates the given `module`, which can either be bytes or 27 | * a precompiled `WebAssembly.Module`. 28 | * 29 | * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated. 30 | * 31 | * @returns {InitOutput} 32 | */ 33 | export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput; 34 | 35 | /** 36 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 37 | * for everything else, calls `WebAssembly.instantiate` directly. 38 | * 39 | * @param {{ module_or_path: InitInput | Promise }} module_or_path - Passing `InitInput` directly is deprecated. 40 | * 41 | * @returns {Promise} 42 | */ 43 | export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise } | InitInput | Promise): Promise; 44 | -------------------------------------------------------------------------------- /packages/jpeg/codec/Makefile: -------------------------------------------------------------------------------- 1 | CODEC_URL := https://github.com/mozilla/mozjpeg/archive/v3.3.1.tar.gz 2 | CODEC_DIR := node_modules/mozjpeg 3 | CODEC_OUT_RELATIVE := .libs/libjpeg.a rdswitch.o 4 | CODEC_OUT := $(addprefix $(CODEC_DIR)/, $(CODEC_OUT_RELATIVE)) 5 | ENVIRONMENT = web,worker 6 | 7 | PRE_JS = pre.js 8 | OUT_JS := enc/mozjpeg_enc.js dec/mozjpeg_dec.js 9 | OUT_WASM := $(OUT_JS:.js=.wasm) 10 | 11 | .PHONY: all clean 12 | 13 | all: $(OUT_JS) 14 | 15 | # Define dependencies for all variations of build artifacts. 16 | $(filter enc/%,$(OUT_JS)): enc/mozjpeg_enc.cpp 17 | $(filter dec/%,$(OUT_JS)): dec/mozjpeg_dec.cpp 18 | 19 | %.js: $(CODEC_OUT) 20 | $(CXX) \ 21 | -I $(CODEC_DIR) \ 22 | ${CXXFLAGS} \ 23 | ${LDFLAGS} \ 24 | --pre-js $(PRE_JS) \ 25 | --bind \ 26 | -s ENVIRONMENT=$(ENVIRONMENT) \ 27 | -s EXPORT_ES6=1 \ 28 | -s DYNAMIC_EXECUTION=0 \ 29 | -s MODULARIZE=1 \ 30 | -o $@ \ 31 | $+ 32 | 33 | # This one is a bit special: there is no rule for .libs/libjpeg.a 34 | # so we use libjpeg.la which implicitly builds that one instead. 35 | $(CODEC_DIR)/.libs/libjpeg.a: $(CODEC_DIR)/Makefile 36 | $(MAKE) -C $(CODEC_DIR) libjpeg.la 37 | 38 | $(CODEC_DIR)/rdswitch.o: $(CODEC_DIR)/Makefile 39 | $(MAKE) -C $(CODEC_DIR) rdswitch.o 40 | 41 | $(CODEC_DIR)/Makefile: $(CODEC_DIR)/configure 42 | cd $(CODEC_DIR) && ./configure \ 43 | --host=wasm32 \ 44 | --disable-shared \ 45 | --without-turbojpeg \ 46 | --without-simd \ 47 | --without-arith-enc \ 48 | --without-arith-dec \ 49 | --with-build-date=jsquash 50 | # ^ If not provided with a dummy value, MozJPEG includes a build date in the 51 | # binary as part of the version string, making binaries different each time. 52 | 53 | $(CODEC_DIR)/configure: $(CODEC_DIR)/configure.ac 54 | cd $(CODEC_DIR) && autoreconf -iv 55 | 56 | $(CODEC_DIR)/configure.ac: $(CODEC_DIR) 57 | 58 | $(CODEC_DIR): 59 | mkdir -p $@ 60 | curl -sL $(CODEC_URL) | tar xz --strip 1 -C $@ 61 | 62 | clean: 63 | $(RM) $(OUT_JS) $(OUT_WASM) 64 | $(MAKE) -C $(CODEC_DIR) clean 65 | -------------------------------------------------------------------------------- /packages/avif/codec/enc/avif_enc_mt.worker.mjs: -------------------------------------------------------------------------------- 1 | "use strict";var Module={};var initializedJS=false;function threadPrintErr(...args){var text=args.join(" ");console.error(text)}function threadAlert(...args){var text=args.join(" ");postMessage({cmd:"alert",text:text,threadId:Module["_pthread_self"]()})}var err=threadPrintErr;self.alert=threadAlert;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason||e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=(...args)=>{postMessage({cmd:"callHandler",handler:handler,args:args})}}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(exports=>exports.default(Module))}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err(`worker.js received unknown command ${e.data.cmd}`);err(e.data)}}catch(ex){Module["__emscripten_thread_crashed"]?.();throw ex}}self.onmessage=handleMessage; 2 | -------------------------------------------------------------------------------- /packages/webp/codec/Makefile: -------------------------------------------------------------------------------- 1 | CODEC_URL = https://github.com/webmproject/libwebp/archive/d2e245ea9e959a5a79e1db0ed2085206947e98f2.tar.gz 2 | CODEC_DIR = node_modules/libwebp 3 | CODEC_BUILD_ROOT := $(CODEC_DIR)/build 4 | CODEC_BASELINE_BUILD_DIR := $(CODEC_BUILD_ROOT)/baseline 5 | CODEC_SIMD_BUILD_DIR := $(CODEC_BUILD_ROOT)/simd 6 | ENVIRONMENT = web,worker 7 | 8 | PRE_JS = pre.js 9 | OUT_JS = enc/webp_enc.js enc/webp_enc_simd.js dec/webp_dec.js 10 | OUT_WASM := $(OUT_JS:.js=.wasm) 11 | 12 | .PHONY: all clean 13 | 14 | all: $(OUT_JS) 15 | 16 | # Define dependencies for all variations of build artifacts. 17 | $(filter enc/%,$(OUT_JS)): enc/webp_enc.o 18 | $(filter dec/%,$(OUT_JS)): dec/webp_dec.o 19 | enc/webp_enc.js dec/webp_dec.js: $(CODEC_BASELINE_BUILD_DIR)/libwebp.a 20 | enc/webp_enc_simd.js: $(CODEC_SIMD_BUILD_DIR)/libwebp.a 21 | 22 | $(OUT_JS): 23 | $(LD) \ 24 | $(LDFLAGS) \ 25 | --pre-js $(PRE_JS) \ 26 | --bind \ 27 | -s ENVIRONMENT=$(ENVIRONMENT) \ 28 | -s EXPORT_ES6=1 \ 29 | -s DYNAMIC_EXECUTION=0 \ 30 | -s MODULARIZE=1 \ 31 | -o $@ \ 32 | $+ 33 | 34 | %.o: %.cpp $(CODEC_DIR)/CMakeLists.txt 35 | $(CXX) -c \ 36 | $(CXXFLAGS) \ 37 | -I $(CODEC_DIR) \ 38 | -o $@ \ 39 | $< 40 | 41 | %/libwebp.a: %/Makefile 42 | $(MAKE) -C $(@D) 43 | 44 | # Enable SIMD on a SIMD build. 45 | $(CODEC_SIMD_BUILD_DIR)/Makefile: CMAKE_FLAGS+=-DWEBP_ENABLE_SIMD=1 46 | 47 | %/Makefile: $(CODEC_DIR)/CMakeLists.txt 48 | emcmake cmake \ 49 | $(CMAKE_FLAGS) \ 50 | -DCMAKE_DISABLE_FIND_PACKAGE_Threads=1 \ 51 | -DWEBP_BUILD_ANIM_UTILS=0 \ 52 | -DWEBP_BUILD_CWEBP=0 \ 53 | -DWEBP_BUILD_DWEBP=0 \ 54 | -DWEBP_BUILD_GIF2WEBP=0 \ 55 | -DWEBP_BUILD_IMG2WEBP=0 \ 56 | -DWEBP_BUILD_VWEBP=0 \ 57 | -DWEBP_BUILD_WEBPINFO=0 \ 58 | -DWEBP_BUILD_WEBPMUX=0 \ 59 | -DWEBP_BUILD_EXTRAS=0 \ 60 | -B $(@D) \ 61 | $(>, 17 | sw: u32, 18 | sh: u32, 19 | ) -> ImageData; 20 | } 21 | 22 | fn convert_from_rgba_u8_slice(data: &[u8], width: usize, height: usize) -> ImageF64 { 23 | let data_f64: Vec<_> = data.iter().map(|x| *x as f64).collect(); 24 | ImageF64::new(data_f64, RGBA_CHANNEL_SIZE, width as u32, height as u32) 25 | } 26 | 27 | fn get_version_from_string(version: String) -> Version { 28 | if version == "magicKernelSharp2021" { 29 | return Version::MagicKernelSharp2021; 30 | } 31 | 32 | if version == "magicKernelSharp2013" { 33 | return Version::MagicKernelSharp2013; 34 | } 35 | 36 | if version == "magicKernel" { 37 | return Version::MagicKernel; 38 | } 39 | 40 | panic!("Version not recognized: {}", version); 41 | } 42 | 43 | #[wasm_bindgen] 44 | pub fn resize( 45 | data: &[u8], 46 | input_width: usize, 47 | input_height: usize, 48 | output_width: usize, 49 | output_height: usize, 50 | version: String 51 | ) -> ImageData { 52 | let resized = magic_resize( 53 | &convert_from_rgba_u8_slice(data, input_width, input_height), 54 | get_version_from_string(version), 55 | Some(output_width as u32), 56 | Some(output_height as u32), 57 | ); 58 | 59 | let buf: Vec<_> = resized.into(); 60 | let buf: Vec = buf.iter().map(|x| *x as u8).collect(); 61 | 62 | 63 | ImageData::new_with_owned_u8_clamped_array_and_sh( 64 | wasm_bindgen::Clamped(buf), 65 | output_width as u32, 66 | output_height as u32, 67 | ) 68 | } 69 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg/squoosh_oxipng.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint8Array} data 5 | * @param {number} level 6 | * @param {boolean} interlace 7 | * @param {boolean} optimize_alpha 8 | * @returns {Uint8Array} 9 | */ 10 | export function optimise(data: Uint8Array, level: number, interlace: boolean, optimize_alpha: boolean): Uint8Array; 11 | /** 12 | * @param {Uint8ClampedArray} data 13 | * @param {number} width 14 | * @param {number} height 15 | * @param {number} level 16 | * @param {boolean} interlace 17 | * @param {boolean} optimize_alpha 18 | * @returns {Uint8Array} 19 | */ 20 | export function optimise_raw(data: Uint8ClampedArray, width: number, height: number, level: number, interlace: boolean, optimize_alpha: boolean): Uint8Array; 21 | 22 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 23 | 24 | export interface InitOutput { 25 | readonly memory: WebAssembly.Memory; 26 | readonly optimise: (a: number, b: number, c: number, d: number, e: number, f: number) => void; 27 | readonly optimise_raw: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void; 28 | readonly __wbindgen_add_to_stack_pointer: (a: number) => number; 29 | readonly __wbindgen_malloc: (a: number, b: number) => number; 30 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 31 | } 32 | 33 | export type SyncInitInput = BufferSource | WebAssembly.Module; 34 | /** 35 | * Instantiates the given `module`, which can either be bytes or 36 | * a precompiled `WebAssembly.Module`. 37 | * 38 | * @param {SyncInitInput} module 39 | * 40 | * @returns {InitOutput} 41 | */ 42 | export function initSync(module: SyncInitInput): InitOutput; 43 | 44 | /** 45 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 46 | * for everything else, calls `WebAssembly.instantiate` directly. 47 | * 48 | * @param {InitInput | Promise} module_or_path 49 | * 50 | * @returns {Promise} 51 | */ 52 | export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; 53 | -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc_mt.worker.js: -------------------------------------------------------------------------------- 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;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=function(){postMessage({cmd:"callHandler",handler:handler,args:[...arguments]})}}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(exports=>exports.default(Module))}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage; 2 | -------------------------------------------------------------------------------- /packages/jxl/codec/enc/jxl_enc_mt_simd.worker.js: -------------------------------------------------------------------------------- 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;Module["instantiateWasm"]=(info,receiveInstance)=>{var module=Module["wasmModule"];Module["wasmModule"]=null;var instance=new WebAssembly.Instance(module,info);return receiveInstance(instance)};self.onunhandledrejection=e=>{throw e.reason??e};function handleMessage(e){try{if(e.data.cmd==="load"){let messageQueue=[];self.onmessage=e=>messageQueue.push(e);self.startWorker=instance=>{Module=instance;postMessage({"cmd":"loaded"});for(let msg of messageQueue){handleMessage(msg)}self.onmessage=handleMessage};Module["wasmModule"]=e.data.wasmModule;for(const handler of e.data.handlers){Module[handler]=function(){postMessage({cmd:"callHandler",handler:handler,args:[...arguments]})}}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(exports=>exports.default(Module))}else if(e.data.cmd==="run"){Module["__emscripten_thread_init"](e.data.pthread_ptr,0,0,1);Module["__emscripten_thread_mailbox_await"](e.data.pthread_ptr);Module["establishStackSpace"]();Module["PThread"].receiveObjectTransfer(e.data);Module["PThread"].threadInitTLS();if(!initializedJS){Module["__embind_initialize_bindings"]();initializedJS=true}try{Module["invokeEntryPoint"](e.data.start_routine,e.data.arg)}catch(ex){if(ex!="unwind"){throw ex}}}else if(e.data.cmd==="cancel"){if(Module["_pthread_self"]()){Module["__emscripten_thread_exit"](-1)}}else if(e.data.target==="setimmediate"){}else if(e.data.cmd==="checkMailbox"){if(initializedJS){Module["checkMailbox"]()}}else if(e.data.cmd){err("worker.js received unknown command "+e.data.cmd);err(e.data)}}catch(ex){if(Module["__emscripten_thread_crashed"]){Module["__emscripten_thread_crashed"]()}throw ex}}self.onmessage=handleMessage; 2 | -------------------------------------------------------------------------------- /packages/avif/codec/dec/avif_dec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "avif/avif.h" 4 | 5 | using namespace emscripten; 6 | 7 | thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray"); 8 | thread_local const val Uint16Array = val::global("Uint16Array"); 9 | thread_local const val ImageData = val::global("ImageData"); 10 | thread_local const val Object = val::global("Object"); 11 | 12 | val decode(std::string avifimage, uint32_t bitDepth = 8) { 13 | avifImage* image = avifImageCreateEmpty(); 14 | avifDecoder* decoder = avifDecoderCreate(); 15 | avifResult decodeResult = 16 | avifDecoderReadMemory(decoder, image, (uint8_t*)avifimage.c_str(), avifimage.length()); 17 | 18 | // image is an independent copy of decoded data, decoder may be destroyed here 19 | avifDecoderDestroy(decoder); 20 | 21 | val result = val::null(); 22 | if (decodeResult == AVIF_RESULT_OK) { 23 | avifRGBImage rgb; 24 | avifRGBImageSetDefaults(&rgb, image); 25 | 26 | rgb.depth = bitDepth; 27 | 28 | avifRGBImageAllocatePixels(&rgb); 29 | avifImageYUVToRGB(image, &rgb); 30 | 31 | if (bitDepth != 8) { 32 | const size_t pixelCount = rgb.width * rgb.height; 33 | const size_t channelCount = 4; 34 | const size_t totalElements = pixelCount * channelCount; 35 | 36 | auto pixelData = Uint16Array.new_(typed_memory_view(totalElements, 37 | reinterpret_cast(rgb.pixels))); 38 | 39 | auto pixelArray = pixelData.call("slice"); 40 | 41 | result = Object.new_(); 42 | result.set("data", pixelArray); 43 | result.set("width", rgb.width); 44 | result.set("height", rgb.height); 45 | } else { 46 | result = ImageData.new_( 47 | Uint8ClampedArray.new_(typed_memory_view(rgb.rowBytes * rgb.height, rgb.pixels)), 48 | rgb.width, 49 | rgb.height); 50 | } 51 | 52 | // Now we can safely free the RGB pixels: 53 | avifRGBImageFreePixels(&rgb); 54 | } 55 | 56 | avifImageDestroy(image); 57 | return result; 58 | } 59 | 60 | EMSCRIPTEN_BINDINGS(my_module) { 61 | function("decode", &decode); 62 | } -------------------------------------------------------------------------------- /packages/qoi/decode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have copied this code from the original and modified 16 | * to align with the jSquash project structure. 17 | */ 18 | 19 | import type { QOIModule } from './codec/dec/qoi_dec.js'; 20 | import { initEmscriptenModule } from './utils.js'; 21 | 22 | import qoi_dec from './codec/dec/qoi_dec.js'; 23 | 24 | let emscriptenModule: Promise; 25 | 26 | export async function init( 27 | moduleOptionOverrides?: Partial, 28 | ): Promise; 29 | export async function init( 30 | module?: WebAssembly.Module, 31 | moduleOptionOverrides?: Partial, 32 | ): Promise { 33 | let actualModule: WebAssembly.Module | undefined = module; 34 | let actualOptions: Partial | undefined = 35 | moduleOptionOverrides; 36 | 37 | // If only one argument is provided and it's not a WebAssembly.Module 38 | if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { 39 | actualModule = undefined; 40 | actualOptions = module as unknown as Partial; 41 | } 42 | 43 | emscriptenModule = initEmscriptenModule(qoi_dec, actualModule, actualOptions); 44 | } 45 | 46 | export default async function decode(buffer: ArrayBuffer): Promise { 47 | if (!emscriptenModule) await init(); 48 | 49 | const module = await emscriptenModule; 50 | const result = module.decode(buffer); 51 | if (!result) throw new Error('Decoding error'); 52 | return result; 53 | } 54 | -------------------------------------------------------------------------------- /packages/png/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/png@3.1.1 4 | 5 | ### Fixes 6 | 7 | - Fixes the type definitions for the `encode` and `decode` methods to work correctly with the intended bitDepths. 8 | 9 | ## @jsquash/png@3.1.0 10 | 11 | ### Added 12 | 13 | - Added `bitDepth` option to `decode` method to allow decoding of 16-bit PNGs to their 16-bit RGBA values 14 | - Added `encode` method to allow encoding of 16-bit RGBA image data 15 | - A Uint16Array is required for the pixel data when `bitDepth` is set to 16 16 | 17 | ## @jsquash/png@3.0.1 18 | 19 | ### Fixes 20 | 21 | - Fixes the decoding of PNG images using non-rgba color types. 22 | 23 | ## @jsquash/png@3.0.0 24 | 25 | ### Breaking Changes 26 | 27 | - `encode` method now returns an `ArrayBuffer` which matches the return type of other jSquash `encode` methods 28 | - Ignores checksum errors. Allows images with invalid header chunks to be decoded (Fixes [#44](https://github.com/jamsinclair/jSquash/issues/44)) 29 | - Upgrades codec to image-png 0.17.10 (increases wasm file size by 54KB) 30 | - Codec wasm and js files moved to /codec/pkg dir (due to addition of Rust source) 31 | - If you are accessing the wasm file by path you'll need to update your paths to reference `node_modules/@jsquash/png/codec/pkg/squoosh_png_bg.wasm`. It's now nested in the `pkg` dir. 32 | 33 | ## @jsquash/png@2.2.0 34 | 35 | ### Adds 36 | 37 | - Adds Node.js ESM support 38 | - Updates relative imports to use file extensions 39 | - Adds `module` field to relevant `package.json` 40 | - Updates pre.js to polyfill ImageData for Node.js 41 | 42 | ### Misc. 43 | 44 | - Removes *.d.ts.map files from the package 45 | 46 | ## @jsquash/png@2.1.4 47 | 48 | ### Fixes 49 | 50 | - Removes unused wasm-feature-detect dependency 51 | 52 | ## @jsquash/png@2.1.2 53 | 54 | Re-release of 2.1.1 with correct dist files 55 | ### Fixes 56 | 57 | - Check for caches object on `globalThis` before using it 58 | 59 | ## @jsquash/png@2.1.1 60 | 61 | ### Fixes 62 | 63 | - Check for caches object on `globalThis` before using it 64 | 65 | ## @jsquash/png@2.1.0 66 | 67 | ### Added 68 | 69 | - Include polyfills for Cloudflare Worker environment for easier compatibility 70 | -------------------------------------------------------------------------------- /packages/jxl/decode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have copied this code from the @jsquash/webp decode module 16 | * and modified it to decode JPEG XL images. 17 | */ 18 | 19 | import jxlDecoder, { JXLModule } from './codec/dec/jxl_dec.js'; 20 | import { initEmscriptenModule } from './utils.js'; 21 | 22 | let emscriptenModule: Promise; 23 | 24 | export async function init( 25 | moduleOptionOverrides?: Partial, 26 | ): Promise; 27 | export async function init( 28 | module?: WebAssembly.Module, 29 | moduleOptionOverrides?: Partial, 30 | ): Promise { 31 | let actualModule: WebAssembly.Module | undefined = module; 32 | let actualOptions: Partial | undefined = 33 | moduleOptionOverrides; 34 | 35 | // If only one argument is provided and it's not a WebAssembly.Module 36 | if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { 37 | actualModule = undefined; 38 | actualOptions = module as unknown as Partial; 39 | } 40 | 41 | emscriptenModule = initEmscriptenModule( 42 | jxlDecoder, 43 | actualModule, 44 | actualOptions, 45 | ); 46 | return emscriptenModule; 47 | } 48 | 49 | export default async function decode(buffer: ArrayBuffer): Promise { 50 | if (!emscriptenModule) emscriptenModule = init(); 51 | 52 | const module = await emscriptenModule; 53 | const result = module.decode(buffer); 54 | if (!result) throw new Error('Decoding error'); 55 | return result; 56 | } 57 | -------------------------------------------------------------------------------- /examples/web-workers/worker.js: -------------------------------------------------------------------------------- 1 | import * as avif from '@jsquash/avif'; 2 | import * as jpeg from '@jsquash/jpeg'; 3 | import * as jxl from '@jsquash/jxl'; 4 | import * as png from '@jsquash/png'; 5 | import * as webp from '@jsquash/webp'; 6 | 7 | let isConverting = false; 8 | 9 | async function decode (sourceType, fileBuffer) { 10 | switch (sourceType) { 11 | case 'avif': 12 | return await avif.decode(fileBuffer); 13 | case 'jpeg': 14 | return await jpeg.decode(fileBuffer); 15 | case 'jxl': 16 | return await jxl.decode(fileBuffer); 17 | case 'png': 18 | return await png.decode(fileBuffer); 19 | case 'webp': 20 | return await webp.decode(fileBuffer); 21 | default: 22 | throw new Error(`Unknown source type: ${sourceType}`); 23 | } 24 | } 25 | 26 | async function encode (outputType, imageData) { 27 | switch (outputType) { 28 | case 'avif': 29 | return await avif.encode(imageData); 30 | case 'jpeg': 31 | return await jpeg.encode(imageData); 32 | case 'jxl': 33 | return await jxl.encode(imageData); 34 | case 'png': 35 | return await png.encode(imageData); 36 | case 'webp': 37 | return await webp.encode(imageData); 38 | default: 39 | throw new Error(`Unknown output type: ${outputType}`); 40 | } 41 | } 42 | 43 | async function convert (sourceType, outputType, fileBuffer) { 44 | const imageData = await decode(sourceType, fileBuffer); 45 | return encode(outputType, imageData); 46 | } 47 | 48 | addEventListener('message', async function (event) { 49 | const { sourceType, outputType, fileBuffer } = event.data; 50 | 51 | if (isConverting) { 52 | // Prevent multiple conversion requests being sent to the same worker. 53 | throw new Error('Conversion task already in progress'); 54 | } 55 | 56 | if (!sourceType || !outputType || !fileBuffer) { 57 | throw new Error('Inputs sourceType, outputType and fileBuffer were not present in message'); 58 | } 59 | 60 | isConverting = true; 61 | const result = await convert(sourceType, outputType, fileBuffer); 62 | 63 | // Send the converted image back to the main thread 64 | postMessage(result); 65 | isConverting = false; 66 | }); 67 | -------------------------------------------------------------------------------- /packages/webp/decode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file to accept an ArrayBuffer instead of typed array 16 | * and manually allow instantiation of the Wasm Module. 17 | */ 18 | import type { WebPModule } from './codec/dec/webp_dec.js'; 19 | 20 | import webp_dec from './codec/dec/webp_dec.js'; 21 | import { initEmscriptenModule } from './utils.js'; 22 | 23 | let emscriptenModule: Promise; 24 | 25 | export async function init( 26 | moduleOptionOverrides?: Partial, 27 | ): Promise; 28 | export async function init( 29 | module?: WebAssembly.Module, 30 | moduleOptionOverrides?: Partial, 31 | ): Promise { 32 | let actualModule: WebAssembly.Module | undefined = module; 33 | let actualOptions: Partial | undefined = 34 | moduleOptionOverrides; 35 | 36 | // If only one argument is provided and it's not a WebAssembly.Module 37 | if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { 38 | actualModule = undefined; 39 | actualOptions = module as unknown as Partial; 40 | } 41 | 42 | emscriptenModule = initEmscriptenModule( 43 | webp_dec, 44 | actualModule, 45 | actualOptions, 46 | ); 47 | } 48 | 49 | export default async function decode(buffer: ArrayBuffer): Promise { 50 | if (!emscriptenModule) init(); 51 | 52 | const module = await emscriptenModule; 53 | const result = module.decode(buffer); 54 | if (!result) throw new Error('Decoding error'); 55 | return result; 56 | } 57 | -------------------------------------------------------------------------------- /packages/qoi/encode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have copied this code from the original and modified 16 | * to align with the jSquash project structure. 17 | */ 18 | import type { QOIModule } from './codec/enc/qoi_enc.js'; 19 | 20 | import qoi_enc from './codec/enc/qoi_enc.js'; 21 | import { initEmscriptenModule } from './utils.js'; 22 | 23 | let emscriptenModule: Promise; 24 | 25 | export async function init( 26 | moduleOptionOverrides?: Partial, 27 | ): Promise; 28 | export async function init( 29 | module?: WebAssembly.Module, 30 | moduleOptionOverrides?: Partial, 31 | ): Promise { 32 | let actualModule: WebAssembly.Module | undefined = module; 33 | let actualOptions: Partial | undefined = 34 | moduleOptionOverrides; 35 | 36 | // If only one argument is provided and it's not a WebAssembly.Module 37 | if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { 38 | actualModule = undefined; 39 | actualOptions = module as unknown as Partial; 40 | } 41 | 42 | emscriptenModule = initEmscriptenModule(qoi_enc, actualModule, actualOptions); 43 | } 44 | 45 | export default async function encode(data: ImageData): Promise { 46 | if (!emscriptenModule) await init(); 47 | 48 | const module = await emscriptenModule; 49 | const resultView = module.encode(data.data, data.width, data.height); 50 | // wasm can't run on SharedArrayBuffers, so we hard-cast to ArrayBuffer. 51 | return resultView.buffer as ArrayBuffer; 52 | } 53 | -------------------------------------------------------------------------------- /packages/png/decode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have copied this code from the JPEG encode module 16 | * and modified it to decode PNG images. 17 | */ 18 | 19 | import type { 20 | ImageDataRGBA16, 21 | InitInput, 22 | InitOutput as PngModule, 23 | } from './codec/pkg/squoosh_png.js'; 24 | import initPngModule, { 25 | decode as pngDecodeWasm, 26 | decode_rgba16 as pngDecodeRgba16Wasm, 27 | } from './codec/pkg/squoosh_png.js'; 28 | 29 | let pngModule: Promise; 30 | 31 | export interface DecodeOptions { 32 | bitDepth?: 8 | 16; 33 | } 34 | 35 | export async function init(moduleOrPath?: InitInput): Promise { 36 | if (!pngModule) { 37 | pngModule = initPngModule(moduleOrPath); 38 | } 39 | 40 | return pngModule; 41 | } 42 | 43 | export async function decode( 44 | data: ArrayBuffer, 45 | options: { bitDepth: 16 }, 46 | ): Promise; 47 | export async function decode( 48 | data: ArrayBuffer, 49 | options?: { bitDepth?: 8 }, 50 | ): Promise; 51 | export async function decode( 52 | data: ArrayBuffer, 53 | options: DecodeOptions = {}, 54 | ): Promise { 55 | await init(); 56 | 57 | const { bitDepth = 8 } = options; 58 | 59 | if (bitDepth === 16) { 60 | const imageData = await pngDecodeRgba16Wasm(new Uint8Array(data)); 61 | if (!imageData) throw new Error('Encoding error.'); 62 | return imageData; 63 | } 64 | 65 | const imageData = await pngDecodeWasm(new Uint8Array(data)); 66 | 67 | if (!imageData) throw new Error('Encoding error.'); 68 | 69 | return imageData; 70 | } 71 | 72 | export default decode; 73 | -------------------------------------------------------------------------------- /packages/oxipng/codec/pkg-parallel/snippets/wasm-bindgen-rayon-3e04391371ad0a8e/src/workerHelpers.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | // Note: this is never used, but necessary to prevent a bug in Firefox 15 | // (https://bugzilla.mozilla.org/show_bug.cgi?id=1702191) where it collects 16 | // Web Workers that have a shared WebAssembly memory with the main thread, 17 | // but are not explicitly rooted via a `Worker` instance. 18 | // 19 | // By storing them in a variable, we can keep `Worker` objects around and 20 | // prevent them from getting GC-d. 21 | let _workers; 22 | 23 | export async function startWorkers(module, memory, builder) { 24 | if (builder.numThreads() === 0) { 25 | throw new Error(`num_threads must be > 0.`); 26 | } 27 | 28 | const workerInit = { 29 | module, 30 | memory, 31 | receiver: builder.receiver() 32 | }; 33 | 34 | _workers = await Promise.all( 35 | Array.from({ length: builder.numThreads() }, async () => { 36 | // Self-spawn into a new Worker. 37 | // 38 | // TODO: while `new URL('...', import.meta.url) becomes a semi-standard 39 | // way to get asset URLs relative to the module across various bundlers 40 | // and browser, ideally we should switch to `import.meta.resolve` 41 | // once it becomes a standard. 42 | const worker = new Worker( 43 | new URL('./workerHelpers.worker.js', import.meta.url), 44 | { 45 | type: 'module' 46 | } 47 | ); 48 | worker.postMessage(workerInit); 49 | await new Promise(resolve => 50 | worker.addEventListener('message', resolve, { once: true }) 51 | ); 52 | return worker; 53 | }) 54 | ); 55 | builder.build(); 56 | } 57 | -------------------------------------------------------------------------------- /packages/png/codec/pkg/squoosh_png.d.ts: -------------------------------------------------------------------------------- 1 | /* tslint:disable */ 2 | /* eslint-disable */ 3 | /** 4 | * @param {Uint8Array} data 5 | * @param {number} width 6 | * @param {number} height 7 | * @param {number} bit_depth 8 | * @returns {Uint8Array} 9 | */ 10 | export function encode(data: Uint8Array, width: number, height: number, bit_depth: number): Uint8Array; 11 | /** 12 | * @param {Uint8Array} data 13 | * @returns {ImageData} 14 | */ 15 | export function decode(data: Uint8Array): ImageData; 16 | /** 17 | * @param {Uint8Array} data 18 | * @returns {ImageDataRGBA16} 19 | */ 20 | export function decode_rgba16(data: Uint8Array): ImageDataRGBA16; 21 | /** 22 | */ 23 | export class ImageDataRGBA16 { 24 | free(): void; 25 | /** 26 | */ 27 | readonly data: Uint16Array; 28 | /** 29 | */ 30 | readonly height: number; 31 | /** 32 | */ 33 | readonly width: number; 34 | } 35 | 36 | export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; 37 | 38 | export interface InitOutput { 39 | readonly memory: WebAssembly.Memory; 40 | readonly __wbg_imagedatargba16_free: (a: number) => void; 41 | readonly imagedatargba16_width: (a: number) => number; 42 | readonly imagedatargba16_height: (a: number) => number; 43 | readonly imagedatargba16_data: (a: number) => number; 44 | readonly encode: (a: number, b: number, c: number, d: number, e: number, f: number) => void; 45 | readonly decode: (a: number, b: number) => number; 46 | readonly decode_rgba16: (a: number, b: number) => number; 47 | readonly __wbindgen_free: (a: number, b: number, c: number) => void; 48 | readonly __wbindgen_add_to_stack_pointer: (a: number) => number; 49 | readonly __wbindgen_malloc: (a: number, b: number) => number; 50 | } 51 | 52 | export type SyncInitInput = BufferSource | WebAssembly.Module; 53 | /** 54 | * Instantiates the given `module`, which can either be bytes or 55 | * a precompiled `WebAssembly.Module`. 56 | * 57 | * @param {SyncInitInput} module 58 | * 59 | * @returns {InitOutput} 60 | */ 61 | export function initSync(module: SyncInitInput): InitOutput; 62 | 63 | /** 64 | * If `module_or_path` is {RequestInfo} or {URL}, makes a request and 65 | * for everything else, calls `WebAssembly.instantiate` directly. 66 | * 67 | * @param {InitInput | Promise} module_or_path 68 | * 69 | * @returns {Promise} 70 | */ 71 | export default function __wbg_init (module_or_path?: InitInput | Promise): Promise; 72 | -------------------------------------------------------------------------------- /packages/jpeg/decode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have copied this code from the JPEG encode module 16 | * and modified it to decode JPEG images. 17 | */ 18 | 19 | import type { MozJPEGModule } from './codec/dec/mozjpeg_dec.js'; 20 | import { initEmscriptenModule } from './utils.js'; 21 | 22 | import mozjpeg_dec from './codec/dec/mozjpeg_dec.js'; 23 | import { DecodeOptions, defaultDecodeOptions } from './meta.js'; 24 | 25 | let emscriptenModule: Promise; 26 | 27 | export async function init( 28 | moduleOptionOverrides?: Partial, 29 | ): Promise; 30 | export async function init( 31 | module?: WebAssembly.Module, 32 | moduleOptionOverrides?: Partial, 33 | ): Promise { 34 | let actualModule: WebAssembly.Module | undefined = module; 35 | let actualOptions: Partial | undefined = 36 | moduleOptionOverrides; 37 | 38 | // If only one argument is provided and it's not a WebAssembly.Module 39 | if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { 40 | actualModule = undefined; 41 | actualOptions = module as unknown as Partial; 42 | } 43 | 44 | emscriptenModule = initEmscriptenModule( 45 | mozjpeg_dec, 46 | actualModule, 47 | actualOptions, 48 | ); 49 | } 50 | 51 | export default async function decode( 52 | buffer: ArrayBuffer, 53 | options: Partial = {}, 54 | ): Promise { 55 | if (!emscriptenModule) init(); 56 | 57 | const _options = { ...defaultDecodeOptions, ...options }; 58 | const module = await emscriptenModule; 59 | const result = module.decode(buffer, _options.preserveOrientation); 60 | if (!result) throw new Error('Decoding error'); 61 | return result; 62 | } 63 | -------------------------------------------------------------------------------- /packages/avif/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## @jsquash/avif@2.1.1 4 | 5 | ### Fixes 6 | 7 | - Fixes the type definitions for the `encode` method to work correctly with the intended bitDepths. 8 | 9 | ## @jsquash/avif@2.1.0 10 | 11 | ### Adds 12 | 13 | - Adds support for encoding and decoding AVIF images with higher bit depths 14 | - 10-bit and 12-bit images are supported for encoding. Pixel data must be provided as 16-bit integers. 15 | - 10-bit, 12-bit and 16-bit images are supported for decoding 16 | - See [README](./README.md) for bit depth configuration options 17 | 18 | - Adds easy support for lossless encoding with the `lossless` option 19 | - When `lossless` is set to `true`, the `quality` and `qualityAlpha` options are ignored 20 | - The `subsample` option is ignored when `lossless` is set to `true` 21 | 22 | - Adds support for only providing a module option override to the `init` function directly 23 | 24 | **Example:** 25 | ```ts 26 | import encode, { init } from '@jsquash/avif/encode'; 27 | await init({ 28 | locateFile: (path) => { 29 | const remoteLocation = 'https://cdn.mydomain.com/wasm'; 30 | return remoteLocation + path; 31 | } 32 | }); 33 | const buffer = await encode(/* image data */); 34 | ``` 35 | 36 | ### Fixes 37 | 38 | - Updates `locateFile` emscripten module option type to support prefix parameter. 39 | 40 | ## @jsquash/avif@2.0.0 41 | 42 | ### Breaking Changes 43 | 44 | - Upgrades libavif to v1.0.1 45 | 46 | ## @jsquash/avif@1.3.0 47 | 48 | ### Adds 49 | 50 | - Adds ability to customise Emscripten module options, e.g. define your own `locateFile` method. 51 | 52 | ## @jsquash/avif@1.2.0 53 | 54 | ### Adds 55 | 56 | - Adds Node.js ESM support 57 | - Updates relative imports to use file extensions 58 | - Adds `module` field to relevant `package.json` 59 | - Updates pre.js to polyfill ImageData for Node.js 60 | 61 | ### Misc. 62 | 63 | - Removes *.d.ts.map files from the package 64 | 65 | ## @jsquash/avif@1.1.2 66 | 67 | ### Bug Fixes 68 | 69 | - Stops the WebWorker module code from being instantiated when running in a Cloudflare Worker environment 70 | 71 | ## @jsquash/avif@1.1.1 72 | 73 | ### Bug Fixes 74 | 75 | - Fixes an issue where it may not have been possible instantiate encode wasm modules manually 76 | 77 | ## @jsquash/avif@1.1.0 78 | 79 | ### Added 80 | 81 | - Include polyfills for Cloudflare Worker environment for easier compatibility 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # MacOS 107 | .DS_Store 108 | 109 | # C/C++ Files 110 | *.o 111 | 112 | # lockfile 113 | package-lock.json 114 | 115 | # examples 116 | example.webp 117 | example.png 118 | 119 | # Ignore Rust build files 120 | target 121 | 122 | # Ignore tsimp 123 | .tsimp/ 124 | 125 | # Ignore deno tests for now 126 | test/deno -------------------------------------------------------------------------------- /packages/resize/lib/resize/src/lut.inc: -------------------------------------------------------------------------------- 1 | static SRGB_TO_LINEAR_LUT: [f32; 256] = [0.0000000,0.0003035,0.0006071,0.0009106,0.0012141,0.0015176,0.0018212,0.0021247,0.0024282,0.0027317,0.0030353,0.0033465,0.0036765,0.0040247,0.0043914,0.0047770,0.0051815,0.0056054,0.0060488,0.0065121,0.0069954,0.0074990,0.0080232,0.0085681,0.0091341,0.0097212,0.0103298,0.0109601,0.0116122,0.0122865,0.0129830,0.0137021,0.0144438,0.0152085,0.0159963,0.0168074,0.0176420,0.0185002,0.0193824,0.0202886,0.0212190,0.0221739,0.0231534,0.0241576,0.0251869,0.0262412,0.0273209,0.0284260,0.0295568,0.0307134,0.0318960,0.0331048,0.0343398,0.0356013,0.0368894,0.0382044,0.0395462,0.0409152,0.0423114,0.0437350,0.0451862,0.0466651,0.0481718,0.0497066,0.0512695,0.0528607,0.0544803,0.0561285,0.0578054,0.0595112,0.0612461,0.0630100,0.0648033,0.0666260,0.0684782,0.0703601,0.0722719,0.0742136,0.0761854,0.0781874,0.0802198,0.0822827,0.0843762,0.0865005,0.0886556,0.0908417,0.0930590,0.0953075,0.0975874,0.0998987,0.1022417,0.1046165,0.1070231,0.1094617,0.1119324,0.1144354,0.1169707,0.1195384,0.1221388,0.1247718,0.1274377,0.1301365,0.1328683,0.1356333,0.1384316,0.1412633,0.1441285,0.1470273,0.1499598,0.1529262,0.1559265,0.1589609,0.1620294,0.1651322,0.1682694,0.1714411,0.1746474,0.1778884,0.1811642,0.1844750,0.1878208,0.1912017,0.1946178,0.1980693,0.2015562,0.2050787,0.2086369,0.2122307,0.2158605,0.2195262,0.2232280,0.2269659,0.2307401,0.2345507,0.2383977,0.2422812,0.2462014,0.2501584,0.2541522,0.2581829,0.2622507,0.2663557,0.2704979,0.2746774,0.2788943,0.2831488,0.2874409,0.2917707,0.2961383,0.3005438,0.3049874,0.3094690,0.3139887,0.3185468,0.3231432,0.3277781,0.3324516,0.3371637,0.3419144,0.3467041,0.3515327,0.3564003,0.3613069,0.3662527,0.3712378,0.3762622,0.3813261,0.3864295,0.3915726,0.3967553,0.4019779,0.4072403,0.4125427,0.4178852,0.4232678,0.4286906,0.4341537,0.4396572,0.4452012,0.4507858,0.4564111,0.4620771,0.4677838,0.4735315,0.4793202,0.4851500,0.4910209,0.4969330,0.5028866,0.5088814,0.5149178,0.5209957,0.5271152,0.5332765,0.5394796,0.5457246,0.5520115,0.5583405,0.5647116,0.5711249,0.5775805,0.5840785,0.5906189,0.5972019,0.6038274,0.6104956,0.6172066,0.6239604,0.6307572,0.6375970,0.6444798,0.6514057,0.6583748,0.6653873,0.6724432,0.6795425,0.6866854,0.6938719,0.7011020,0.7083759,0.7156937,0.7230552,0.7304609,0.7379106,0.7454044,0.7529423,0.7605246,0.7681513,0.7758223,0.7835379,0.7912980,0.7991028,0.8069524,0.8148467,0.8227859,0.8307700,0.8387991,0.8468733,0.8549927,0.8631573,0.8713672,0.8796223,0.8879232,0.8962694,0.9046614,0.9130987,0.9215820,0.9301109,0.9386859,0.9473066,0.9559735,0.9646863,0.9734455,0.9822506,0.9911022,1.0000000]; -------------------------------------------------------------------------------- /packages/jpeg/encode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have modified this file. 16 | * Updated to support a partial subset of Jpeg encoding options to be provided. 17 | * The jpeg options are defaulted to defaults from the meta.ts file. 18 | */ 19 | import type { EncodeOptions } from './meta.js'; 20 | import type { MozJPEGModule } from './codec/enc/mozjpeg_enc.js'; 21 | 22 | import mozjpeg_enc from './codec/enc/mozjpeg_enc.js'; 23 | import { defaultOptions } from './meta.js'; 24 | import { initEmscriptenModule } from './utils.js'; 25 | 26 | let emscriptenModule: Promise; 27 | 28 | export async function init( 29 | moduleOptionOverrides?: Partial, 30 | ): Promise; 31 | export async function init( 32 | module?: WebAssembly.Module, 33 | moduleOptionOverrides?: Partial, 34 | ): Promise { 35 | let actualModule: WebAssembly.Module | undefined = module; 36 | let actualOptions: Partial | undefined = 37 | moduleOptionOverrides; 38 | 39 | // If only one argument is provided and it's not a WebAssembly.Module 40 | if (arguments.length === 1 && !(module instanceof WebAssembly.Module)) { 41 | actualModule = undefined; 42 | actualOptions = module as unknown as Partial; 43 | } 44 | 45 | emscriptenModule = initEmscriptenModule( 46 | mozjpeg_enc, 47 | actualModule, 48 | actualOptions, 49 | ); 50 | } 51 | 52 | export default async function encode( 53 | data: ImageData, 54 | options: Partial = {}, 55 | ): Promise { 56 | if (!emscriptenModule) init(); 57 | 58 | const module = await emscriptenModule; 59 | const _options = { ...defaultOptions, ...options }; 60 | const resultView = module.encode( 61 | data.data, 62 | data.width, 63 | data.height, 64 | _options, 65 | ); 66 | // wasm can't run on SharedArrayBuffers, so we hard-cast to ArrayBuffer. 67 | return resultView.buffer as ArrayBuffer; 68 | } 69 | -------------------------------------------------------------------------------- /packages/png/encode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** 15 | * Notice: I (Jamie Sinclair) have copied this code from the JPEG encode module 16 | * and modified it to encode PNG images and also optimise them. 17 | */ 18 | 19 | import type { 20 | InitInput, 21 | InitOutput as PngModule, 22 | } from './codec/pkg/squoosh_png.js'; 23 | import initPngModule, { encode as pngEncode } from './codec/pkg/squoosh_png.js'; 24 | 25 | type ImageDataRGBA16 = { 26 | data: Uint16Array; 27 | width: number; 28 | height: number; 29 | }; 30 | 31 | let pngModule: Promise; 32 | 33 | export async function init(moduleOrPath?: InitInput): Promise { 34 | if (!pngModule) { 35 | pngModule = initPngModule(moduleOrPath); 36 | } 37 | 38 | return pngModule; 39 | } 40 | 41 | export default async function encode( 42 | data: ImageDataRGBA16, 43 | options: { bitDepth: 16 }, 44 | ): Promise; 45 | export default async function encode( 46 | data: ImageData, 47 | options?: { bitDepth?: 8 }, 48 | ): Promise; 49 | export default async function encode( 50 | data: ImageData | ImageDataRGBA16, 51 | options: { bitDepth?: 8 | 16 } = {}, 52 | ): Promise { 53 | await init(); 54 | 55 | const bitDepth = options?.bitDepth ?? 8; 56 | 57 | if (bitDepth !== 8 && bitDepth !== 16) { 58 | throw new Error('Invalid bit depth. Must be either 8 or 16.'); 59 | } 60 | 61 | const isUint16Array = data.data instanceof Uint16Array; 62 | if (isUint16Array && bitDepth !== 16) { 63 | throw new Error( 64 | 'Invalid bit depth, must be 16 for Uint16Array or manually convert to RGB8 values with Uint8Array.', 65 | ); 66 | } 67 | if (!isUint16Array && bitDepth === 16) { 68 | throw new Error( 69 | 'Invalid bit depth, must be 8 for Uint8Array or manually convert to RGB16 values with Uint16Array.', 70 | ); 71 | } 72 | 73 | const encodeData = new Uint8Array(data.data.buffer); 74 | const output = await pngEncode(encodeData, data.width, data.height, bitDepth); 75 | if (!output) throw new Error('Encoding error.'); 76 | 77 | return output.buffer; 78 | } 79 | -------------------------------------------------------------------------------- /packages/avif/codec/helper.Makefile: -------------------------------------------------------------------------------- 1 | # This is a helper Makefile for building LibAVIF + LibAOM with given params. 2 | # 3 | # Params that must be supplied by the caller: 4 | # $(CODEC_DIR) 5 | # $(LIBAOM_DIR) 6 | # $(BUILD_DIR) 7 | # $(OUT_JS) 8 | # $(OUT_CPP) 9 | # $(LIBAOM_FLAGS) 10 | # $(LIBAVIF_FLAGS) 11 | # $(ENVIRONMENT) 12 | 13 | # $(OUT_JS) is something like "enc/avif_enc.js" or "enc/avif_enc_mt.js" 14 | # so $(OUT_BUILD_DIR) will be "node_modules/build/enc/avif_enc[_mt]" 15 | OUT_BUILD_DIR := $(BUILD_DIR)/$(basename $(OUT_JS)) 16 | 17 | # We're making libavif and libaom for every node_modules/[enc|dec]/ 18 | CODEC_BUILD_DIR := $(OUT_BUILD_DIR)/libavif 19 | CODEC_OUT := $(CODEC_BUILD_DIR)/libavif.a 20 | 21 | LIBAOM_BUILD_DIR := $(OUT_BUILD_DIR)/libaom 22 | LIBAOM_OUT := $(LIBAOM_BUILD_DIR)/libaom.a 23 | 24 | OUT_WASM = $(OUT_JS:.js=.wasm) 25 | OUT_WORKER=$(OUT_JS:.js=.worker.js) 26 | 27 | PRE_JS = pre.js 28 | 29 | .PHONY: all clean 30 | 31 | all: $(OUT_JS) 32 | 33 | # Only add libsharpyuv as a dependency for encoders. 34 | # Yes, that if statement is true for encoders. 35 | ifneq (,$(findstring enc/, $(OUT_JS))) 36 | $(OUT_JS): $(LIBSHARPYUV) 37 | $(CODEC_OUT): $(LIBSHARPYUV) 38 | endif 39 | 40 | $(OUT_JS): $(OUT_CPP) $(LIBAOM_OUT) $(CODEC_OUT) 41 | $(CXX) \ 42 | -I $(CODEC_DIR)/include \ 43 | $(CXXFLAGS) \ 44 | $(LDFLAGS) \ 45 | $(OUT_FLAGS) \ 46 | --pre-js $(PRE_JS) \ 47 | --bind \ 48 | -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ 49 | -s ENVIRONMENT=$(ENVIRONMENT) \ 50 | -s EXPORT_ES6=1 \ 51 | -s DYNAMIC_EXECUTION=0 \ 52 | -s MODULARIZE=1 \ 53 | -s STACK_SIZE=$(STACK_SIZE) \ 54 | -s INITIAL_MEMORY=$(INITIAL_MEMORY_SIZE) \ 55 | -o $@ \ 56 | $+ 57 | 58 | $(CODEC_OUT): $(CODEC_DIR)/CMakeLists.txt $(LIBAOM_OUT) 59 | emcmake cmake \ 60 | -DCMAKE_LIBRARY_PATH=$(LIBSHARPYUV_BUILD_DIR) \ 61 | -DCMAKE_BUILD_TYPE=Release \ 62 | -DBUILD_SHARED_LIBS=0 \ 63 | -DAVIF_CODEC_AOM=1 \ 64 | -DAOM_LIBRARY=$(LIBAOM_OUT) \ 65 | -DAOM_INCLUDE_DIR=$(LIBAOM_DIR) \ 66 | $(LIBAVIF_FLAGS) \ 67 | -B $(CODEC_BUILD_DIR) \ 68 | $(CODEC_DIR) && \ 69 | $(MAKE) -C $(CODEC_BUILD_DIR) 70 | 71 | $(LIBAOM_OUT): $(LIBAOM_DIR)/CMakeLists.txt 72 | emcmake cmake \ 73 | -DCMAKE_BUILD_TYPE=Release \ 74 | -DENABLE_CCACHE=0 \ 75 | -DAOM_TARGET_CPU=generic \ 76 | -DENABLE_DOCS=0 \ 77 | -DENABLE_TESTS=0 \ 78 | -DENABLE_EXAMPLES=0 \ 79 | -DENABLE_TOOLS=0 \ 80 | -DCONFIG_ACCOUNTING=1 \ 81 | -DCONFIG_INSPECTION=0 \ 82 | -DCONFIG_RUNTIME_CPU_DETECT=0 \ 83 | -DCONFIG_WEBM_IO=0 \ 84 | $(LIBAOM_FLAGS) \ 85 | -B $(LIBAOM_BUILD_DIR) \ 86 | $(LIBAOM_DIR) && \ 87 | $(MAKE) -C $(LIBAOM_BUILD_DIR) 88 | 89 | clean: 90 | $(RM) $(OUT_JS) $(OUT_WASM) $(OUT_WORKER) 91 | $(MAKE) -C $(CODEC_BUILD_DIR) clean 92 | $(MAKE) -C $(LIBAOM_BUILD_DIR) clean -------------------------------------------------------------------------------- /examples/with-rollup/main.js: -------------------------------------------------------------------------------- 1 | import * as avif from '@jsquash/avif'; 2 | import * as jpeg from '@jsquash/jpeg'; 3 | import * as jxl from '@jsquash/jxl'; 4 | import * as png from '@jsquash/png'; 5 | import * as webp from '@jsquash/webp'; 6 | 7 | async function decode (sourceType, fileBuffer) { 8 | switch (sourceType) { 9 | case 'avif': 10 | return await avif.decode(fileBuffer); 11 | case 'jpeg': 12 | return await jpeg.decode(fileBuffer); 13 | case 'jxl': 14 | return await jxl.decode(fileBuffer); 15 | case 'png': 16 | return await png.decode(fileBuffer); 17 | case 'webp': 18 | return await webp.decode(fileBuffer); 19 | default: 20 | throw new Error(`Unknown source type: ${sourceType}`); 21 | } 22 | } 23 | 24 | async function encode (outputType, imageData) { 25 | switch (outputType) { 26 | case 'avif': 27 | return await avif.encode(imageData); 28 | case 'jpeg': 29 | return await jpeg.encode(imageData); 30 | case 'jxl': 31 | return await jxl.encode(imageData); 32 | case 'png': 33 | return await png.encode(imageData); 34 | case 'webp': 35 | return await webp.encode(imageData); 36 | default: 37 | throw new Error(`Unknown output type: ${outputType}`); 38 | } 39 | } 40 | 41 | async function convert (sourceType, outputType, fileBuffer) { 42 | const imageData = await decode(sourceType, fileBuffer); 43 | return encode(outputType, imageData); 44 | } 45 | 46 | function blobToBase64(blob) { 47 | return new Promise((resolve, _) => { 48 | const reader = new FileReader(); 49 | reader.onloadend = () => resolve(reader.result); 50 | reader.readAsDataURL(blob); 51 | }); 52 | } 53 | 54 | async function showOutput (imageBuffer, outputType) { 55 | const preview = document.querySelector('#preview'); 56 | const imageBlob = new Blob([imageBuffer], { type: `image/${outputType}` }); 57 | const base64String = await blobToBase64(imageBlob); 58 | const previewImg = document.createElement('img'); 59 | previewImg.src = base64String; 60 | preview.innerHTML = ''; 61 | preview.appendChild(previewImg); 62 | } 63 | 64 | async function initForm () { 65 | const form = document.querySelector('form'); 66 | 67 | form.addEventListener('submit', async (event) => { 68 | event.preventDefault(); 69 | const formData = new FormData(form); 70 | const file = formData.get('file'); 71 | const sourceType = file.name.endsWith('jxl') ? 'jxl' : file.type.replace('image/', ''); 72 | const outputType = formData.get('outputType'); 73 | const fileBuffer = await file.arrayBuffer(); 74 | const imageBuffer = await convert(sourceType, outputType, fileBuffer); 75 | showOutput(imageBuffer, outputType); 76 | }); 77 | } 78 | 79 | async function main () { 80 | initForm(); 81 | } 82 | 83 | main(); 84 | --------------------------------------------------------------------------------