Repository navigation
3.8.0
This release encodes animations a frame at a time, adds OpenType features to text rendering and sharp YUV conversion to lossy WebP, and brings SVG rendering much closer to resvg: filters, patterns, markers and embedded images. It also fixes lossless WebPs that 3.7.0 could write undecodable (#82). Like every codec in ImageScript, it's plain TypeScript: no WebAssembly and no native code. There are no breaking API changes.
const encoder = Animation.webpEncoder(1000, 1000, { quality: 85 });
for (const frame of frames) await encoder.add(frame, { duration: 40 });
const webp = await encoder.finish();
await Image.renderText(font, 32, 'Office 1/2', { features: { smcp: true, frac: true } });
await image.encodeWebP({ quality: 80, sharpYuv: true });
await Image.renderSVG(svg); // now with filters, patterns, markers and <image>New
Animations a frame at a time
Animation.webpEncoder(), Animation.gifEncoder() and Animation.apngEncoder() (width, height, options) encode animations without holding all frames in memory: await encoder.add(frame, options) for each frame (a Frame or any image; options like { duration: 40 } override the frame's), then await encoder.finish().
- Same files as
encodeWebP(),encodeGIF()andencodeAPNG()produce for the same frames - Memory: only the canvas and the previous frame are kept (APNG keeps its frames compressed until the end): 120 frames of 1000x1000 take 159 MB instead of 1066 MB
OpenType features in renderText
features: { tnum: true, smcp: true, liga: false, salt: 2 } turns features on for the whole text (tabular numbers, small caps, stylistic sets, ...), turns them off (default ones like ligatures and kerning included) or picks an alternate by number. It works like HarfBuzz's user features and shapes exactly like hb-shape --features. Fonts that lack a feature ignore it.
Sharp YUV for lossy WebP
encodeWebP({ quality, sharpYuv: true }) (for images, animations and Animation.webpEncoder) converts to YUV with libwebp's sharp conversion, ported so the files match cwebp -sharp_yuv. Colored edges stay sharp. Encoding takes about twice as long. Photos come out about the same size (+0.3% on a 1920x1080 photo), but images with many hard color edges get considerably larger.
Image#region()
region(x, y, width, height) copies a region into a new image without changing the original. It's like crop on a clone, but without copying the whole image first.
SVG rendering
- Filters: all 17 primitives (blur, offset, flood, composite, merge, drop shadow, color matrix, component transfer, tile, blend with all 16 modes, morphology, convolve matrix, turbulence, displacement map, diffuse and specular lighting with all three lights, image), plus the CSS filter functions (
blur(),drop-shadow(),grayscale(), ...). Filter regions,color-interpolation-filtersandhrefinheritance are supported. Ported from resvg: 396 of its 408 filter tests pass, up from 81 - Patterns: in both units, with
viewBox,preserveAspectRatio,patternTransformandhrefinheritance. 32 of resvg's 33 pattern tests pass, up from 4 - Markers: start, mid and end markers, with
orient(includingauto-start-reverse),markerUnits,refX/refY,viewBoxand clipping, placed like resvg places them. 61 of 64 tests pass, up from 11 - Images (
<image>) from data URIs: every formatImage.decode()reads (GIFs show their first frame) and nested SVGs, gzipped ones included. External files and URLs aren't loaded
Text in SVGs isn't rendered yet.
Improvements
- Optimized lossy WebP animations are smaller and look better. Like libwebp, they skip pixels that changed by less than a tolerance derived from the quality, and make unchanged pixels transparent only in whole 8x8 blocks. On cross-fading animations the files are up to 13% smaller than before, at 0.1 dB PSNR below unoptimized ones (before: 0.8-1 dB below)
Fixes
- Lossless WebPs, and lossy ones with alpha (most optimized animations), could be undecodable since 3.7.0 (#82)
Performance
composite()with an opacity is about 40% faster innormalmode (7.6 ms instead of 12.6 ms for a 1100x680 layer), and 5-30% faster without an opacity