Closed Auxority closed 1 month ago
Hey @Auxority looks like a bug. Would you be able to try debugging it and finding what the issue is? If you'll submit a PR with test cases I'd be more than happy to review and approve.
I'll give it a go on Monday :)
Sadly a simple make
or make test
on the latest tag or master branch already fails. And there are no clear instructions on how to build the project or how to use it.
I did look through the code and found that if you replace the Quality parameter with the Lossless: true
parameter, that it works fine. Although this still means that the Quality parameter won't work for values between 86 and 100. It probably has something to do with this function:
func vipsSaveToBuffer(params C.struct_SaveParams) ([]byte, error) {
if err := C.save_to_buffer(¶ms); err != 0 {
return nil, handleSaveBufferError(params.outputBuffer)
}
buf := C.GoBytes(params.outputBuffer, C.int(params.outputLen))
defer gFreePointer(params.outputBuffer)
return buf, nil
}
Which is kinda strange, since that same method is used for AVIF, and not only for WebP images. Just to be sure I also ran the vips command vips copy 01.png 01.webp[Q=100]
in my Docker container, and that worked fine.
I'd gladly contribute if the instructions were a bit clearer, but for now I'll leave it as is. I hope you guys are able to find a fix.
Edit: This is the stack trace with the relevant methods:
/my-code.go
params := vips.WebpExportParams{
Quality: 100,
}
buffer, _, err := image.ExportWebp(¶ms)
/go/pkg/mod/github.com/davidbyttow/govips/v2@v2.13.0/vips/image.go:924
buf, err := vipsSaveWebPToBuffer(r.image, paramsWithIccProfile)
/go/pkg/mod/github.com/davidbyttow/govips/v2@v2.13.0/vips/foreign.go:386
return vipsSaveToBuffer(p)
/go/pkg/mod/github.com/davidbyttow/govips/v2@v2.13.0/vips/foreign.go:465
if err := C.save_to_buffer(¶ms); err != 0 {
return nil, handleSaveBufferError(params.outputBuffer)
}
Means that it goes wrong here: C.save_to_buffer(¶ms); So it seems that there is an issue with the C bindings.
Oh I think I found the issue! @tonimelisma
if (!ret && params->quality) {
vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
The ret variable is NOT set here in foreign.c:299
.
int set_webpsave_options(VipsOperation *operation, SaveParams *params) {
int ret =
vips_object_set(VIPS_OBJECT(operation),
"strip", params->stripMetadata,
"lossless", params->webpLossless,
"near_lossless", params->webpNearLossless,
"reduction_effort", params->webpReductionEffort,
"profile", params->webpIccProfile ? params->webpIccProfile : "none",
"min_size", params->webpMinSize,
"kmin", params->webpKMin,
"kmax", params->webpKMax,
NULL);
if (!ret && params->quality) {
vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
return ret;
}
While it is set in many other methods:
if (!ret && params->quality) {
ret = vips_object_set(VIPS_OBJECT(operation), "Q", params->quality, NULL);
}
Although this still seems strange though, because it does work at lower quality values.
Thank you so much @Auxority - great find. Do you think you could send a PR?
Sure, will try to do that today.
edit: day was filled at work, trying again tomorrow.
Thank you <3
Hey there, I ran into an issue while attempting to convert an image from JPG to WebP. It works fine when converting it from JPG to AVIF, but for some reason the JPG to WebP conversion doesn't work. At least, not at 100% quality. At lower quality values (below 89), the conversion works fine.
Code:
Output: