golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.24k stars 17.57k forks source link

x/image/webp: unable to decode image #60437

Open jmooring opened 1 year ago

jmooring commented 1 year ago

What version of Go are you using (go version)?

go version go1.20.4 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jmooring/.cache/go-build"
GOENV="/home/jmooring/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/jmooring/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/jmooring/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/snap/go/current"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/snap/go/current/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.4"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build960738136=/tmp/go-build -gno-record-gcc-switches"

What did you do?

main.go ```go package main import ( "fmt" "image" "log" "os" _ "golang.org/x/image/webp" ) func main() { reader, err := os.Open(os.Args[1]) if err != nil { log.Fatal(err) } m, _, err := image.Decode(reader) if err != nil { log.Fatal(err) } fmt.Printf("Successfully decoded %s. Image bounds: %s\n", os.Args[1], m.Bounds()) } ```
go run . test.webp

What did you expect to see?

Successfully decoded test.webp. Image bounds: (0,0)-(210,210)

What did you see instead?

2023/05/25 11:56:07 webp: invalid format
exit status 1

Notes

This is not an animated WebP image.

This image is not corrupt:

Test image

test.webp

jespino commented 1 year ago

I've been investigating a bit on this issue, and I want to provide some extra info here:

It looks like related to the Alpha Channel. The webpinfo command gives me the following output:

File: test.webp
RIFF HEADER:
  File size:  58606
Chunk VP8X at offset     12, length     18
  ICCP: 1
  Alpha: 1
  EXIF: 0
  XMP: 0
  Animation: 0
  Canvas size 210 x 210
Chunk ICCP at offset     30, length    680
Chunk VP8L at offset    710, length  57896
  Width: 210
  Height: 210
  Alpha: 1
  Animation: 0
  Format: Lossless (2)
No error detected.

This is saying that there are three chunks. The first one is the VP8X, which works fine. The second one, the ICCP (The Color Profile), is not implemented in the decoder, and the third one is a VP8L chunk, and because we already declared that we need Alpha, we will check if the Alpha channel is defined. Because we ignore the ICCP, there is no alpha channel defined.

If you use image magick to convert from that file to png and back to webp, the webpinfo command gives the following info:

File: test2.webp
RIFF HEADER:
  File size:  14520
Chunk VP8X at offset     12, length     18
  ICCP: 1
  Alpha: 1
  EXIF: 0
  XMP: 0
  Animation: 0
  Canvas size 210 x 210
Chunk ICCP at offset     30, length    680
Chunk ALPH at offset    710, length   3308
Chunk VP8  at offset   4018, length  10502
  Width: 210
  Height: 210
  Alpha: 0
  Animation: 0
  Format: Lossy (1)
No error detected.

The main difference is the ALPH chunk is there, so it works perfectly now.

From the code perspective, what happens is that the alpha variable is not initialized before the VP8L chunk is processed.

jespino commented 1 year ago

I'm looking into it more. Reading the specification, the VP8L frame already contains the alpha information. You can read that here: https://developers.google.com/speed/webp/docs/riff_container?hl=es-419#alpha (almost at the end of that section).

So I guess adding support to read the alpha information from the VP8L chunk, should fix this.

gopherbot commented 1 year ago

Change https://go.dev/cl/498535 mentions this issue: Allow to use VP8L+ICC in the same file without APLH chunk