// 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// This file deals with image transforms, specified in section 3.// nTiles returns the number of tiles needed to cover size pixels, where each// tile's side is 1<<bits pixels long.func nTiles( int32, uint32) int32 {return ( + 1<< - 1) >> }const ( transformTypePredictor = 0 transformTypeCrossColor = 1 transformTypeSubtractGreen = 2 transformTypeColorIndexing = 3 nTransformTypes = 4)// transform holds the parameters for an invertible transform.type transform struct {// transformType is the type of the transform. transformType uint32// oldWidth is the width of the image before transformation (or // equivalently, after inverse transformation). The color-indexing // transform can reduce the width. For example, a 50-pixel-wide // image that only needs 4 bits (half a byte) per color index can // be transformed into a 25-pixel-wide image. oldWidth int32// bits is the log-2 size of the transform's tiles, for the predictor // and cross-color transforms. 8>>bits is the number of bits per // color index, for the color-index transform. bits uint32// pix is the tile values, for the predictor and cross-color // transforms, and the color palette, for the color-index transform. pix []byte}var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{transformTypePredictor: inversePredictor,transformTypeCrossColor: inverseCrossColor,transformTypeSubtractGreen: inverseSubtractGreen,transformTypeColorIndexing: inverseColorIndexing,}func inversePredictor( *transform, []byte, int32) []byte {if .oldWidth == 0 || == 0 {return }// The first pixel's predictor is mode 0 (opaque black). [3] += 0xff , := int32(4), int32(1)<<.bits-1for := int32(1); < .oldWidth; ++ {// The rest of the first row's predictor is mode 1 (L). [+0] += [-4] [+1] += [-3] [+2] += [-2] [+3] += [-1] += 4 } , := 0, nTiles(.oldWidth, .bits)for := int32(1); < ; ++ {// The first column's predictor is mode 2 (T). [+0] += [+0] [+1] += [+1] [+2] += [+2] [+3] += [+3] , = +4, +4 := 4 * ( >> .bits) * := .pix[+1] & 0x0f += 4for := int32(1); < .oldWidth; ++ {if & == 0 { = .pix[+1] & 0x0f += 4 }switch {case0: // Opaque black. [+3] += 0xffcase1: // L. [+0] += [-4] [+1] += [-3] [+2] += [-2] [+3] += [-1]case2: // T. [+0] += [+0] [+1] += [+1] [+2] += [+2] [+3] += [+3]case3: // TR. [+0] += [+4] [+1] += [+5] [+2] += [+6] [+3] += [+7]case4: // TL. [+0] += [-4] [+1] += [-3] [+2] += [-2] [+3] += [-1]case5: // Average2(Average2(L, TR), T). [+0] += avg2(avg2([-4], [+4]), [+0]) [+1] += avg2(avg2([-3], [+5]), [+1]) [+2] += avg2(avg2([-2], [+6]), [+2]) [+3] += avg2(avg2([-1], [+7]), [+3])case6: // Average2(L, TL). [+0] += avg2([-4], [-4]) [+1] += avg2([-3], [-3]) [+2] += avg2([-2], [-2]) [+3] += avg2([-1], [-1])case7: // Average2(L, T). [+0] += avg2([-4], [+0]) [+1] += avg2([-3], [+1]) [+2] += avg2([-2], [+2]) [+3] += avg2([-1], [+3])case8: // Average2(TL, T). [+0] += avg2([-4], [+0]) [+1] += avg2([-3], [+1]) [+2] += avg2([-2], [+2]) [+3] += avg2([-1], [+3])case9: // Average2(T, TR). [+0] += avg2([+0], [+4]) [+1] += avg2([+1], [+5]) [+2] += avg2([+2], [+6]) [+3] += avg2([+3], [+7])case10: // Average2(Average2(L, TL), Average2(T, TR)). [+0] += avg2(avg2([-4], [-4]), avg2([+0], [+4])) [+1] += avg2(avg2([-3], [-3]), avg2([+1], [+5])) [+2] += avg2(avg2([-2], [-2]), avg2([+2], [+6])) [+3] += avg2(avg2([-1], [-1]), avg2([+3], [+7]))case11: // Select(L, T, TL). := int32([-4]) := int32([-3]) := int32([-2]) := int32([-1]) := int32([-4]) := int32([-3]) := int32([-2]) := int32([-1]) := int32([+0]) := int32([+1]) := int32([+2]) := int32([+3]) := abs(-) + abs(-) + abs(-) + abs(-) := abs(-) + abs(-) + abs(-) + abs(-)if < { [+0] += uint8() [+1] += uint8() [+2] += uint8() [+3] += uint8() } else { [+0] += uint8() [+1] += uint8() [+2] += uint8() [+3] += uint8() }case12: // ClampAddSubtractFull(L, T, TL). [+0] += clampAddSubtractFull([-4], [+0], [-4]) [+1] += clampAddSubtractFull([-3], [+1], [-3]) [+2] += clampAddSubtractFull([-2], [+2], [-2]) [+3] += clampAddSubtractFull([-1], [+3], [-1])case13: // ClampAddSubtractHalf(Average2(L, T), TL). [+0] += clampAddSubtractHalf(avg2([-4], [+0]), [-4]) [+1] += clampAddSubtractHalf(avg2([-3], [+1]), [-3]) [+2] += clampAddSubtractHalf(avg2([-2], [+2]), [-2]) [+3] += clampAddSubtractHalf(avg2([-1], [+3]), [-1]) } , = +4, +4 } }return}func inverseCrossColor( *transform, []byte, int32) []byte {var , , int32 , , := int32(0), int32(1)<<.bits-1, nTiles(.oldWidth, .bits)for := int32(0); < ; ++ { := 4 * ( >> .bits) * for := int32(0); < .oldWidth; ++ {if & == 0 { = int32(int8(.pix[+0])) = int32(int8(.pix[+1])) = int32(int8(.pix[+2])) += 4 } := [+0] := [+1] := [+2] += uint8(uint32(*int32(int8())) >> 5) += uint8(uint32(*int32(int8())) >> 5) += uint8(uint32(*int32(int8())) >> 5) [+0] = [+2] = += 4 } }return}func inverseSubtractGreen( *transform, []byte, int32) []byte {for := 0; < len(); += 4 { := [+1] [+0] += [+2] += }return}func inverseColorIndexing( *transform, []byte, int32) []byte {if .bits == 0 {for := 0; < len(); += 4 { := 4 * uint32([+1]) [+0] = .pix[+0] [+1] = .pix[+1] [+2] = .pix[+2] [+3] = .pix[+3] }return } , , := uint32(0), int32(0), uint32(8>>.bits)switch .bits {case1: , = 0x0f, 0x01case2: , = 0x03, 0x03case3: , = 0x01, 0x07 } , , , := 0, 0, uint32(0), make([]byte, 4*.oldWidth*)for := int32(0); < ; ++ {for := int32(0); < .oldWidth; ++ {if & == 0 { = uint32([+1]) += 4 } := 4 * ( & ) [+0] = .pix[+0] [+1] = .pix[+1] [+2] = .pix[+2] [+3] = .pix[+3] += 4 >>= } }return}func abs( int32) int32 {if < 0 {return - }return}func avg2(, uint8) uint8 {returnuint8((int32() + int32()) / 2)}func clampAddSubtractFull(, , uint8) uint8 { := int32() + int32() - int32()if < 0 {return0 }if > 255 {return255 }returnuint8()}func clampAddSubtractHalf(, uint8) uint8 { := int32() + (int32()-int32())/2if < 0 {return0 }if > 255 {return255 }returnuint8()}
The pages are generated with Goldsv0.8.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.