Skip to content

Conversation

@willnorris
Copy link
Owner

This is an experimental branch that adds webp encoding. In my very limited testing, this seems to add quite a lot of visual artifacts at 90% compress, and results in larger files sizes at lossless compress. Now granted, that was only with a sample size of 1 using https://octodex.github.com/images/codercat.jpg. I'll try more testing later, but wanted to get this posted for others to take a look at and try out.

Updates #388

@robgordon89
Copy link

@willnorris 👋 firstly thanks for this amazing project, I have tested this it works really well the issue I had with WebP was transparency and this seems to have fixed that, I also wanted to say that at 90% quality its very distorted but at 100% it seems to be 4x larger 🤔

Might be better to default to 100% quality

In any case this does add better support IMO even with the increased size, i tried the latest go-libwebp 1.8.0 without any decrease in final image size.

@bemoty
Copy link

bemoty commented Apr 14, 2025

Hi @willnorris, thanks so much for your work on this.

I just tested this branch again using my own images and it worked really well. No artifacts or distortion, especially in lossless format which is my planned use case. Only thing I noticed is that the quality parameter doesn't seem to work yet -- when I fetched http://localhost:8080/500,webp,q60/f/logo.png I still got the lossless version of the image -- though I might be misunderstanding something here.

In any case, I would love to see this get added. Even if just as an experimental option. Any plans for doing so? :)

Cheers

image

@willnorris
Copy link
Owner Author

yeah, for some reason the quality option wasn't doing anything. Updating to the latest go-libwebp seems to have resolved it, at least for me. I'm still seeing wildly different results between q100 and q99, though. Apparently I can't upload webp images to GitHub, but you should be able to test locally as well:

The original JPG image is 183 KB:
http://localhost:8080/x/https://willnorris.com/images/imageproxy/small-things.jpg

The webp image at q100 is 484 KB with the same visual quality:
http://localhost:8080/x,webp,q100/https://willnorris.com/images/imageproxy/small-things.jpg

The webp image at q99 is 9.5 KB with significantly less quality:
http://localhost:8080/x,webp,q99/https://willnorris.com/images/imageproxy/small-things.jpg

Now given that the q99 webp is only 9KB, the quality is understandable. But why did q99 reduce it by that much? It seems like it is treating it as 9% quality rather than 99%. I've looked into the go-libwebp source and even hardcoded some values to make sure it's passing the right value down to the underlying encode function, and that doesn't seem to make a difference.

So yeah, I don't mind going ahead and merging this as an experimental feature. I'll probably leave the default encoding format as JPG, even for WEBP source images. I'll only use WEBP output if the option is explicitly requested, at least for now.

@bemoty
Copy link

bemoty commented Apr 15, 2025

I did some more testing and it seems like this is a bug in how both the dynamic and transpiled versions of libwebp are used by go-libwebp. I hardcoded some q-values in [email protected]/lib/common/common.go/Encode

	size := enc(
		uintptr(unsafe.Pointer(pix)),
		int32(m.Bounds().Dx()),
		int32(m.Bounds().Dy()),
		int32(m.Stride),
		q,
		uintptr(unsafe.Pointer(out)),
	)

Turns out, the q-value apparently has a range of (0,100], not (0,1]. Values smaller than 100 seemingly apply quality changes accordingly; 100 itself is visually lossless, but since the EncodeFunc is WebPEncodeRGBA and not WebPEncodeLosslessRGBA, I'm guessing this doesn't provide actual lossless results.

Anyway... I think there is not much we can do here. The go-libwebp Encode function caps the q-value between 0 and 1, and this is something that will have to be fixed upstream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants