-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: x/image/webp: support for WebP Encoding #45121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
cc @nigeltao |
A WebP encoder would be a lot of work. If someone wants to write one, that would be great. But as far as I know nobody is working on that. |
That's a shame, whilst I understand that it may be a bit of work, it feels like it should be out of the box considering webp and go are both made by you guys! Adding C bindings when converting to webp using third party packages can be messy, as well as using the executables. I would love to offer a hand to contribute to the /x/image library but wouldn't know where to start. |
It's not a bit of work. As Ian said, it's a lot of work. :-) |
The good news is that image encoding is much less of a security minefield than image decoding is, simply because the input format (a bitmap) is far, far simpler. That said, have you considered ImageFlow? It’s free software (AGPL) available as both a daemon and a library. Commercial licenses are also available. |
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as duplicate.
This comment was marked as duplicate.
Starting a new website project with a Go backend and was planning on using WebP for image thumbnails and it's really sad to see that there's no native encoder.. :( I would really like to avoid using C bindings (due to performance and memory safety concerns), but it seems that's the only option at the moment, except for executing the official I also considered using Rust, but that's way too advanced for me. Edit: I found https://github.com/nickalie/go-webpbin which seems quite decent. haven't tested it yet though. |
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as duplicate.
This comment was marked as off-topic.
This comment was marked as off-topic.
@ex-tag considering the shift with Intel and Nvidia recently and major providers using AV1 and particularly AVIF for websites, future steps for supporting these fantastic encoders would be hugely beneficial for the stdlib. But can appreciate its not a small job. |
Could go-libwebp by Jack Mordaunt offer a potential solution? I'm aware that rewriting libwebp in Go would be quite time-consuming, but Jack Mordaunt utilized ccgo and was able to port the libwebp C code to native Go code, making it functional, if I understand correctly. I'm not an expert, and I'm unsure of any potential risks this approach may present, but I wanted to share the idea. @JackMordaunt |
I think there is a better solution. Example may use c-bindings from library on C language. |
Thanks for the reference! Yes, it's functional. However there's a lot of downside to the transpilation approach which bars it from being anything official.
For anyone interested, |
Finally! The native solution - https://github.com/HugoSmits86/nativewebp |
looks like few lines of code one could write over the weekend. so it was not about a lot of work but rather just reading the spec, i assume... gj. |
Awesome! Is there a chance that nativewebp could become x/image/webp? Thanks for the great work, @HugoSmits86! |
@wjkoh I’m not sure how to go about making that happen. If there’s a process or interest from the Go team, I’d be happy to explore it! |
@nigeltao @dmitshur @rolandshoemaker could you please advise on how to submit a new feature to x/image/webp? |
I don't think it would make sense to integrate this until it also supports the lossy part of the spec (which is what makes webp a viable jpeg replacement, and incidentally is 95% of the complexity of the format. There's a reason libwebp is 50k lines of code). |
@ALTree Fair point, but WebP is also a container format supporting VP8I, VP8X, and VP8L. Partial support is better than nothing, especially for specific use cases. For instance, one client required WebP output, and while most accept JPEG or PNG, nativewebp let me meet their needs without overhauling my pipeline. Even limited functionality can solve real-world problems. |
Exactly. My use-case. |
@ALTree Why is lossy support needed? Are lossless files too large? |
I am curious to know more about this. What client is this that requires only webp output, but does not support jpeg/png? How popular is it? |
Take this 3.0MB jpg image of Castello Estense in Ferrara. Converting it to a webp file in lossy mode with
Converting it to a lossless webp (again at
One may argue that a lossless conversion makes no sense in this scenario, since webp in lossless mode is supposed to be a png replacement and here we have a jpg image, but that's my point: it makes no sense to serve a VP8L webp in this case. If a client asks for a webp image hoping to save some bandwidth over jpeg, he won't be happy to receive a lossless webp that is more than 2 times the size of what a jpeg would have been. In fact, if lossless webp is all you support, in this scenario you'd be better off ignoring the webp preference and serving the jpg image itself. webp is intended to be both a png and a jpg replacement, with its lossless and lossy modes respectively. Someone interested in using the format will expect an encoder in the standard library to support both. |
I have tried with a PNG file (1,1Mb) |
@agnivade The client is an enterprise with a complex pipeline of 100+ scripts and tools for after-production image processing. They use lossless WebP to avoid quality loss from repeated saves across steps. My tool integrates into this on-premise setup, where file size and/or network traffic isn’t an issue. Switching to PNG or another format would require major changes, including custom metadata handling, needing approval from multiple departments; a lengthy process that could risk the deal. Therefore it was easier for me to just build nativewebp and meet their needs directly and avoid these complications.
@ALTree Your argument overlooks the timeline. While full support for all WebP modes would be ideal, after 14 years of Go and WebP, there’s still no support at all(!), and no signs of it changing. At this point, some support is far better than none. Those expecting support for all modes likely also expect Google’s language to have native WebP support by now. In both cases, they’ll be equally disappointed but not worse off. Meanwhile, there’s a significant group for whom VP8L support alone provides a viable solution. It’s about addressing current gaps rather than waiting indefinitely for a perfect solution. |
People don't seem to be asking the right question. There is only one question we need to ask: If we add a lossless WebP encoder to x/image/webp, who will be hurt, and who will benefit? The answer to the first question is no one, and to the second is everyone. Lossless WebP is already a better alternative to PNG and, in some cases, a deal-closer for Go users, as @HugoSmits86 mentioned above. At what cost? Only about 1,000 lines added to x/image/webp. Also, the more people see the new encoder, the greater the possibility that they will try to bring a lossy WebP encoder to fruition as well. |
One of the many applications of this new WebP lossless encoding for Go is Hugo. I only need to install ImageMagick to convert PNG files to WebP files for my Hugo-based website. I think this WebP encoding can allow Hugo to automatically transcode all PNG files to WebP without manual intervention, saving a ton of network traffic for all Hugo users worldwide. @bep @spf13 |
As to Hugo; Hugo's extended version (built with |
Probably OT but wouldn't it be better to just ship hugo with platform-native imagemagic/vips instead of cgo? Personally, I use vips cli to convert images into avif in my projects nowadays. And it is no different than using the old school imagemagic in php, for example, because you still need those libraries to be present in the machine and call them on one way or another, so why not just add one binary to handle all of the work and avoid cgo altogether? Not sure if imagemagic supports pipes, vips does not, but doing the work on file system seems a non-factor to me any way. In the end, Go is has GC and trying to use non-GC code will never not be a problem. |
@ivanjaros Image processing libraries are a security nightmare, which is probably why @bep is going to use WebAssembly. |
Trying to get discussion back on track, it seems like this should be a proposal, specifically to add If @HugoSmits86 is willing to contribute their implementation to the standard library under the Go license, I'm not sure there would be objections from the Go team. If the lossless encoder provides value to users, which based on discussion here it seems like it would, adding initial support for only the lossless mode, but with the ability to extend it in the future, seems reasonable. One thing worth considering though is that the x/image module is relatively lightly maintained. We do not have anyone on the core Go team who actively develops these packages, and they receive sporadic attention (my involvement has been entirely focused on fixing security issues.) It is worth thinking about whether this would provide significant value as an x/image package, or if it can be more valuable (and receive more attention) remaining as a third-party module. |
Thanks! I'd love to contribute my encoder to the standard library. Now that nativeWebP has reached version 1.0 with full support for VP8L, updates are going to slow down anyway, mostly optimizations for speed and compression. libwebp still outperforms it in compression efficiency, but at least we're already significantly better than the PNG encoder in the Go image package. I agree that this should be a formal proposal to add func Encode(w io.Writer, img image.Image, opt *Options) error and an Options type to x/image/webp, following the pattern of other format encoders. Regarding maintenance, since nativeWebP is stabilizing, I’d expect fewer major updates, which makes it easier to maintain. I understand that x/image doesn’t get as much attention, but if there's interest, I’m happy to contribute and help maintain it. If it makes more sense to keep it as a third-party module for now, I’m open to that as well; whatever best serves Go developers. Looking forward to thoughts from the team! |
The answer to the first question is not "no one". Code has a maintenance cost and image codecs have historically been a rich source of security issues. @HugoSmits86 may have the best of intentions re helping maintain it, but there's no guarantee that he'll still be around 10 years from now. The IIUC, these 'x' packages were also all started from before we had
For example, the current |
To be fair the "who would be hurt" comment was about releasing an incomplete encoder; one that supports only VP8L at first, instead of waiting until VP8L, VP8, and VP8X (which the decoder also lacks, by the way) are all supported. The point was that supporting VP8L alone wouldn’t negatively impact anyone, so why not make it available sooner? Nobody is denying that maintaining a codec requires effort. However, I don’t think it’s fair to demand a 10-year commitment upfront. If that were the standard, the Go team itself wouldn’t be able to release anything; unless they exclusively recruited monks who never left their monastery (Ensuring they wouldn’t get hit by a bus and break their decade-long open-source vow). That said, I understand the concerns around API stability and long-term maintenance. The original discussion wasn’t about implementing a full encoder from the start but rather about adding VP8L support in the absence of VP8. To balance these concerns with maintainability, my proposal is to rework my codec in the style of the existing VP8L decoder. This approach ensures that potential evolutions, such as lossy encoding, remain outside of the VP8L package, preventing future modifications to the VP8L encoder and keeping the design clean and stable.
This argument actually strengthens the case for including an encoder. If security is a concern, relying on third-party libraries outside the Go ecosystem seems like an even greater risk. Expecting users to depend on external, potentially unvetted libraries for a core image format (without a reliable way to assess their security) raises questions about responsibility. If we acknowledge that image codecs require careful maintenance due to security risks, it seems more responsible to provide a well-maintained, in-house solution rather than pushing users toward potentially unsafe alternatives. |
One issue is discoverability. Searching 'webp' on pkg.go.dev, x/image/webp is the first result, (at least) the next two are C library wrappers, and I have to scroll down to see @HugoSmits86's package at number 10. I didn't know there was a native encoding implementation until I searched for this issue. Is it worth updating x/image/webp's package documentation to link to Hugo's package? Also it would be nice if I could filter out CGO projects when searching, but that's a separate issue. |
Hi there,
Currently we are able to decode webp images, which is great. But why can't we encode them?
Given that PSI is such a crucial factor for getting websites to rank, it's important that any server should be able to convert and serve webp images.
I have to jump through hoops at the moment and use the webp executable which is far from ideal.
Please please add an encoder!
Many many thanks.
The text was updated successfully, but these errors were encountered: