Converting webP images at scale

Andreas Sandberg
PriceRunner Tech & Data
3 min readNov 25, 2021

At PriceRunner we handle a lot of images, hundreds of millions actually.

The main source for these images are merchants providing us with image links in addition to all other offer information (such as the price, stock status and product description).

In order to present these images on our site in a consistent and efficient way we need to do some basic image transformations. We may need to scale the image dimension or compress the image to optimize the image payload on a mobile device. To further improve performance and decrease the load on our system all requested images are cached in CloudFlare.

The native support for image transformation in Java is limited. In terms of image formats only jpeg, png, gif, bmp and wbmp are supported natively. Image processing is also slow (and expensive in terms of CPU and memory), however, it used to be sufficient for our needs until webP came into the picture.

WebP is an image format developed by Google and was first announced during the end of 2010. The image format has many benefits compared to the traditional ones (primary jpeg, gif and png), with a smaller file size being the main one. Since most modern web browsers have native support for webP images nowadays, the format has increased in popularity.

This is also the case for our merchants. Many of them rely on automated transformation in their CDN:s based on the browser requesting the image (browsers not supporting webP will be served a different format). Hence our image processing must somehow also support webP.

And here comes the catch! Let’s say you want to scale an image using pure Java code, this is what it could look like:

BufferedImage originalImage = ...Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_SMOOTH);

Although this method has rather poor performance it will work using pure Java code. But since Java lacks native support for webP we need to rely on external libraries or write the algorithm ourselves. Since Google developed the image format, they have also written open source libraries for coding (cwebp) and decoding (dwebp) webP which is available at their official developer site. There are also pre-compiled binaries available for all major platforms, which is great for users who want to convert a few webP images.

However, the library is written in C, which means that developers either need to call the library using native bindings (such as JNI) or use the command line-based tool:

final byte[] imageBytes = ...Path inputFile = Files.write(Paths.get("/tmp/input.webp"), imageBytes);Path outputFile = Paths.get("/tmp/output.png");Process process = Runtime.getRuntime().exec("dwebp " + inputFile " -o " + outputFile);

Regardless of how the call is made the library will consume a significant amount of CPU and non heap memory during conversion which will be hard for the JVM to keep track of. The conversion will also be rather time consuming per image, in our tests (with max two concurrent conversions) the process execution time exceeds 20 seconds per image.

Therefore although functioning, the official Google library will not be sufficient when trying to convert millions of images per day (at least not when using Java). Thankfully there is an open-source alternative to the rescue; TwelveMonkeys which contains several javax.imageio plugins which are easily loaded into the JVM by simply putting the jars to the application classpath. The support for webP images is currently limited to lossy webP, using VP8 encoding and simple format.

Implementation is straight forward;

byte[] imageBytes = ...try (var is = new ByteArrayInputStream(imageBytes);
var os = new ByteArrayOutputStream()) {
final BufferedImage image = ImageIO.read(is);
if (image != null && ImageIO.write(image, "jpg", os)) {
var converted = os.toByteArray();
}
}

The performance is far better compared to the dwebp alternative and we currently convert more than 50 images per second using ten instances of our image service.

From a personal point of view I think it is remarkable that Google don’t provide a effective pure Java library with support for webP image transformation but instead rely on the open-source community to resolve this matter.

--

--