Repository navigation
v3.2.0: smaller animations, options objects, faster codecs
This release makes animations a lot smaller, makes options easier to pass and speeds up the most common codecs. There are no breaking changes.
New
Smaller animations (#59)
encodeGIF(), encodeAPNG() and encodeWebP() now store each frame as only the area that changed since the frame before, and merge identical frames. Within that area, unchanged pixels become transparent where that compresses better.
Re-encoding 762 animations took this share of the previous size in total:
| GIF | APNG | WebP |
|---|---|---|
| 51% | 63% | 54% |
- The less moves in an animation, the smaller it gets. Animations where everything moves stay about the same size.
- Large animations encode faster, small ones up to about twice as slow.
- The files show the same animation in browsers, Pillow and libwebp. They don't decode to the same frames anymore, though.
{optimize: false}stores the frames as they are.
Options objects (#58)
Every method with optional arguments now also takes them as an object, so you can leave options out without counting positions:
image.resize(100, 100, {mode: Image.RESIZE_BICUBIC});
image.composite(logo, {x: 10, y: 10, opacity: 0.5});
Image.renderText(font, 32, 'Hi', {color: 0xff0000ff, strokeWidth: 2});
animation.encodeGIF({quality: 80});The positional arguments keep working until 4.0.
Metadata in every format (#56)
encodeJPEG(), encodeWebP(), encodeTGA() and the animation encoders take the same metadata as encode(), as the metadata option:
image.encodeJPEG({quality: 80, metadata: {author: 'me'}});Each format stores the fields it has a place for: Exif and a comment for JPEG, Exif for WebP, comments for GIF, the extension area for TGA, text chunks for PNG and APNG.
All files now name ImageScript as the software and include the creation time, as PNGs already did. {software: ''} leaves the software out.
trim() (#67)
Removes borders of one color, for example the empty space around rendered text or a solid background around a logo.
- Without a color, the top left pixel's color is used.
tolerancealso trims near colors, such as JPEG artifacts.- Frames keep their position in the animation.
Animation.frames (#60)
The frames of an animation as an array. Changing the array (push(), splice(), …) changes the animation, and you can replace it as a whole.
Performance (#62–#66)
Every change gives bit-identical results, checked against 3.1 on about 1600 images and the resvg test suite.
| Faster by about | |
|---|---|
| GIF decoding | 25% |
| SVG rendering | 15–20% |
| PNG decoding | 25% |
| PNG encoding | 10% |
| Lossless WebP encoding | 15% |
| Resizing | 10% |
The package is also about 10 kB smaller, because the type declarations of internal modules are no longer included.
Benchmarks (#61)
bench/ compares ImageScript with Jimp, image-js, Photon, sharp, @napi-rs/canvas and ImageScript 1.x. It covers:
- decoding and encoding
- image operations
- text and SVG rendering
- animations
- file sizes and install sizes
The results are refreshed automatically after every release.
Deprecated
- Animations as arrays:
animation[0],animation.length,animation.map()and the other array methods on an animation still work, but in 4.0Animationwon't extendArrayanymore. Useanimation.frames. PNGMetadatais now calledMetadata. The old name stays an alias until 4.0.
Fixes
- TGA encoding: run length encoded packets end with the row, as TGA 2.0 requires. Some readers rejected the files before, Pillow among them (#57).
- PNG text metadata: text that isn't Latin-1 (such as
Ⓒor emoji) is written as UTF-8 intoiTXtchunks. Readers showed it garbled before (#56). creationTime: an invalid value throws aRangeErrorinstead of writing "Invalid Date" (#56).
Upgrading
No code changes are needed. If you compare the frames of re-encoded animations with the originals, pass {optimize: false} to the encoder, because optimized files decode to different (smaller) frames.