WordPress with PHP GD’s image resize artifact-pattern problem

Up until now, I’ve been using WordPress with the PHP GD graphics library (libgd) to downscale images for thumbnails and responsive images. The resulting images haven’t always been pretty and they’ve ended up larger than the source images. I finally found a good solution that doesn’t involve switching to ImageMagick.

GD introduces some complex repeating and alternating patterns on downscaled images. On many photos it was almost impossible to see the effect, but on some simple illustrations or images with slight gradients it would be very obvious. The artifacts introduced additional complexity in the images which would yield poor compression.

The below image groups demonstrates an example of the type of noise-artifact patterns that can be added to downscaled images when resizing with PHP+libgd. The rightmost image highlights the differences between the original and downscaled images. Click the thumbnails for larger versions.

Original image
Original image
Downscaled
Downscaled
Contrast enhanced
Contrast enhanced
Original image
Original image
Downscaled
Downscaled
Contrast enhanced
Contrast enhanced

The first image has a solid background that should be the same color for most of the image. You can see the noise patterns shift in the different encoding tiles. The second image has a more complex background and shows a more varied noise pattern.

The complex patterns, despite being repeating, don’t compress well. The two downscaled example images above take up almost twice the number of bytes compared to the original despite having 46 % fewer pixels. This is after both images being compressed with the state-of-the-art lossless Zopfli compression method.

The core issue seems to be an optimistic cast from floating numbers representing the red-green-blue (RGB) colors to an integer. The resulting color values may vary greatly depending on the processor’s handling of high-precision floating numbers.

A patch was suggested in that changed the behavior from cast to rounding the number. This would should have reduced the impact of the issue but at a possibly hefty performance cost. The patch was never picked up by libgd, however.

The most common alternative to libgd is ImageMagick but I don’t consider it to be an option anymore as the library has been plagued with security vulnerabilities in recent years. At the time of writing, the Common Vulnerabilities and Exposures (CVE) List contains 504 different vulnerabilities found in ImageMagick.

WordPress supports GD and ImageMagick out of the box but its image editor handling is modular. Creuna Finland went ahead and made an Vips Image Editor plugin that uses the Vips (libvips) graphics library. Vips is a much more modern and resource efficient alternative to GD and ImageMagick.

Vips produces smaller files than both GD and ImageMagick and it does it faster and without the artifact corruptions of GD or the security baggage of ImageMagick. I still apply additional post-processing with the Guetzli and Zopfli compression methods to make the image files even smaller, though. Vips can also output WebP image files when compiled against libwebp.

I’ve installed Vips and regenerated and recompressed all downscaled and thumbnail images I had in WordPress. I also took this as an opportunity to generate additional image sizes and also generate WebP images of all sizes to improve responsive image support and to be more bandwidth efficient. The compression gains from switching image processing library made it feasible to store and offer more image sizes for browsers to choose from.

I’ve also noticed that it’s faster to upload new images to WordPress after switching to Vips.

If you definitely have to stick with GD then you can try updating and applying the above patch. If you want to try using a more modern library, I suggest you try using Vips instead.

Thanks to the Vips project for creating an excellent image processing library and thanks to Creuna for bringing it to WordPress.