docs: update examples and site (#85)

This commit is contained in:
LongYinan 2024-02-19 22:45:21 +08:00 committed by GitHub
parent bba3bd3ae5
commit 503adf4cd8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 241 additions and 218 deletions

View File

@ -66,8 +66,8 @@ jobs:
set -e &&
apt-get update &&
apt-get install meson -y &&
rm /usr/lib/llvm-16/lib/libc++.so &&
export LDFLAGS="-L/usr/lib/llvm-16/lib -L/usr/x86_64-unknown-linux-gnu/lib/gcc/x86_64-unknown-linux-gnu/4.8.5" &&
rm /usr/lib/llvm-18/lib/libc++.so &&
export LDFLAGS="-L/usr/lib/llvm-18/lib -L/usr/x86_64-unknown-linux-gnu/lib/gcc/x86_64-unknown-linux-gnu/4.8.5" &&
export CFLAGS="-fuse-ld=lld -B/usr/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/4.8.5 --sysroot=/usr/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/sysroot" &&
export CXXFLAGS="-stdlib=libc++ -fuse-ld=lld -B/usr/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/4.8.5 --sysroot=/usr/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/sysroot -L/usr/lib/llvm-15/lib" &&
yarn workspace @napi-rs/image build --features with_simd --target x86_64-unknown-linux-gnu &&
@ -97,11 +97,11 @@ jobs:
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
build: >-
set -e &&
rm /usr/aarch64-unknown-linux-gnu/lib/llvm-16/lib/libunwind.so &&
rm /usr/aarch64-unknown-linux-gnu/lib/llvm-16/lib/libc++.so &&
rm /usr/aarch64-unknown-linux-gnu/lib/llvm-18/lib/libunwind.so &&
rm /usr/aarch64-unknown-linux-gnu/lib/llvm-18/lib/libc++.so &&
export LDFLAGS="-L/usr/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/4.8.5" &&
export CFLAGS="-fuse-ld=lld -mcrc -B/usr/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/4.8.5 --sysroot=/usr/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot" &&
export CXXFLAGS="-fuse-ld=lld -mcrc -B/usr/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/4.8.5 --sysroot=/usr/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot -L/usr/aarch64-unknown-linux-gnu/lib/llvm-16/lib -stdlib=libc++" &&
export CXXFLAGS="-fuse-ld=lld -mcrc -B/usr/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/4.8.5 --sysroot=/usr/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot -L/usr/aarch64-unknown-linux-gnu/lib/llvm-18/lib -stdlib=libc++" &&
yarn workspace @napi-rs/image build --features with_simd --target aarch64-unknown-linux-gnu &&
chmod -R 777 target
- host: ubuntu-latest

View File

@ -89,16 +89,16 @@ You can clone this repo and run the following command to taste the example below
- `yarn install`
- `node example.mjs`
| Optimization | Raw | Raw Size | Optimized Size |
| ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------- |
| `losslessCompressPng()` <br/>**Lossless** | <img src="./un-optimized.png" width="400" />[CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by [Niabot](https://commons.wikimedia.org/wiki/User:Niabot) | `888K` | `736K` |
| `pngQuantize({ maxQuality: 75 })` <br/>**Lossy** | <img src="./un-optimized.png" width="400" />[CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by [Niabot](https://commons.wikimedia.org/wiki/User:Niabot) | `888K` | `248K` |
| `compressJpeg()` <br/>**Lossless** | <img src="./un-optimized.jpg" width="400" /> | `192K` | `184K` |
| `compressJpeg(75)` <br/>**Lossy** | <img src="./un-optimized.jpg" width="400" /> | `192K` | `104K` |
| `new Transformer(PNG).webpLossless()`<br/>**Lossless** | <img src="./un-optimized.png" width="400" />[CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by [Niabot](https://commons.wikimedia.org/wiki/User:Niabot) | `888K` | `588K` |
| `new Transformer(PNG).webp(75)`<br/>**Lossy** | <img src="./un-optimized.png" width="400" />[CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by [Niabot](https://commons.wikimedia.org/wiki/User:Niabot) | `888K` | `64K` |
| `Transformer(PNG).avif({ quality: 100 })`<br/>**Lossless** | <img src="./un-optimized.png" width="400" />[CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by [Niabot](https://commons.wikimedia.org/wiki/User:Niabot) | `888K` | `536K` |
| `new Transformer(PNG).avif({ quality: 75, chromaSubsampling: ChromaSubsampling.Yuv420 })`<br/>**Lossy** | <img src="./un-optimized.png" width="400" />[CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by [Niabot](https://commons.wikimedia.org/wiki/User:Niabot) | `888K` | `64K` |
| Optimization | Raw | Raw Size | Optimized Size |
| ------------------------------------------------------------------------------------------------------- | -------------------------------------------- | -------- | -------------- |
| `losslessCompressPng()` <br/>**Lossless** | <img src="./un-optimized.png" width="400" /> | `1.2M` | `876K` |
| `pngQuantize({ maxQuality: 75 })` <br/>**Lossy** | <img src="./un-optimized.png" width="400" /> | `1.2M` | `228K` |
| `compressJpeg()` <br/>**Lossless** | <img src="./un-optimized.jpg" width="400" /> | `192K` | `184K` |
| `compressJpeg(75)` <br/>**Lossy** | <img src="./un-optimized.jpg" width="400" /> | `192K` | `104K` |
| `new Transformer(PNG).webpLossless()`<br/>**Lossless** | <img src="./un-optimized.png" width="400" /> | `1.2M` | `676K` |
| `new Transformer(PNG).webp(75)`<br/>**Lossy** | <img src="./un-optimized.png" width="400" /> | `1.2M` | `84K` |
| `Transformer(PNG).avif({ quality: 100 })`<br/>**Lossless** | <img src="./un-optimized.png" width="400" /> | `1.2M` | `584K` |
| `new Transformer(PNG).avif({ quality: 75, chromaSubsampling: ChromaSubsampling.Yuv420 })`<br/>**Lossy** | <img src="./un-optimized.png" width="400" /> | `1.2M` | `112K` |
```js
import { readFileSync, writeFileSync } from 'fs'

View File

@ -12,7 +12,7 @@
"website"
],
"devDependencies": {
"@napi-rs/cli": "^3.0.0-alpha.38",
"@napi-rs/cli": "^3.0.0-alpha.40",
"@taplo/cli": "^0.7.0",
"@types/node": "^20.11.16",
"@types/sharp": "^0.31.1",

View File

@ -35,6 +35,9 @@ image = { version = "0.24", default-features = false, features = [
"openexr",
] }
jpeg-decoder = "0.3"
libavif = { version = "0.13", default-features = false, features = [
"codec-aom",
] }
libc = "0.2"
lodepng = "3"
napi = { version = "2", default-features = false, features = ["napi3"] }
@ -64,15 +67,5 @@ libwebp-sys = { version = "0.9", default-features = false, features = ["std", "p
[target.'cfg(all(target_os = "macos", target_arch = "x86_64"))'.dependencies]
libwebp-sys = { version = "0.9", default-features = false, features = ["std", "parallel"] }
[target.'cfg(target_family = "wasm")'.dependencies]
libavif = { git="https://github.com/njaard/libavif-rs.git", rev = "678bd68", version = "0.12", default-features = false, features = [
"codec-rav1e",
] }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
libavif = { git="https://github.com/njaard/libavif-rs.git", rev = "678bd68", version = "0.12", default-features = false, features = [
"codec-aom",
] }
[build-dependencies]
napi-build = "2"

View File

@ -8,7 +8,7 @@ import { losslessCompressPng, pngQuantize, compressJpeg, Transformer } from '../
const ROOT_DIR = join(fileURLToPath(import.meta.url), '..', '..', '..', '..')
const PNG = await fs.readFile(join(ROOT_DIR, 'nasa-4928x3279.png'))
const PNG = await fs.readFile(join(ROOT_DIR, 'un-optimized.png'))
const JPEG = await fs.readFile(join(ROOT_DIR, 'un-optimized.jpg'))
test('should be able to lossless optimize png image', async (t) => {
@ -21,7 +21,11 @@ test('should be able to lossless optimize png image', async (t) => {
})
test('should be able to lossy optimize png image', async (t) => {
const dest = await pngQuantize(PNG, { speed: 10 })
if (process.env.NAPI_RS_FORCE_WASI) {
t.pass()
return
}
const dest = await pngQuantize(PNG, { speed: 5, maxQuality: 1, minQuality: 1 })
t.true(dest.length < PNG.length)
})
@ -49,9 +53,15 @@ test('should be able to lossless encode webp from jpeg', (t) => {
})
test('should be able to encode avif from png', (t) => {
t.true(new Transformer(PNG).avifSync().length < PNG.length)
t.true(new Transformer(PNG).avifSync({
speed: 10,
threads: 4,
}).length < PNG.length)
})
test('should be able to encode avif from jpeg', (t) => {
t.true(new Transformer(JPEG).avifSync().length < JPEG.length)
t.true(new Transformer(JPEG).avifSync({
speed: 10,
threads: 4,
}).length < JPEG.length)
})

View File

@ -18,8 +18,8 @@ const SVG = await fs.readFile(join(ROOT_DIR, 'input-debian.svg'))
test('should be able to get metadata from png', async (t) => {
const decoder = new Transformer(PNG)
const metadata = await decoder.metadata()
t.is(metadata.width, 1052)
t.is(metadata.height, 744)
t.is(metadata.width, 1024)
t.is(metadata.height, 681)
})
test('should be able to get metadata from jpg', async (t) => {

View File

@ -1,5 +1,3 @@
extern crate napi_build;
fn main() {
napi_build::setup();
}

View File

@ -64,7 +64,7 @@
},
"repository": "git@github.com:Brooooooklyn/Image.git",
"devDependencies": {
"@napi-rs/cli": "^3.0.0-alpha.38",
"@napi-rs/cli": "^3.0.0-alpha.40",
"@napi-rs/wasm-runtime": "^0.1.1"
}
}

View File

@ -102,8 +102,8 @@ pub(crate) fn encode_avif_inner(
) -> Result<AvifData<'static>> {
let mut encoder = libavif::Encoder::new();
let config: Config = config.unwrap_or_default().into();
encoder.set_quality((63.0 * (1.0 - config.quality as f32 / 100.0)) as u8);
encoder.set_alpha_quality((63.0 * (1.0 - config.alpha_quality as f32 / 100.0)) as u8);
encoder.set_quality(config.quality);
encoder.set_alpha_quality(config.alpha_quality);
encoder.set_speed(config.speed);
encoder.set_max_threads(config.threads);
let (width, height) = input_image.dimensions();

View File

@ -565,6 +565,15 @@ impl Task for EncodeTask {
color_type,
)
}?;
if output_buf.is_null() {
return Err(Error::new(
Status::GenericFailure,
format!(
"Encode lossless webp failed, {}",
dynamic_image.as_bytes().len()
),
));
}
return Ok(EncodeOutput::Raw(output_buf, size));
}
EncodeOptions::Avif(ref options) => {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 886 KiB

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -25,138 +25,144 @@ const Title = '@napi-rs/image'
ctx.fillText(Title, 80, 100)
const Arrow = new Image()
Arrow.src = Buffer.from(`
<svg viewBox="0 0 1088 615" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
Arrow.src = Buffer.from(`<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1088 615" version="1.1">
<g stroke-width="1" fill="none" fill-rule="evenodd">
<text font-family="'Iosevka Slab', sans-serif" font-size="18" font-weight="600" fill="#00e676">
<tspan x="900" y="459">Optimized Images</tspan>
<text font-family="Iosevka Slab" font-size="18" font-weight="600" fill="#00e676">
<tspan x="900" y="459">Optimized Images</tspan>
</text>
<g transform="translate(1002, 326)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-1"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="Iosevka Slab" font-size="22" font-weight="400" fill="#a7f3d0">
<tspan x="18.891" y="46.7096774">.png</tspan>
</text>
<g transform="translate(1002, 326)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-1"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="18.891" y="46.7096774">.png</tspan>
</text>
</g>
<g transform="translate(1002, 214)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-2"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<g transform="translate(1002, 214)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-2"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="15" y="46.7096774">.avif</tspan>
</text>
</g>
<g transform="translate(894, 326)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-3"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="21.817" y="46.7096774">.jpg</tspan>
</text>
</g>
<g transform="translate(894, 214)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-4"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="9" y="46.7096774">.webp</tspan>
</text>
</g>
<g transform="translate(342, 225)" stroke="#73e8ff" stroke-width="4">
<path d="M499.558824,86.52 C499.558824,86.52 484.852941,81.02 439.908088,109.436667 C394.963235,137.853333 380.992647,164.436667 380.992647,164.436667" stroke-dasharray="7"></path>
<path d="M499.558824,86.0616667 C499.558824,86.0616667 484.852941,91.5616667 439.908088,63.145 C394.963235,34.7283333 380.992647,8.145 380.992647,8.145" stroke-dasharray="7"></path>
<path d="M0.477941176,170.395 C0.477941176,170.395 169.382939,98.895 447.847936,98.895" stroke-dasharray="6"></path>
<path d="M0.477941176,72.395 C0.477941176,72.395 169.382939,0.895 447.847936,0.895" stroke-dasharray="6" transform="translate(224.162939, 36.645000) scale(1, -1) translate(-224.162939, -36.645000) "></path>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="18" font-weight="600" fill="#ffcc80">
<tspan x="24.934" y="562">Raw Images</tspan>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#a7f3d0">
<tspan x="15" y="46.7096774">.avif</tspan>
</text>
<g transform="translate(228, 335)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-5"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.jpg</tspan>
</text>
</g>
<g transform="translate(894, 326)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-3"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<g transform="translate(228, 223)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-6"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.png</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#a7f3d0">
<tspan x="21.817" y="46.7096774">.jpg</tspan>
</text>
</g>
<g transform="translate(894, 214)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-4"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="84" height="84" rx="3"></rect>
</g>
<g transform="translate(116, 391)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-7"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.tiff</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#a7f3d0">
<tspan x="9" y="46.7096774">.webp</tspan>
</text>
</g>
<g transform="translate(342, 225)" stroke="#73e8ff" stroke-width="4">
<path
d="M499.558824,86.52 C499.558824,86.52 484.852941,81.02 439.908088,109.436667 C394.963235,137.853333 380.992647,164.436667 380.992647,164.436667"
stroke-dasharray="7"></path>
<path
d="M499.558824,86.0616667 C499.558824,86.0616667 484.852941,91.5616667 439.908088,63.145 C394.963235,34.7283333 380.992647,8.145 380.992647,8.145"
stroke-dasharray="7"></path>
<path d="M0.477941176,170.395 C0.477941176,170.395 169.382939,98.895 447.847936,98.895" stroke-dasharray="6">
</path>
<path d="M0.477941176,72.395 C0.477941176,72.395 169.382939,0.895 447.847936,0.895" stroke-dasharray="6"
transform="translate(224.162939, 36.645000) scale(1, -1) translate(-224.162939, -36.645000) "></path>
</g>
<text font-family="Iosevka Slab" font-size="18" font-weight="600" fill="#ffcc80">
<tspan x="24.934" y="562">Raw Images</tspan>
</text>
<g transform="translate(228, 335)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-5"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<g transform="translate(116, 279)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-8"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.ico</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.jpg</tspan>
</text>
</g>
<g transform="translate(228, 223)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-6"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<g transform="translate(116, 167)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-9"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.pnm</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.png</tspan>
</text>
</g>
<g transform="translate(116, 391)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-7"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<g transform="translate(4, 447)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-10"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.bmp</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.tiff</tspan>
</text>
</g>
<g transform="translate(116, 279)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-8"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<g transform="translate(4, 335)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-11"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.tga</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.ico</tspan>
</text>
</g>
<g transform="translate(116, 167)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-9"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<g transform="translate(4, 223)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-12"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.hdr</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.pnm</tspan>
</text>
</g>
<g transform="translate(4, 447)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-10"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<g transform="translate(4, 111)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-13"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="'Iosevka Slab', sans-serif" font-size="22" font-weight="500" fill="#FFFFFF">
<tspan x="10" y="38">.dxt</tspan>
</text>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.bmp</tspan>
</text>
</g>
<g transform="translate(4, 335)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-11"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.tga</tspan>
</text>
</g>
<g transform="translate(4, 223)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-12"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.hdr</tspan>
</text>
</g>
<g transform="translate(4, 111)">
<g>
<use fill-opacity="0.1" fill="#b3e5fc" fill-rule="evenodd" xlink:href="#path-13"></use>
<rect stroke="#b3e5fc" stroke-width="4" x="-2" y="-2" width="66" height="66" rx="3"></rect>
</g>
<text font-family="Iosevka Slab" font-size="22" font-weight="500" fill="#fde68a">
<tspan x="10" y="38">.dxt</tspan>
</text>
</g>
</g>
</svg>`)
ctx.drawImage(Arrow, 80, 60)

View File

@ -4,8 +4,8 @@
"version": "0.0.0",
"type": "module",
"dependencies": {
"@napi-rs/canvas": "^0.1.45",
"@napi-rs/image": "^1.7.0",
"@napi-rs/canvas": "^0.1.46",
"@napi-rs/image": "^1.8.0",
"chalk": "^5.3.0",
"next": "canary",
"next-mdx-remote": "^4.4.1",

View File

@ -94,22 +94,20 @@ You can clone this repo and run the following command to taste the example below
- `yarn install`
- `node example.mjs`
> The anime girl <br/><br/>
> Shot by NASA <br/><br/>
>
> <img src="img/un-optimized.png" width="300" /> <br />
> [CC-BY-SA 3.0](https://creativecommons.org/licenses/by/3.0) by
> [Niabot](https://commons.wikimedia.org/wiki/User:Niabot){' '}
| Optimization | <div style={{ width: '80px' }}>Raw</div> | <div style={{ width: '80px' }}>Optimized</div> | Raw Size | Optimized Size |
| ------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------- | -------- | -------------- |
| `losslessCompressPng()` <br/>**Lossless** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossless.png](../public/img/optimized-lossless.png) | `888K` | `736K` |
| `pngQuantize({ maxQuality: 75 })` <br/>**Lossy** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossy.png](../public/img/optimized-lossy.png) | `888K` | `248K` |
| `losslessCompressPng()` <br/>**Lossless** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossless.png](../public/img/optimized-lossless.png) | `1.2M` | `876K` |
| `pngQuantize({ maxQuality: 75 })` <br/>**Lossy** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossy.png](../public/img/optimized-lossy.png) | `1.2M` | `228K` |
| `compressJpeg()` <br/>**Lossless** | ![un-optimized.jpg](../public/img/un-optimized.jpg) | ![optimized-lossless.jpg](../public/img/optimized-lossless.jpg) | `192K` | `184K` |
| `compressJpeg(75)` <br/>**Lossy** | ![un-optimized.jpg](../public/img/un-optimized.jpg) | ![optimized-lossy.jpg](../public/img/optimized-lossy.jpg) | `192K` | `104K` |
| `new Transformer(PNG).webpLossless()`<br/>**Lossless** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossless.webp](../public/img/optimized-lossless.webp) | `888K` | `588K` |
| `new Transformer(PNG).webp(75)`<br/>**Lossy** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossy-png.webp](../public/img/optimized-lossy-png.webp) | `888K` | `64K` |
| `Transformer(PNG).avif({ quality: 100 })`<br/>**Lossless** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossless-png.avif](../public/img/optimized-lossless-png.avif) | `888K` | `536K` |
| `new Transformer(PNG).avif({ quality: 75, chromaSubsampling: ChromaSubsampling.Yuv420 })`<br/>**Lossy** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossy-png.avif](../public/img/optimized-lossy-png.avif) | `888K` | `64K` |
| `new Transformer(PNG).webpLossless()`<br/>**Lossless** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossless.webp](../public/img/optimized-lossless.webp) | `1.2M` | `676K` |
| `new Transformer(PNG).webp(75)`<br/>**Lossy** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossy-png.webp](../public/img/optimized-lossy-png.webp) | `1.2M` | `84K` |
| `Transformer(PNG).avif({ quality: 100 })`<br/>**Lossless** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossless-png.avif](../public/img/optimized-lossless-png.avif) | `1.2M` | `584K` |
| `new Transformer(PNG).avif({ quality: 75, chromaSubsampling: ChromaSubsampling.Yuv420 })`<br/>**Lossy** | ![un-optimized.png](../public/img/un-optimized.png) | ![optimized-lossy-png.avif](../public/img/optimized-lossy-png.avif) | `1.2M` | `112K` |
```js filename="example.mjs"
import { readFileSync, writeFileSync } from 'fs'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

111
yarn.lock
View File

@ -441,82 +441,82 @@ __metadata:
languageName: node
linkType: hard
"@napi-rs/canvas-android-arm64@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-android-arm64@npm:0.1.45"
"@napi-rs/canvas-android-arm64@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-android-arm64@npm:0.1.46"
conditions: os=android & cpu=arm64
languageName: node
linkType: hard
"@napi-rs/canvas-darwin-arm64@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-darwin-arm64@npm:0.1.45"
"@napi-rs/canvas-darwin-arm64@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-darwin-arm64@npm:0.1.46"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@napi-rs/canvas-darwin-x64@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-darwin-x64@npm:0.1.45"
"@napi-rs/canvas-darwin-x64@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-darwin-x64@npm:0.1.46"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@napi-rs/canvas-linux-arm-gnueabihf@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-linux-arm-gnueabihf@npm:0.1.45"
"@napi-rs/canvas-linux-arm-gnueabihf@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-linux-arm-gnueabihf@npm:0.1.46"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@napi-rs/canvas-linux-arm64-gnu@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-linux-arm64-gnu@npm:0.1.45"
"@napi-rs/canvas-linux-arm64-gnu@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-linux-arm64-gnu@npm:0.1.46"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@napi-rs/canvas-linux-arm64-musl@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-linux-arm64-musl@npm:0.1.45"
"@napi-rs/canvas-linux-arm64-musl@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-linux-arm64-musl@npm:0.1.46"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@napi-rs/canvas-linux-x64-gnu@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-linux-x64-gnu@npm:0.1.45"
"@napi-rs/canvas-linux-x64-gnu@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-linux-x64-gnu@npm:0.1.46"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@napi-rs/canvas-linux-x64-musl@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-linux-x64-musl@npm:0.1.45"
"@napi-rs/canvas-linux-x64-musl@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-linux-x64-musl@npm:0.1.46"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@napi-rs/canvas-win32-x64-msvc@npm:0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas-win32-x64-msvc@npm:0.1.45"
"@napi-rs/canvas-win32-x64-msvc@npm:0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas-win32-x64-msvc@npm:0.1.46"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@napi-rs/canvas@npm:^0.1.45":
version: 0.1.45
resolution: "@napi-rs/canvas@npm:0.1.45"
"@napi-rs/canvas@npm:^0.1.46":
version: 0.1.46
resolution: "@napi-rs/canvas@npm:0.1.46"
dependencies:
"@napi-rs/canvas-android-arm64": "npm:0.1.45"
"@napi-rs/canvas-darwin-arm64": "npm:0.1.45"
"@napi-rs/canvas-darwin-x64": "npm:0.1.45"
"@napi-rs/canvas-linux-arm-gnueabihf": "npm:0.1.45"
"@napi-rs/canvas-linux-arm64-gnu": "npm:0.1.45"
"@napi-rs/canvas-linux-arm64-musl": "npm:0.1.45"
"@napi-rs/canvas-linux-x64-gnu": "npm:0.1.45"
"@napi-rs/canvas-linux-x64-musl": "npm:0.1.45"
"@napi-rs/canvas-win32-x64-msvc": "npm:0.1.45"
"@napi-rs/canvas-android-arm64": "npm:0.1.46"
"@napi-rs/canvas-darwin-arm64": "npm:0.1.46"
"@napi-rs/canvas-darwin-x64": "npm:0.1.46"
"@napi-rs/canvas-linux-arm-gnueabihf": "npm:0.1.46"
"@napi-rs/canvas-linux-arm64-gnu": "npm:0.1.46"
"@napi-rs/canvas-linux-arm64-musl": "npm:0.1.46"
"@napi-rs/canvas-linux-x64-gnu": "npm:0.1.46"
"@napi-rs/canvas-linux-x64-musl": "npm:0.1.46"
"@napi-rs/canvas-win32-x64-msvc": "npm:0.1.46"
dependenciesMeta:
"@napi-rs/canvas-android-arm64":
optional: true
@ -536,17 +536,16 @@ __metadata:
optional: true
"@napi-rs/canvas-win32-x64-msvc":
optional: true
checksum: 10c0/a31d5db85cfdfffa469d49bae9f98688414173144f7fd36ecb02c1be03fcff98de4849b7cd4e85e12bad19bdd92755237b0c4ca8cdee7d8baaf6087e36eb64f3
checksum: 10c0/188239ee3ffc5c65dec12a4d621594f1fb6c1171fec89518a4a3776f8fd9892f13765dce214fc37e708a6e3f6d719099872873e882f752a592e8f071a4d93593
languageName: node
linkType: hard
"@napi-rs/cli@npm:^3.0.0-alpha.38":
version: 3.0.0-alpha.38
resolution: "@napi-rs/cli@npm:3.0.0-alpha.38"
"@napi-rs/cli@npm:^3.0.0-alpha.40":
version: 3.0.0-alpha.40
resolution: "@napi-rs/cli@npm:3.0.0-alpha.40"
dependencies:
"@napi-rs/cross-toolchain": "npm:^0.0.14"
"@octokit/rest": "npm:^20.0.2"
"@tybys/wasm-util": "npm:0.8.1"
clipanion: "npm:^3.2.1"
colorette: "npm:^2.0.20"
debug: "npm:^4.3.4"
@ -557,6 +556,7 @@ __metadata:
semver: "npm:^7.5.4"
toml: "npm:^3.0.0"
typanion: "npm:^3.14.0"
wasm-sjlj: "npm:^1.0.4"
peerDependencies:
"@emnapi/runtime": ^1.0.0
emnapi: ^1.0.0
@ -570,7 +570,7 @@ __metadata:
bin:
napi: dist/cli.js
napi-raw: cli.mjs
checksum: 10c0/f0f4ed480bd2d0c627bc0f1de43bc4b9c5c589c62c78df092ec53b0a4ffa6e4080bca76302e38c1f46099dd6ab9753f9ede3023fc2af3646a6f1fcd375973ed7
checksum: 10c0/0eaa113258b7429794253c7f27866944018dfe05abc85681f6db969101b75acb583189ce4523d0e1863e735648af317a646c3f3914895a0ae951879de135e135
languageName: node
linkType: hard
@ -611,11 +611,11 @@ __metadata:
languageName: unknown
linkType: soft
"@napi-rs/image@npm:^1.7.0, @napi-rs/image@workspace:packages/binding":
"@napi-rs/image@npm:^1.8.0, @napi-rs/image@workspace:packages/binding":
version: 0.0.0-use.local
resolution: "@napi-rs/image@workspace:packages/binding"
dependencies:
"@napi-rs/cli": "npm:^3.0.0-alpha.38"
"@napi-rs/cli": "npm:^3.0.0-alpha.40"
"@napi-rs/wasm-runtime": "npm:^0.1.1"
languageName: unknown
linkType: soft
@ -1866,7 +1866,7 @@ __metadata:
languageName: node
linkType: hard
"@tybys/wasm-util@npm:0.8.1, @tybys/wasm-util@npm:^0.8.1":
"@tybys/wasm-util@npm:^0.8.1":
version: 0.8.1
resolution: "@tybys/wasm-util@npm:0.8.1"
dependencies:
@ -5543,7 +5543,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "image@workspace:."
dependencies:
"@napi-rs/cli": "npm:^3.0.0-alpha.38"
"@napi-rs/cli": "npm:^3.0.0-alpha.40"
"@taplo/cli": "npm:^0.7.0"
"@types/node": "npm:^20.11.16"
"@types/sharp": "npm:^0.31.1"
@ -10986,6 +10986,15 @@ __metadata:
languageName: node
linkType: hard
"wasm-sjlj@npm:^1.0.4":
version: 1.0.4
resolution: "wasm-sjlj@npm:1.0.4"
dependencies:
node-gyp: "npm:latest"
checksum: 10c0/79b0d48c23e55e98e8cac86610003714dc5b874c76bc88501eab70c4c96f4c6d49420e036825fc7c55f42317620433f25ff7fb0ea2dc9e6db505b79450653301
languageName: node
linkType: hard
"wcwidth@npm:^1.0.0, wcwidth@npm:^1.0.1":
version: 1.0.1
resolution: "wcwidth@npm:1.0.1"
@ -11027,8 +11036,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "website@workspace:website"
dependencies:
"@napi-rs/canvas": "npm:^0.1.45"
"@napi-rs/image": "npm:^1.7.0"
"@napi-rs/canvas": "npm:^0.1.46"
"@napi-rs/image": "npm:^1.8.0"
chalk: "npm:^5.3.0"
next: "npm:canary"
next-mdx-remote: "npm:^4.4.1"