libvips 8.15 is now done, so here’s a summary of what’s new. Check the ChangeLog if you need more details.
The headline features are SIMD optimisations with Highway, some useful
dzsave and TIFF save, metadata improvements, and the usual
small improvements to image format support. Details below!
We need to thank lovell, kleisauke, miltoncandelero, MathemanFlo, donghuikugou, jcupitt, DarthSim, shado23, a3mar, and others for their great work on this release.
Traditionally, libvips has relied on liborc’s runtime compiler to dynamically generate optimised SIMD/vector code specifically for the target architecture. However, maintaining this code proved challenging, and it didn’t generalize to architectures like WebAssembly. Additionally, it lacked support for newer instruction sets like AVX2 and AVX-512, and the vector paths of liborc didn’t match the precision of the C paths.
In 8.15, we’ve used Highway to reimplement vector paths in many operations. Highway is a C++ library with carefully-chosen functions that map well to CPU instructions without extensive compiler transformations. Highway supports five architectures, allowing our code to target various instruction sets, including those with ‘scalable’ vectors (size unknown at compile time). At runtime, dynamic dispatch selects the best available implementation based on the processor’s capabilities, ensuring optimal performance. While Highway is our preferred choice, the liborc paths remain available as a fallback whenever Highway is unavailable.
Additionally, for x86/x86-64 targets, a couple of functions are now marked
target_clones attribute to improve performance on AVX CPUs by ~10%.
An improvement to the shrink operators has allowed a dramatic speedup in edge cases where there was upstream coordinate transformation. Performance should now be more predictable in these cases.
General image load and save improvements
There are two improvements to all loaders and savers. First, you can pass a
revalidate flag to all loaders which will make them bypass the libvips cache
and refetch the image from the source. This is useful if you are loading a file
where the contents might change.
Secondly, we’ve deprecated the
strip option to savers and added a new
option which you can use to select what classes of metadata item you’d like to
not remove. For example:
$ vips copy k2.tif x.jpg[keep=icc:exif]
Will copy a JPEG image, keep any ICC profile and EXIF metadata, but delete
everything else, such as XMP and IPTC. Use
keep=none to remove everything.
This new colon syntax for flag options works everywhere, including in language
We’ve added a new
bitdepth metadata item which all loaders and savers
now support, and deprecated the old
libvips used to rely on libtiff to manage write of compressed tiles. This meant that the selected compression library (libjpeg, perhaps) would run inside libtiff, and was therefore single-threaded.
In libvips 8.15, we’ve taken over control of JPEG and JPEG2000 compression and we now do this ourselves in parallel, leaving only the raw tile write to libtiff.
When making a JPEG-compressed TIFF with libvips 8.14 I see:
$ time vips copy CMU-1.svs[rgb] x.tif[compression=jpeg,tile,pyramid] real 0m11.732s user 1m8.123s sys 0m5.810s
But with 8.15 it’s now:
$ time vips copy CMU-1.svs[rgb] x.tif[compression=jpeg,tile,pyramid] real 0m5.332s user 1m2.410s sys 0m7.543s
More than twice as fast.
We’ve also added support for load and save of 16-bit float TIFFs, and improved the compatibility of 32-bit float TIFFs.
libvips used to save each tile in
dzsave by building and executing a complete
libvips pipeline. With small tiles, the setup and teardown cost
was often a significant part of the runtime, and this limited speed.
With libvips 8.15 we’ve added a direct path for JPEG tiles (the default case) which avoids this overhead.
With libvips 8.14 I saw:
$ time vips dzsave CMU-1.svs[rgb] x real 0m14.435s user 1m26.434s sys 0m50.474s
With 8.15 it’s now:
$ time vips dzsave CMU-1.svs[rgb] x real 0m5.586s user 1m4.462s sys 0m21.581s
Nearly 3x faster. There’s a new
--Q flag to set the Q factor for direct JPEG
We’ve made another improvement to
dzsave: it now uses a better ZIP write
libarchive, which should improve portability.
- PDF loading with PDFium now includes support for PDF forms, making it capable of rendering user-provided input in checkboxes and text fields.
- We’ve added two new edge detectors,
vips_prewitt(), and improved the accuracy of
- GIF load now sets
interlaced=1for interlaced GIF images.
- Improved C++ binding, taking advantage of C++11 features.
- The built-in ICC profiles have been replaced with smaller and more accurate ICC v4 variants.