// Copyright 2014 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.

// Package vp8l implements a decoder for the VP8L lossless image format. // // The VP8L specification is at: // https://developers.google.com/speed/webp/docs/riff_container
package vp8l // import "golang.org/x/image/vp8l" import ( ) var ( errInvalidCodeLengths = errors.New("vp8l: invalid code lengths") errInvalidHuffmanTree = errors.New("vp8l: invalid Huffman tree") ) // colorCacheMultiplier is the multiplier used for the color cache hash // function, specified in section 4.2.3. const colorCacheMultiplier = 0x1e35a7bd // distanceMapTable is the look-up table for distanceMap. var distanceMapTable = [120]uint8{ 0x18, 0x07, 0x17, 0x19, 0x28, 0x06, 0x27, 0x29, 0x16, 0x1a, 0x26, 0x2a, 0x38, 0x05, 0x37, 0x39, 0x15, 0x1b, 0x36, 0x3a, 0x25, 0x2b, 0x48, 0x04, 0x47, 0x49, 0x14, 0x1c, 0x35, 0x3b, 0x46, 0x4a, 0x24, 0x2c, 0x58, 0x45, 0x4b, 0x34, 0x3c, 0x03, 0x57, 0x59, 0x13, 0x1d, 0x56, 0x5a, 0x23, 0x2d, 0x44, 0x4c, 0x55, 0x5b, 0x33, 0x3d, 0x68, 0x02, 0x67, 0x69, 0x12, 0x1e, 0x66, 0x6a, 0x22, 0x2e, 0x54, 0x5c, 0x43, 0x4d, 0x65, 0x6b, 0x32, 0x3e, 0x78, 0x01, 0x77, 0x79, 0x53, 0x5d, 0x11, 0x1f, 0x64, 0x6c, 0x42, 0x4e, 0x76, 0x7a, 0x21, 0x2f, 0x75, 0x7b, 0x31, 0x3f, 0x63, 0x6d, 0x52, 0x5e, 0x00, 0x74, 0x7c, 0x41, 0x4f, 0x10, 0x20, 0x62, 0x6e, 0x30, 0x73, 0x7d, 0x51, 0x5f, 0x40, 0x72, 0x7e, 0x61, 0x6f, 0x50, 0x71, 0x7f, 0x60, 0x70, } // distanceMap maps a LZ77 backwards reference distance to a two-dimensional // pixel offset, specified in section 4.2.2. func distanceMap( int32, uint32) int32 { if int32() > int32(len(distanceMapTable)) { return int32() - int32(len(distanceMapTable)) } := int32(distanceMapTable[-1]) := >> 4 := 8 - &0xf if := * + ; >= 1 { return } return 1 } // decoder holds the bit-stream for a VP8L image. type decoder struct { r io.ByteReader bits uint32 nBits uint32 } // read reads the next n bits from the decoder's bit-stream. func ( *decoder) ( uint32) (uint32, error) { for .nBits < { , := .r.ReadByte() if != nil { if == io.EOF { = io.ErrUnexpectedEOF } return 0, } .bits |= uint32() << .nBits .nBits += 8 } := .bits & (1<< - 1) .bits >>= .nBits -= return , nil } // decodeTransform decodes the next transform and the width of the image after // transformation (or equivalently, before inverse transformation), specified // in section 3. func ( *decoder) ( int32, int32) ( transform, int32, error) { .oldWidth = .transformType, = .read(2) if != nil { return transform{}, 0, } switch .transformType { case transformTypePredictor, transformTypeCrossColor: .bits, = .read(3) if != nil { return transform{}, 0, } .bits += 2 .pix, = .decodePix(nTiles(, .bits), nTiles(, .bits), 0, false) if != nil { return transform{}, 0, } case transformTypeSubtractGreen: // No-op. case transformTypeColorIndexing: , := .read(8) if != nil { return transform{}, 0, } ++ .bits = 0 switch { case <= 2: .bits = 3 case <= 4: .bits = 2 case <= 16: .bits = 1 } = nTiles(, .bits) , := .decodePix(int32(), 1, 4*256, false) if != nil { return transform{}, 0, } for := 4; < len(); += 4 { [+0] += [-4] [+1] += [-3] [+2] += [-2] [+3] += [-1] } // The spec says that "if the index is equal or larger than color_table_size, // the argb color value should be set to 0x00000000 (transparent black)." // We re-slice up to 256 4-byte pixels. .pix = [:4*256] } return , , nil } // repeatsCodeLength is the minimum code length for repeated codes. const repeatsCodeLength = 16 // These magic numbers are specified at the end of section 5.2.2. // The 3-length arrays apply to code lengths >= repeatsCodeLength. var ( codeLengthCodeOrder = [19]uint8{ 17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, } repeatBits = [3]uint8{2, 3, 7} repeatOffsets = [3]uint8{3, 3, 11} ) // decodeCodeLengths decodes a Huffman tree's code lengths which are themselves // encoded via a Huffman tree, specified in section 5.2.2. func ( *decoder) ( []uint32, []uint32) error { := hTree{} if := .build(); != nil { return } := len() , := .read(1) if != nil { return } if != 0 { , := .read(3) if != nil { return } = 2 + 2* , := .read() if != nil { return } = int() + 2 if > len() { return errInvalidCodeLengths } } // The spec says that "if code 16 [meaning repeat] is used before // a non-zero value has been emitted, a value of 8 is repeated." := uint32(8) for := 0; < len(); { if == 0 { break } -- , := .next() if != nil { return } if < repeatsCodeLength { [] = ++ if != 0 { = } continue } , := .read(uint32(repeatBits[-repeatsCodeLength])) if != nil { return } += uint32(repeatOffsets[-repeatsCodeLength]) if +int() > len() { return errInvalidCodeLengths } // A code length of 16 repeats the previous non-zero code. // A code length of 17 or 18 repeats zeroes. := uint32(0) if == 16 { = } for ; > 0; -- { [] = ++ } } return nil } // decodeHuffmanTree decodes a Huffman tree into h. // h may be nil, in which case we decode and discard the tree. func ( *decoder) ( *hTree, uint32) error { , := .read(1) if != nil { return } if != 0 { , := .read(1) if != nil { return } ++ , := .read(1) if != nil { return } = 7* + 1 var [2]uint32 [0], = .read() if != nil { return } if == 2 { [1], = .read(8) if != nil { return } } if == nil { return nil } return .buildSimple(, , ) } , := .read(4) if != nil { return } += 4 if int() > len(codeLengthCodeOrder) { return errInvalidHuffmanTree } := [len(codeLengthCodeOrder)]uint32{} for := uint32(0); < ; ++ { [codeLengthCodeOrder[]], = .read(3) if != nil { return } } := make([]uint32, ) if = .decodeCodeLengths(, [:]); != nil { return } if == nil { return nil } return .build() } const ( huffGreen = 0 huffRed = 1 huffBlue = 2 huffAlpha = 3 huffDistance = 4 nHuff = 5 ) // hGroup is an array of 5 Huffman trees. type hGroup [nHuff]hTree // decodeHuffmanGroups decodes the one or more hGroups used to decode the pixel // data. If one hGroup is used for the entire image, then hPix and hBits will // be zero. If more than one hGroup is used, then hPix contains the meta-image // that maps tiles to hGroup index, and hBits contains the log-2 tile size. func ( *decoder) ( int32, int32, bool, uint32) ( []hGroup, []byte, uint32, error) { // hPix maps tiles to hGroup indices. // The number of hGroups is determined by the maximum index. // VP8L permits unused hGroups in the input. // While the number of used hGroups is bounded by the number of tiles, // the number of decoded hGroups is only bounded by the maximum hGroup index (2^16-1). // // When the total number of hGroups is large, we store only the referenced hGroups // and rewrite hGroup indices in hPix. // // When mapping is nil, we do no remapping. // Otherwise, for hGroup i (where i is the real index of the group), // mapping[i] is -1 for an unreferenced group or the remapped index otherwise. var []int16 := 0 := int16(1) if { , := .read(1) if != nil { return nil, nil, 0, } if != 0 { , = .read(3) if != nil { return nil, nil, 0, } += 2 := nTiles(, ) := nTiles(, ) := * , = .decodePix(, , 0, false) if != nil { return nil, nil, 0, } for := 0; < len(); += 4 { := int([])<<8 | int([+1]) if < { = } } // The standard allows for up to 2^16-1 hGroups. // // An input file containing a 1600x900 image can include // and reference every possible group. With maximum-size trees // (a ~12MiB input file), this is >3GiB of allocation. // // libwebp will decode a file containing 2^16-1 hGroups, // but it won't produce one. It encodes at most 2600 hGroups // (MAX_HUFF_IMAGE_SIZE, src/dec/common_dec.h) // Reject any image using more. const = 2600 const int16 = + 1 // must fit in int16 if >= { return nil, nil, 0, errors.New("vp8l: too many Huffman trees") } // If maxHGroupIndex is too large, map indices to contiguous indices // to avoid allocating large slices of unused Huffman trees. // // The definition of "too large" matches the one used in libwebp // (see src/dec/vp8l_dec.c). if >= 1000 || int32() >= { = make([]int16, +1) for := range { [] = -1 } = 0 for := 0; < len(); += 4 { := int([])<<8 | int([+1]) if [] == -1 { [] = ++ } [] = byte([] >> 8) [+1] = byte([]) } } else { = int16( + 1) } } } = make([]hGroup, ) for := range + 1 { var *hGroup if == nil { = &[] } else if [] != -1 { = &[[]] } for , := range alphabetSizes { if == 0 && > 0 { += 1 << } var *hTree if != nil { = &[] } if := .decodeHuffmanTree(, ); != nil { return nil, nil, 0, } } } return , , , nil } const ( nLiteralCodes = 256 nLengthCodes = 24 nDistanceCodes = 40 ) var alphabetSizes = [nHuff]uint32{ nLiteralCodes + nLengthCodes, nLiteralCodes, nLiteralCodes, nLiteralCodes, nDistanceCodes, } // decodePix decodes pixel data, specified in section 5.2.2. func ( *decoder) ( int32, int32, int32, bool) ([]byte, error) { // Decode the color cache parameters. , , := uint32(0), uint32(0), ([]uint32)(nil) , := .read(1) if != nil { return nil, } if != 0 { , = .read(4) if != nil { return nil, } if < 1 || 11 < { return nil, errors.New("vp8l: invalid color cache parameters") } = 32 - = make([]uint32, 1<<) } // Decode the Huffman groups. , , , := .decodeHuffmanGroups(, , , ) if != nil { return nil, } , := int32(0), int32(0) if != 0 { , = 1<<-1, nTiles(, ) } // Decode the pixels. if < 4** { = 4 * * } := make([]byte, 4**, ) , := 0, 0 , := int32(0), int32(0) , := &[0], != 0 for < len() { if { := 4 * (*(>>) + ( >> )) = &[uint32([])<<8|uint32([+1])] } , := [huffGreen].next() if != nil { return nil, } switch { case < nLiteralCodes: // We have a literal pixel. , := [huffRed].next() if != nil { return nil, } , := [huffBlue].next() if != nil { return nil, } , := [huffAlpha].next() if != nil { return nil, } [+0] = uint8() [+1] = uint8() [+2] = uint8() [+3] = uint8() += 4 ++ if == { , = 0, +1 } = != 0 && & == 0 case < nLiteralCodes+nLengthCodes: // We have a LZ77 backwards reference. , := .lz77Param( - nLiteralCodes) if != nil { return nil, } , := [huffDistance].next() if != nil { return nil, } , := .lz77Param() if != nil { return nil, } := distanceMap(, ) := + 4*int() := - 4*int() := - 4*int() if < 0 || len() < || < 0 || len() < { return nil, errors.New("vp8l: invalid LZ77 parameters") } for ; < ; , = +1, +1 { [] = [] } += int32() for >= { , = -, +1 } = != 0 default: // We have a color cache lookup. First, insert previous pixels // into the cache. Note that VP8L assumes ARGB order, but the // Go image.RGBA type is in RGBA order. for ; < ; += 4 { := uint32([+0])<<16 | uint32([+1])<<8 | uint32([+2])<<0 | uint32([+3])<<24 [(*colorCacheMultiplier)>>] = } -= nLiteralCodes + nLengthCodes if int() >= len() { return nil, errors.New("vp8l: invalid color cache index") } := [] [+0] = uint8( >> 16) [+1] = uint8( >> 8) [+2] = uint8( >> 0) [+3] = uint8( >> 24) += 4 ++ if == { , = 0, +1 } = != 0 && & == 0 } } return , nil } // lz77Param returns the next LZ77 parameter: a length or a distance, specified // in section 4.2.2. func ( *decoder) ( uint32) (uint32, error) { if < 4 { return + 1, nil } := ( - 2) >> 1 := (2 + &1) << , := .read() if != nil { return 0, } return + + 1, nil } // decodeHeader decodes the VP8L header from r. func decodeHeader( io.Reader) ( *decoder, int32, int32, error) { , := .(io.ByteReader) if ! { = bufio.NewReader() } = &decoder{r: } , := .read(8) if != nil { return nil, 0, 0, } if != 0x2f { return nil, 0, 0, errors.New("vp8l: invalid header") } , := .read(14) if != nil { return nil, 0, 0, } ++ , := .read(14) if != nil { return nil, 0, 0, } ++ _, = .read(1) // Read and ignore the hasAlpha hint. if != nil { return nil, 0, 0, } , := .read(3) if != nil { return nil, 0, 0, } if != 0 { return nil, 0, 0, errors.New("vp8l: invalid version") } return , int32(), int32(), nil } // DecodeConfig decodes the color model and dimensions of a VP8L image from r. func ( io.Reader) (image.Config, error) { , , , := decodeHeader() if != nil { return image.Config{}, } return image.Config{ ColorModel: color.NRGBAModel, Width: int(), Height: int(), }, nil } // Decode decodes a VP8L image from r. func ( io.Reader) (image.Image, error) { , , , := decodeHeader() if != nil { return nil, } // Decode the transforms. var ( int [nTransformTypes]transform [nTransformTypes]bool = ) for { , := .read(1) if != nil { return nil, } if == 0 { break } var transform , , = .decodeTransform(, ) if != nil { return nil, } if [.transformType] { return nil, errors.New("vp8l: repeated transform") } [.transformType] = true [] = ++ } // Decode the transformed pixels. , := .decodePix(, , 0, true) if != nil { return nil, } // Apply the inverse transformations. for := - 1; >= 0; -- { := &[] = inverseTransforms[.transformType](, , ) } return &image.NRGBA{ Pix: , Stride: 4 * int(), Rect: image.Rect(0, 0, int(), int()), }, nil }