gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
74.62k stars 7.45k forks source link

Muted black and white levels when resizing WebP images #8879

Open aureliendossantos opened 3 years ago

aureliendossantos commented 3 years ago

Image Processing works well when the source image is a png or a jpg, but when it's a webp, blacks and whites appear toned down. At first I wondered if it was a problem similar to #8298, but that issue has to do with non-sRGB images, which is not the case here. My webp is sRGB (unless cwebp is fooling me) and the problem only appears with webp images.

What version of Hugo are you using (hugo version)?

hugo v0.87.0-B0C541E4+extended windows/amd64 BuildDate=2021-08-03T10:57:28Z VendorInfo=gohugoio

Example

Here's a sRGB webp image I want to process. You can clearly see the deep blacks in the trees and the bright clouds. (How I created this image: I first exported it as a sRGB PNG in Adobe Lightroom then converted it with cwebp. The problem would have been the same if I directly exported the webp with, say, GIMP)

Photo You can download the original here.

Here's the image processed by Hugo with .Resize. No matter the targeted format (webp, png, jpg) or the targeted size, it will always have these muted blacks and whites.

This is 66_hu491b7a84666ef3266e0bfb2f80fb050e_290232_1600x0_resize_q75_h2_linear_2.webp (converted in png so I could upload it on GitHub)

ptgott commented 3 years ago

I think I've reproduced this with a failing integration test here. I'll start digging in this week.

Edit: the test doesn't use sRGB, so I'll need to tweak it a bit. If I encode the test images using image.NewRGBA, the test passes.

ptgott commented 3 years ago

I've reworked my integration test. Now it loads a real webp image using the sRGB color space (created via Gimp). The image uses dark and light colors from the original image in this thread, with one color per half to make it easy to compare colors before and after resizing.

The test copies the image to the assets/images directory, then resizes a template to 10x10 png. Unfortunately, I've failed to reproduce this issue: the colors on either side of the resized image are the same as the ones in the original image. @aureliendossantos is there anything the test could be missing here? Thanks!

bep commented 3 years ago

I have tested the above web image in a standalone Go program, by just decoding the webp and encoding it directly as JPEG. And the result is the "dull blacks" as reported above. This is, of course, narrows down the problem and makes it easier to pin down. Not sure what it is, if it's a bug in the Webp decoder we use. We use a Go native decoder. We use the libweb C encoder (because there are no Go encoder). We could, in theory, use the C decoder, but that opens up a massive set of security questions that I'm not prepared to ask/answer.

package main

import (
    "image"
    "log"
    "os"
    "path/filepath"

    "image/jpeg"

    _ "golang.org/x/image/webp"
)

func main() {
    dir := "/Users/bep/dev/sites/hugotest/assets/images/misc/"
    filename := filepath.Join(dir, "webp-muted.webp")
    outfilename := filepath.Join(dir, "webp-muted.jpg")

    f, err := os.Open(filename)
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    img, _, err := image.Decode(f)
    if err != nil {
        log.Fatal(err)
    }

    outFile, err := os.Create(outfilename)
    if err != nil {
        log.Fatal(err)
    }
    defer outFile.Close()

    if err := jpeg.Encode(outFile, img, nil); err != nil {
        log.Fatal(err)
    }
}
bep commented 3 years ago

OK, the issue is reported upstream here: https://github.com/golang/go/issues/40173

savtrip commented 2 years ago

@aureliendossantos Did you end up finding a work around for this issue?

aureliendossantos commented 2 years ago

@aureliendossantos Did you end up finding a work around for this issue?

No, I didn't yet!

xianfei commented 1 year ago

I fixed it via replacing "golang.org/x/image/webp" with "github.com/chai2010/webp". You can try it https://github.com/xianfei/hugo WX20230205-202245@2x WX20230205-201944@2x

savtrip commented 1 year ago

Hey @bep it seems this issue was not resolved upstream, is it possible to switch to another library such as: https://github.com/chai2010/webp? Or any other solution that uses an FFI around CWEPB decode?

I saw your previous comment that said you weren't prepared to ask/answer the implications of an external binary, is this still the position?

If not I am more than happy to contribute and make a pull request.

Also, thank you for maintaining Hugo, it is much appreciated.