Skip to content

Commit 46108dd

Browse files
benchmark ImageScript 3.3.0
1 parent 1595177 commit 46108dd

9 files changed

Lines changed: 293 additions & 239 deletions

File tree

‎bench/README.md‎

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
How [ImageScript](https://github.com/matmen/ImageScript) compares to other image libraries for Node.js: speed, file
44
sizes and what installing each takes. ImageScript is plain JavaScript with no dependencies, so it runs wherever
5-
JavaScript does; sharp and @napi-rs/canvas wrap native libraries (libvips, Skia), Photon and ImageScript 1 are
6-
WebAssembly.
5+
JavaScript does, like Jimp, image-js and PureJsImage; sharp and @napi-rs/canvas wrap native libraries (libvips, Skia),
6+
Photon and ImageScript 1 are WebAssembly.
77

88
<img src="charts/install.svg" alt="Install size of each library">
99

@@ -19,56 +19,58 @@ WebAssembly.
1919

2020
## Numbers
2121

22-
Operations per second (more is faster), measured 2026-10-17 with Node.js v24.21.0 on AMD EPYC 7763 64-Core Processor, ImageScript 3.3.0.
23-
24-
| | **ImageScript 3** | **ImageScript 1** | **Jimp** | **image-js** | **Photon** | **sharp** | **@napi-rs/canvas** |
25-
|---|--:|--:|--:|--:|--:|--:|--:|
26-
| decode JPEG | **11.8** | 6.37 | 6.83 | 6.37 | 21.2 | 69.6 | 49.4 |
27-
| decode PNG | **32.9** | 30.7 | 15.8 | 8.33 | 41.0 | 53.6 | 54.6 |
28-
| decode WebP (lossy) | **10.4** | – | – | – | 11.2 | 36.4 | 61.5 |
29-
| encode JPEG (quality 80) | **12.5** | 19.4 | 2.50 | 9.47 | 8.87 | 56.3 | 34.8 |
30-
| encode PNG | **8.77** | 3.90 | 4.18 | 2.67 | 9.78 | 7.27 | 2.14 |
31-
| encode WebP (lossless) | **1.60** | – | – | – | 23.9 | 0.68 | 2.12 |
32-
| resize to half | **73.2** | 370 | 61.1 | 11.1 | 15.2 | 60.3 | 393 |
33-
| rotate by 30° | **27.9** | 5.57 | 1.76 | 1.15 | 4.67 | 14.3 | 38.5 |
34-
| blur (radius 5) | **13.9** | – | 0.01 | 1.25 | 6.60 | 29.8 | 60.0 |
35-
| composite an overlay | **447** | 608 | 31.9 | 116 | 169 | 113 | 447 |
36-
| crop | **825** | 754 | 50.7 | 65.5 | 204 | 1,307 | 1,437 |
37-
| clone | **1,382** | 934 | 1,033 | 885 | 419 | 1,520 | 490 |
38-
| render text | **2,103** | 59.6 | – | – | – | 2,007 | 3,495 |
39-
| render SVG | **6.83** | fails | – | – | – | 26.6 | 93.9 |
40-
| decode animated GIF | **14.8** | 7.90 | – | – | – | 17.2 | – |
41-
| encode animated GIF | **5.02** | 1.16 | – | – | – | 0.88 | – |
22+
Operations per second (more is faster), measured 2026-10-23 with Node.js v24.21.0 on AMD EPYC 7763 64-Core Processor, ImageScript 3.3.0.
23+
24+
| | **ImageScript 3** | **ImageScript 1** | **Jimp** | **image-js** | **PureJsImage** | **Photon** | **sharp** | **@napi-rs/canvas** |
25+
|---|--:|--:|--:|--:|--:|--:|--:|--:|
26+
| decode JPEG | **11.9** | 6.45 | 6.59 | 6.01 | 8.04 | 21.3 | 69.0 | 49.1 |
27+
| decode PNG | **33.1** | 30.5 | 15.8 | 8.32 | 11.8 | 40.8 | 52.5 | 53.6 |
28+
| decode WebP (lossy) | **10.0** | – | – | – | 9.85 | 11.1 | 35.9 | 60.4 |
29+
| encode JPEG (quality 80) | **12.6** | 19.3 | 2.51 | 9.42 | 7.18 | 8.86 | 55.2 | 34.7 |
30+
| encode PNG | **8.20** | 3.73 | 4.13 | 2.67 | 1.81 | 9.71 | 7.31 | 2.14 |
31+
| encode WebP (lossless) | **1.64** | – | – | – | 0.36 | 23.7 | 0.66 | 2.09 |
32+
| resize to half | **72.3** | 337 | 63.8 | 11.0 | 16.6 | 15.0 | 58.5 | 361 |
33+
| rotate by 30° | **28.1** | 5.28 | 1.77 | 1.16 | 1.99 | 4.51 | 14.0 | 37.7 |
34+
| blur (radius 5) | **14.0** | – | 0.01 | 1.24 | – | 6.56 | 29.3 | 60.2 |
35+
| composite an overlay | **414** | 614 | 31.4 | 119 | – | 165 | 110 | 397 |
36+
| crop | **817** | 666 | 48.9 | 64.3 | 98.6 | 199 | 1,191 | 1,156 |
37+
| clone | **1,153** | 907 | 1,183 | 873 | 1,308 | 381 | 1,372 | 452 |
38+
| render text | **2,030** | 57.9 | – | – | – | – | 2,250 | 2,594 |
39+
| render SVG | **6.65** | fails | – | – | – | – | 25.2 | 92.1 |
40+
| decode animated GIF | **14.8** | 7.69 | – | – | – | – | 16.5 | – |
41+
| encode animated GIF | **5.06** | 1.14 | – | – | – | – | 0.87 | – |
4242

4343
Encoded sizes:
4444

45-
| | **ImageScript 3** | **ImageScript 1** | **Jimp** | **image-js** | **Photon** | **sharp** | **@napi-rs/canvas** |
46-
|---|--:|--:|--:|--:|--:|--:|--:|
47-
| photo PNG | 2.2 MB | 3.0 MB | 2.7 MB | 2.8 MB | 2.8 MB | 2.8 MB | 2.1 MB |
48-
| photo JPEG | 217 kB | 257 kB | 260 kB | 260 kB | 257 kB | 218 kB | 218 kB |
49-
| photo WebP | 1.4 MB | – | – | – | 1.7 MB | 1.2 MB | 1.4 MB |
50-
| graphic PNG | 1.1 MB | 802 kB | 2.0 MB | 736 kB | 2.2 MB | 718 kB | 1.0 MB |
51-
| graphic JPEG | 275 kB | 314 kB | 315 kB | 315 kB | 314 kB | 275 kB | 276 kB |
52-
| graphic WebP | 580 kB | – | – | – | 856 kB | 239 kB | 631 kB |
53-
| animation GIF | 825 kB | 1.3 MB | – | – | – | 720 kB | – |
54-
55-
| | **ImageScript 3** | **ImageScript 1** | **Jimp** | **image-js** | **Photon** | **sharp** | **@napi-rs/canvas** |
56-
|---|---|---|---|---|---|---|---|
57-
| kind | JavaScript | WebAssembly | JavaScript | JavaScript | WebAssembly | native (libvips) | native (Skia) |
58-
| package | `imagescript@3.3.0` | `imagescript@1.3.1` | `jimp@1.6.1` | `image-js@1.7.1` | `@silvia-odwyer/photon-node@0.3.4` | `sharp@0.35.5` | `@napi-rs/canvas@1.0.11` |
59-
| install size | 1.1 MB | 6.7 MB | 26.8 MB | 47.8 MB | 2.3 MB | 20.3 MB | 35.0 MB |
60-
| packages | 1 | 1 | 64 | 55 | 1 | 6 | 2 |
45+
| | **ImageScript 3** | **ImageScript 1** | **Jimp** | **image-js** | **PureJsImage** | **Photon** | **sharp** | **@napi-rs/canvas** |
46+
|---|--:|--:|--:|--:|--:|--:|--:|--:|
47+
| photo PNG | 2.2 MB | 3.0 MB | 2.7 MB | 2.8 MB | 2.1 MB | 2.8 MB | 2.8 MB | 2.1 MB |
48+
| photo JPEG | 217 kB | 257 kB | 260 kB | 260 kB | 222 kB | 257 kB | 218 kB | 218 kB |
49+
| photo WebP | 1.4 MB | – | – | – | 2.1 MB | 1.7 MB | 1.2 MB | 1.4 MB |
50+
| graphic PNG | 1.1 MB | 802 kB | 2.0 MB | 736 kB | 811 kB | 2.2 MB | 718 kB | 1.0 MB |
51+
| graphic JPEG | 275 kB | 314 kB | 315 kB | 315 kB | 286 kB | 314 kB | 275 kB | 276 kB |
52+
| graphic WebP | 580 kB | – | – | – | 758 kB | 856 kB | 239 kB | 631 kB |
53+
| animation GIF | 825 kB | 1.3 MB | – | – | – | – | 720 kB | – |
54+
55+
| | **ImageScript 3** | **ImageScript 1** | **Jimp** | **image-js** | **PureJsImage** | **Photon** | **sharp** | **@napi-rs/canvas** |
56+
|---|---|---|---|---|---|---|---|---|
57+
| kind | JavaScript | WebAssembly | JavaScript | JavaScript | JavaScript | WebAssembly | native (libvips) | native (Skia) |
58+
| package | `imagescript@3.3.0` | `imagescript@1.3.1` | `jimp@1.6.1` | `image-js@1.7.1` | `purejsimage@0.17.0` | `@silvia-odwyer/photon-node@0.3.4` | `sharp@0.35.5` | `@napi-rs/canvas@1.0.11` |
59+
| install size | 1.1 MB | 6.7 MB | 26.8 MB | 47.8 MB | 6.7 MB | 2.3 MB | 20.3 MB | 35.0 MB |
60+
| packages | 1 | 1 | 64 | 55 | 1 | 1 | 6 | 2 |
6161

6262
## Method
6363

6464
- Inputs (in `inputs/`, sources in [inputs/SOURCES.md](inputs/SOURCES.md)): a 1920×1080 photo (JPEG, and made from it
6565
when the benchmark starts, PNG and lossy WebP), a 1434×1434 graphic with transparency (PNG), a 445×445 diagram with
6666
transparency placed on the photo (PNG), a 300×300 GIF with 101 frames.
6767
- Rendering: "The quick brown fox jumps over the lazy dog, 0123456789" in Source Sans 3 at 64px, and `tests/svgs/features.svg` (gradients, clipping,
68-
CSS) at 1920 pixels wide. Jimp and Photon can't render TrueType/OpenType fonts or SVGs; ImageScript 1 crashes
68+
CSS) at 1920 pixels wide. Jimp, image-js, PureJsImage and Photon can't render TrueType/OpenType fonts or SVGs; ImageScript 1 crashes
6969
on this SVG; @napi-rs/canvas (Skia's SVG module) ignores its CSS, so it draws a little less.
7070
- Every operation starts from the same decoded image and returns a new one: libraries that change images in place
71-
clone first, sharp runs a pipeline from raw pixels back to raw pixels, @napi-rs/canvas draws into a new canvas.
71+
clone first, sharp runs a pipeline from raw pixels back to raw pixels, PureJsImage (which has no decoded images) one
72+
from a BMP back to a BMP, @napi-rs/canvas draws into a new canvas. PureJsImage has no blur, composite, rendering or
73+
animated GIFs.
7274
- Where the library lets you choose, resizing is bilinear (ImageScript 1 only has nearest neighbor), blurring is
7375
gaussian with a radius or sigma of 5, rotating grows the image to fit. Each library uses its own defaults
7476
otherwise, e.g. its PNG compression level.

‎bench/charts/animation.svg‎

Lines changed: 3 additions & 3 deletions
Loading

0 commit comments

Comments
 (0)