func()

in vp8l/decode.go [352:487]


func (d *decoder) decodePix(w int32, h int32, minCap int32, topLevel bool) ([]byte, error) {
	// Decode the color cache parameters.
	ccBits, ccShift, ccEntries := uint32(0), uint32(0), ([]uint32)(nil)
	useColorCache, err := d.read(1)
	if err != nil {
		return nil, err
	}
	if useColorCache != 0 {
		ccBits, err = d.read(4)
		if err != nil {
			return nil, err
		}
		if ccBits < 1 || 11 < ccBits {
			return nil, errors.New("vp8l: invalid color cache parameters")
		}
		ccShift = 32 - ccBits
		ccEntries = make([]uint32, 1<<ccBits)
	}

	// Decode the Huffman groups.
	hGroups, hPix, hBits, err := d.decodeHuffmanGroups(w, h, topLevel, ccBits)
	if err != nil {
		return nil, err
	}
	hMask, tilesPerRow := int32(0), int32(0)
	if hBits != 0 {
		hMask, tilesPerRow = 1<<hBits-1, nTiles(w, hBits)
	}

	// Decode the pixels.
	if minCap < 4*w*h {
		minCap = 4 * w * h
	}
	pix := make([]byte, 4*w*h, minCap)
	p, cachedP := 0, 0
	x, y := int32(0), int32(0)
	hg, lookupHG := &hGroups[0], hMask != 0
	for p < len(pix) {
		if lookupHG {
			i := 4 * (tilesPerRow*(y>>hBits) + (x >> hBits))
			hg = &hGroups[uint32(hPix[i])<<8|uint32(hPix[i+1])]
		}

		green, err := hg[huffGreen].next(d)
		if err != nil {
			return nil, err
		}
		switch {
		case green < nLiteralCodes:
			// We have a literal pixel.
			red, err := hg[huffRed].next(d)
			if err != nil {
				return nil, err
			}
			blue, err := hg[huffBlue].next(d)
			if err != nil {
				return nil, err
			}
			alpha, err := hg[huffAlpha].next(d)
			if err != nil {
				return nil, err
			}
			pix[p+0] = uint8(red)
			pix[p+1] = uint8(green)
			pix[p+2] = uint8(blue)
			pix[p+3] = uint8(alpha)
			p += 4

			x++
			if x == w {
				x, y = 0, y+1
			}
			lookupHG = hMask != 0 && x&hMask == 0

		case green < nLiteralCodes+nLengthCodes:
			// We have a LZ77 backwards reference.
			length, err := d.lz77Param(green - nLiteralCodes)
			if err != nil {
				return nil, err
			}
			distSym, err := hg[huffDistance].next(d)
			if err != nil {
				return nil, err
			}
			distCode, err := d.lz77Param(distSym)
			if err != nil {
				return nil, err
			}
			dist := distanceMap(w, distCode)
			pEnd := p + 4*int(length)
			q := p - 4*int(dist)
			qEnd := pEnd - 4*int(dist)
			if p < 0 || len(pix) < pEnd || q < 0 || len(pix) < qEnd {
				return nil, errors.New("vp8l: invalid LZ77 parameters")
			}
			for ; p < pEnd; p, q = p+1, q+1 {
				pix[p] = pix[q]
			}

			x += int32(length)
			for x >= w {
				x, y = x-w, y+1
			}
			lookupHG = hMask != 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 ; cachedP < p; cachedP += 4 {
				argb := uint32(pix[cachedP+0])<<16 |
					uint32(pix[cachedP+1])<<8 |
					uint32(pix[cachedP+2])<<0 |
					uint32(pix[cachedP+3])<<24
				ccEntries[(argb*colorCacheMultiplier)>>ccShift] = argb
			}
			green -= nLiteralCodes + nLengthCodes
			if int(green) >= len(ccEntries) {
				return nil, errors.New("vp8l: invalid color cache index")
			}
			argb := ccEntries[green]
			pix[p+0] = uint8(argb >> 16)
			pix[p+1] = uint8(argb >> 8)
			pix[p+2] = uint8(argb >> 0)
			pix[p+3] = uint8(argb >> 24)
			p += 4

			x++
			if x == w {
				x, y = 0, y+1
			}
			lookupHG = hMask != 0 && x&hMask == 0
		}
	}
	return pix, nil
}