// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Original code was cropped and fixed by @DarthSim for imgproxy needs package main import ( "errors" "image" "image/color" "io" "golang.org/x/image/riff" "golang.org/x/image/vp8" "golang.org/x/image/vp8l" ) var errInvalidFormat = errors.New("webp: invalid format") var ( fccALPH = riff.FourCC{'A', 'L', 'P', 'H'} fccVP8 = riff.FourCC{'V', 'P', '8', ' '} fccVP8L = riff.FourCC{'V', 'P', '8', 'L'} fccVP8X = riff.FourCC{'V', 'P', '8', 'X'} fccWEBP = riff.FourCC{'W', 'E', 'B', 'P'} ) // Since we need this only for type detecting, we can return fake image func decodeWebp(r io.Reader) (image.Image, error) { return image.NewRGBA(image.Rect(0, 0, 1, 1)), nil } func decodeWebpConfig(r io.Reader) (image.Config, error) { formType, riffReader, err := riff.NewReader(r) if err != nil { return image.Config{}, err } if formType != fccWEBP { return image.Config{}, errInvalidFormat } var ( wantAlpha bool buf [10]byte ) for { chunkID, chunkLen, chunkData, err := riffReader.Next() if err == io.EOF { err = errInvalidFormat } if err != nil { return image.Config{}, err } switch chunkID { case fccALPH: // Ignore case fccVP8: if wantAlpha || int32(chunkLen) < 0 { return image.Config{}, errInvalidFormat } d := vp8.NewDecoder() d.Init(chunkData, int(chunkLen)) fh, err := d.DecodeFrameHeader() return image.Config{ ColorModel: color.YCbCrModel, Width: fh.Width, Height: fh.Height, }, err case fccVP8L: if wantAlpha { return image.Config{}, errInvalidFormat } return vp8l.DecodeConfig(chunkData) case fccVP8X: if chunkLen != 10 { return image.Config{}, errInvalidFormat } if _, err := io.ReadFull(chunkData, buf[:10]); err != nil { return image.Config{}, err } const alphaBit = 1 << 4 widthMinusOne := uint32(buf[4]) | uint32(buf[5])<<8 | uint32(buf[6])<<16 heightMinusOne := uint32(buf[7]) | uint32(buf[8])<<8 | uint32(buf[9])<<16 return image.Config{ ColorModel: color.NYCbCrAModel, Width: int(widthMinusOne) + 1, Height: int(heightMinusOne) + 1, }, nil default: return image.Config{}, errInvalidFormat } } } func init() { image.RegisterFormat("webp", "RIFF????WEBPVP8", decodeWebp, decodeWebpConfig) }