Documentation
¶
Overview ¶
Package vp8enc implements a VP8 (lossy) keyframe encoder for WebP.
All constants in this file are taken directly from RFC 6386 (The VP8 Data Format and Decoding Guide). They are facts about the codec, not original authorship, and are used here as specification constants.
Cross-referenced against the pure-Go decoder at golang.org/x/image/vp8 (BSD-3-Clause) to guarantee bit-exact roundtrip compatibility.
Index ¶
- Constants
- Variables
- func DequantizeBlock(q []int16, coef []int16, dcFactor, acFactor uint16)
- func EncodeFrame(w io.Writer, img image.Image, opts EncodeOptions) error
- func EncodeWebP(w io.Writer, img image.Image, opts EncodeOptions) error
- func ExtractAlpha(img image.Image) []byte
- func FDCT4x4(src []int16, dst []int16)
- func FWHT4x4(src []int16, dst []int16)
- func IDCT4x4(src []int16, dst []int16)
- func IWHT4x4(src []int16, dst []int16)
- func PredictI4(dst *[16]byte, mode int, tl byte, top *[8]byte, left *[4]byte)
- func PredictI16(dst *[256]byte, mode int, topRow, leftCol *[16]byte, topLeft byte, ...)
- func PredictUV8(dst *[64]byte, mode int, topRow, leftCol *[8]byte, topLeft byte, ...)
- func QuantizeBlock(coef []int16, qOut []int16, dqOut []int16, dcFactor, acFactor uint16, ...) int
- func QuantizeBlockSplit(coef []int16, qOut []int16, dqOut []int16, dcFactor, acFactor uint16, ...) int
- func SumSquaredError(a, b []byte) int64
- func TrellisTrim(q *[16]int16, dq *[16]int16, acFactor uint16) int
- func WriteCoefBlock(enc *BoolEncoder, coefs *[16]int16, plane, context int, ...) int
- func WriteFilterHeader(e *BoolEncoder, simple bool, level, sharpness int)
- func WriteFilterHeaderOff(e *BoolEncoder)
- func WriteHeaderInit(e *BoolEncoder)
- func WriteLog2NumParts(e *BoolEncoder, log2 int)
- func WriteMBModes(e *BoolEncoder, predY16, predC8 int)
- func WriteMBModesBPred(e *BoolEncoder, modes *[4][4]int, aboveModes *[4]int, leftModes *[4]int, ...)
- func WriteQuantHeader(e *BoolEncoder, baseQ int)
- func WriteRefreshEntropyProbs(e *BoolEncoder)
- func WriteSegmentHeaderOff(e *BoolEncoder)
- func WriteSkipProb(e *BoolEncoder, skipProbOn bool, prob uint8)
- func WriteTokenProbUpdates(e *BoolEncoder)
- type BoolEncoder
- func (e *BoolEncoder) Bytes() []byte
- func (e *BoolEncoder) Finish() []byte
- func (e *BoolEncoder) Len() int
- func (e *BoolEncoder) Reset()
- func (e *BoolEncoder) WriteBit(bit int, prob int)
- func (e *BoolEncoder) WriteFlag(v bool)
- func (e *BoolEncoder) WriteInt(v int32, n int, prob int)
- func (e *BoolEncoder) WriteOptionalInt(v int32, n int, prob int)
- func (e *BoolEncoder) WriteUint(v uint32, n int, prob int)
- type CategoryInfo
- type EncodeOptions
- type Frame
- type Quantizer
Constants ¶
const ( ModeDC = 0 ModeVE = 1 ModeHE = 2 ModeTM = 3 )
Y16 mode enum used by WriteMBModes. The decoder tree is:
readBit(156) -> if 0: readBit(163) -> 0:DC, 1:VE
-> if 1: readBit(128) -> 0:HE, 1:TM
const ( PlaneY1WithY2 = 0 // Y AC coefficients when MB has a Y2 block PlaneY2 = 1 // Y2 DC-plane (16 DC coefficients combined via WHT) PlaneUV = 2 // Chroma PlaneY1SansY2 = 3 // Y coefficients when MB has no Y2 (B_PRED mode) NumPlanes = 4 )
Plane indices (RFC 6386 section 13.3).
const ( NumBands = 8 NumContexts = 3 NumProbs = 11 )
const ( DctEOB = 0 // End of block DctZero = 1 DctVal1 = 2 DctVal2 = 3 DctVal3 = 4 DctVal4 = 5 DctCat1 = 6 // [5..6] DctCat2 = 7 // [7..10] DctCat3 = 8 // [11..18] DctCat4 = 9 // [19..34] DctCat5 = 10 // [35..66] DctCat6 = 11 // [67..2048] NumTokens = 12 )
Token values (RFC 6386 section 13.2).
const ( ModeI4DC = 0 ModeI4TM = 1 ModeI4VE = 2 ModeI4HE = 3 ModeI4RD = 4 ModeI4VR = 5 ModeI4LD = 6 ModeI4VL = 7 ModeI4HD = 8 ModeI4HU = 9 )
I4 mode enum (extends the I16/UV8 Mode* constants). These match the decoder's predDC..predHU values so we can use them as array indices into PredProb.
const ( // VP8 image dimension is stored in 14 bits, so the cap is one less than // VP8L's 16384-pixel cap. MaxDimension = (1 << 14) - 1 )
const NumPredModes = 10
NumPredModes is the number of I4 prediction modes.
const UniformProb = 128
UniformProb is the canonical 50/50 probability used for uncoded bits carried through the boolean coder (RFC 6386 section 7).
Variables ¶
var CoefBands = [16]int{0, 1, 2, 3, 6, 4, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7}
CoefBands maps a coefficient's zigzag position to one of 8 coding bands (RFC 6386 section 13.3). Used as an index into the token probability table.
var CoefFirst = [NumPlanes]int{ PlaneY1WithY2: 1, PlaneY2: 0, PlaneUV: 0, PlaneY1SansY2: 0, }
Block scan order: for coding coefficients, we walk position 0..15 in zigzag order. When a block has a Y2 (DC predicted separately), the Y1 plane starts at zigzag index 1 (i.e. skips DC).
CoefFirst[plane] = starting zigzag index.
var CoefTree = [22]int8{ -DctEOB, 2, -DctZero, 4, -DctVal1, 6, 8, 12, -DctVal2, 10, -DctVal3, -DctVal4, 14, 16, -DctCat1, -DctCat2, 18, 20, -DctCat3, -DctCat4, -DctCat5, -DctCat6, }
Token tree structure (RFC 6386 section 13.2 figure). Each internal node has a probability (from the context tables) and two children. Traversing left on a "0" bit, right on a "1" bit. The encoder walks the tree from the token value back to the root to produce the bit sequence.
Tree layout (-token means leaf with that token value):
root
/ \
EOB node1
/ \
Zero node2
/ \
Val1 node3
/ \
node4 node5
/ \ / \
Val2 Val3 Cat1 node6 ...
var DctCategories = [6]CategoryInfo{ {Base: 5, Bits: []int{159}}, {Base: 7, Bits: []int{165, 145}}, {Base: 11, Bits: []int{173, 148, 140}}, {Base: 19, Bits: []int{176, 155, 140, 135}}, {Base: 35, Bits: []int{180, 157, 141, 134, 130}}, {Base: 67, Bits: []int{254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129}}, }
DctCategories is indexed by (token-DctCat1). Each entry gives the base value of the category and the fixed probability table used to code the magnitude extra bits.
var DefaultTokenProb = [NumPlanes][NumBands][NumContexts][NumProbs]uint8{
{
{
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
},
{
{253, 136, 254, 255, 228, 219, 128, 128, 128, 128, 128},
{189, 129, 242, 255, 227, 213, 255, 219, 128, 128, 128},
{106, 126, 227, 252, 214, 209, 255, 255, 128, 128, 128},
},
{
{1, 98, 248, 255, 236, 226, 255, 255, 128, 128, 128},
{181, 133, 238, 254, 221, 234, 255, 154, 128, 128, 128},
{78, 134, 202, 247, 198, 180, 255, 219, 128, 128, 128},
},
{
{1, 185, 249, 255, 243, 255, 128, 128, 128, 128, 128},
{184, 150, 247, 255, 236, 224, 128, 128, 128, 128, 128},
{77, 110, 216, 255, 236, 230, 128, 128, 128, 128, 128},
},
{
{1, 101, 251, 255, 241, 255, 128, 128, 128, 128, 128},
{170, 139, 241, 252, 236, 209, 255, 255, 128, 128, 128},
{37, 116, 196, 243, 228, 255, 255, 255, 128, 128, 128},
},
{
{1, 204, 254, 255, 245, 255, 128, 128, 128, 128, 128},
{207, 160, 250, 255, 238, 128, 128, 128, 128, 128, 128},
{102, 103, 231, 255, 211, 171, 128, 128, 128, 128, 128},
},
{
{1, 152, 252, 255, 240, 255, 128, 128, 128, 128, 128},
{177, 135, 243, 255, 234, 225, 128, 128, 128, 128, 128},
{80, 129, 211, 255, 194, 224, 128, 128, 128, 128, 128},
},
{
{1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{246, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{255, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
},
},
{
{
{198, 35, 237, 223, 193, 187, 162, 160, 145, 155, 62},
{131, 45, 198, 221, 172, 176, 220, 157, 252, 221, 1},
{68, 47, 146, 208, 149, 167, 221, 162, 255, 223, 128},
},
{
{1, 149, 241, 255, 221, 224, 255, 255, 128, 128, 128},
{184, 141, 234, 253, 222, 220, 255, 199, 128, 128, 128},
{81, 99, 181, 242, 176, 190, 249, 202, 255, 255, 128},
},
{
{1, 129, 232, 253, 214, 197, 242, 196, 255, 255, 128},
{99, 121, 210, 250, 201, 198, 255, 202, 128, 128, 128},
{23, 91, 163, 242, 170, 187, 247, 210, 255, 255, 128},
},
{
{1, 200, 246, 255, 234, 255, 128, 128, 128, 128, 128},
{109, 178, 241, 255, 231, 245, 255, 255, 128, 128, 128},
{44, 130, 201, 253, 205, 192, 255, 255, 128, 128, 128},
},
{
{1, 132, 239, 251, 219, 209, 255, 165, 128, 128, 128},
{94, 136, 225, 251, 218, 190, 255, 255, 128, 128, 128},
{22, 100, 174, 245, 186, 161, 255, 199, 128, 128, 128},
},
{
{1, 182, 249, 255, 232, 235, 128, 128, 128, 128, 128},
{124, 143, 241, 255, 227, 234, 128, 128, 128, 128, 128},
{35, 77, 181, 251, 193, 211, 255, 205, 128, 128, 128},
},
{
{1, 157, 247, 255, 236, 231, 255, 255, 128, 128, 128},
{121, 141, 235, 255, 225, 227, 255, 255, 128, 128, 128},
{45, 99, 188, 251, 195, 217, 255, 224, 128, 128, 128},
},
{
{1, 1, 251, 255, 213, 255, 128, 128, 128, 128, 128},
{203, 1, 248, 255, 255, 128, 128, 128, 128, 128, 128},
{137, 1, 177, 255, 224, 255, 128, 128, 128, 128, 128},
},
},
{
{
{253, 9, 248, 251, 207, 208, 255, 192, 128, 128, 128},
{175, 13, 224, 243, 193, 185, 249, 198, 255, 255, 128},
{73, 17, 171, 221, 161, 179, 236, 167, 255, 234, 128},
},
{
{1, 95, 247, 253, 212, 183, 255, 255, 128, 128, 128},
{239, 90, 244, 250, 211, 209, 255, 255, 128, 128, 128},
{155, 77, 195, 248, 188, 195, 255, 255, 128, 128, 128},
},
{
{1, 24, 239, 251, 218, 219, 255, 205, 128, 128, 128},
{201, 51, 219, 255, 196, 186, 128, 128, 128, 128, 128},
{69, 46, 190, 239, 201, 218, 255, 228, 128, 128, 128},
},
{
{1, 191, 251, 255, 255, 128, 128, 128, 128, 128, 128},
{223, 165, 249, 255, 213, 255, 128, 128, 128, 128, 128},
{141, 124, 248, 255, 255, 128, 128, 128, 128, 128, 128},
},
{
{1, 16, 248, 255, 255, 128, 128, 128, 128, 128, 128},
{190, 36, 230, 255, 236, 255, 128, 128, 128, 128, 128},
{149, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
},
{
{1, 226, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{247, 192, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{240, 128, 255, 128, 128, 128, 128, 128, 128, 128, 128},
},
{
{1, 134, 252, 255, 255, 128, 128, 128, 128, 128, 128},
{213, 62, 250, 255, 255, 128, 128, 128, 128, 128, 128},
{55, 93, 255, 128, 128, 128, 128, 128, 128, 128, 128},
},
{
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
{128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128},
},
},
{
{
{202, 24, 213, 235, 186, 191, 220, 160, 240, 175, 255},
{126, 38, 182, 232, 169, 184, 228, 174, 255, 187, 128},
{61, 46, 138, 219, 151, 178, 240, 170, 255, 216, 128},
},
{
{1, 112, 230, 250, 199, 191, 247, 159, 255, 255, 128},
{166, 109, 228, 252, 211, 215, 255, 174, 128, 128, 128},
{39, 77, 162, 232, 172, 180, 245, 178, 255, 255, 128},
},
{
{1, 52, 220, 246, 198, 199, 249, 220, 255, 255, 128},
{124, 74, 191, 243, 183, 193, 250, 221, 255, 255, 128},
{24, 71, 130, 219, 154, 170, 243, 182, 255, 255, 128},
},
{
{1, 182, 225, 249, 219, 240, 255, 224, 128, 128, 128},
{149, 150, 226, 252, 216, 205, 255, 171, 128, 128, 128},
{28, 108, 170, 242, 183, 194, 254, 223, 255, 255, 128},
},
{
{1, 81, 230, 252, 204, 203, 255, 192, 128, 128, 128},
{123, 102, 209, 247, 188, 196, 255, 233, 128, 128, 128},
{20, 95, 153, 243, 164, 173, 255, 203, 128, 128, 128},
},
{
{1, 222, 248, 255, 216, 213, 128, 128, 128, 128, 128},
{168, 175, 246, 252, 235, 205, 255, 255, 128, 128, 128},
{47, 116, 215, 255, 211, 212, 255, 255, 128, 128, 128},
},
{
{1, 121, 236, 253, 212, 214, 255, 255, 128, 128, 128},
{141, 84, 213, 252, 201, 202, 255, 219, 128, 128, 128},
{42, 80, 160, 240, 162, 185, 255, 205, 128, 128, 128},
},
{
{1, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
{238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128},
},
},
}
DefaultTokenProb is the default probability table used to arithmetic-code DCT/WHT coefficients (RFC 6386 section 13.5). Indexed by [plane][band]context[prob].
var DequantTableAC = [128]uint16{}/* 128 elements not displayed */
var DequantTableDC = [128]uint16{}/* 128 elements not displayed */
DequantTableDC and DequantTableAC are the quantizer lookup tables (RFC 6386 section 14.1). Index is the "quantizer index" in [0, 127].
var PredProb = [NumPredModes][NumPredModes][9]uint8{
{
{231, 120, 48, 89, 115, 113, 120, 152, 112},
{152, 179, 64, 126, 170, 118, 46, 70, 95},
{175, 69, 143, 80, 85, 82, 72, 155, 103},
{56, 58, 10, 171, 218, 189, 17, 13, 152},
{114, 26, 17, 163, 44, 195, 21, 10, 173},
{121, 24, 80, 195, 26, 62, 44, 64, 85},
{144, 71, 10, 38, 171, 213, 144, 34, 26},
{170, 46, 55, 19, 136, 160, 33, 206, 71},
{63, 20, 8, 114, 114, 208, 12, 9, 226},
{81, 40, 11, 96, 182, 84, 29, 16, 36},
},
{
{134, 183, 89, 137, 98, 101, 106, 165, 148},
{72, 187, 100, 130, 157, 111, 32, 75, 80},
{66, 102, 167, 99, 74, 62, 40, 234, 128},
{41, 53, 9, 178, 241, 141, 26, 8, 107},
{74, 43, 26, 146, 73, 166, 49, 23, 157},
{65, 38, 105, 160, 51, 52, 31, 115, 128},
{104, 79, 12, 27, 217, 255, 87, 17, 7},
{87, 68, 71, 44, 114, 51, 15, 186, 23},
{47, 41, 14, 110, 182, 183, 21, 17, 194},
{66, 45, 25, 102, 197, 189, 23, 18, 22},
},
{
{88, 88, 147, 150, 42, 46, 45, 196, 205},
{43, 97, 183, 117, 85, 38, 35, 179, 61},
{39, 53, 200, 87, 26, 21, 43, 232, 171},
{56, 34, 51, 104, 114, 102, 29, 93, 77},
{39, 28, 85, 171, 58, 165, 90, 98, 64},
{34, 22, 116, 206, 23, 34, 43, 166, 73},
{107, 54, 32, 26, 51, 1, 81, 43, 31},
{68, 25, 106, 22, 64, 171, 36, 225, 114},
{34, 19, 21, 102, 132, 188, 16, 76, 124},
{62, 18, 78, 95, 85, 57, 50, 48, 51},
},
{
{193, 101, 35, 159, 215, 111, 89, 46, 111},
{60, 148, 31, 172, 219, 228, 21, 18, 111},
{112, 113, 77, 85, 179, 255, 38, 120, 114},
{40, 42, 1, 196, 245, 209, 10, 25, 109},
{88, 43, 29, 140, 166, 213, 37, 43, 154},
{61, 63, 30, 155, 67, 45, 68, 1, 209},
{100, 80, 8, 43, 154, 1, 51, 26, 71},
{142, 78, 78, 16, 255, 128, 34, 197, 171},
{41, 40, 5, 102, 211, 183, 4, 1, 221},
{51, 50, 17, 168, 209, 192, 23, 25, 82},
},
{
{138, 31, 36, 171, 27, 166, 38, 44, 229},
{67, 87, 58, 169, 82, 115, 26, 59, 179},
{63, 59, 90, 180, 59, 166, 93, 73, 154},
{40, 40, 21, 116, 143, 209, 34, 39, 175},
{47, 15, 16, 183, 34, 223, 49, 45, 183},
{46, 17, 33, 183, 6, 98, 15, 32, 183},
{57, 46, 22, 24, 128, 1, 54, 17, 37},
{65, 32, 73, 115, 28, 128, 23, 128, 205},
{40, 3, 9, 115, 51, 192, 18, 6, 223},
{87, 37, 9, 115, 59, 77, 64, 21, 47},
},
{
{104, 55, 44, 218, 9, 54, 53, 130, 226},
{64, 90, 70, 205, 40, 41, 23, 26, 57},
{54, 57, 112, 184, 5, 41, 38, 166, 213},
{30, 34, 26, 133, 152, 116, 10, 32, 134},
{39, 19, 53, 221, 26, 114, 32, 73, 255},
{31, 9, 65, 234, 2, 15, 1, 118, 73},
{75, 32, 12, 51, 192, 255, 160, 43, 51},
{88, 31, 35, 67, 102, 85, 55, 186, 85},
{56, 21, 23, 111, 59, 205, 45, 37, 192},
{55, 38, 70, 124, 73, 102, 1, 34, 98},
},
{
{125, 98, 42, 88, 104, 85, 117, 175, 82},
{95, 84, 53, 89, 128, 100, 113, 101, 45},
{75, 79, 123, 47, 51, 128, 81, 171, 1},
{57, 17, 5, 71, 102, 57, 53, 41, 49},
{38, 33, 13, 121, 57, 73, 26, 1, 85},
{41, 10, 67, 138, 77, 110, 90, 47, 114},
{115, 21, 2, 10, 102, 255, 166, 23, 6},
{101, 29, 16, 10, 85, 128, 101, 196, 26},
{57, 18, 10, 102, 102, 213, 34, 20, 43},
{117, 20, 15, 36, 163, 128, 68, 1, 26},
},
{
{102, 61, 71, 37, 34, 53, 31, 243, 192},
{69, 60, 71, 38, 73, 119, 28, 222, 37},
{68, 45, 128, 34, 1, 47, 11, 245, 171},
{62, 17, 19, 70, 146, 85, 55, 62, 70},
{37, 43, 37, 154, 100, 163, 85, 160, 1},
{63, 9, 92, 136, 28, 64, 32, 201, 85},
{75, 15, 9, 9, 64, 255, 184, 119, 16},
{86, 6, 28, 5, 64, 255, 25, 248, 1},
{56, 8, 17, 132, 137, 255, 55, 116, 128},
{58, 15, 20, 82, 135, 57, 26, 121, 40},
},
{
{164, 50, 31, 137, 154, 133, 25, 35, 218},
{51, 103, 44, 131, 131, 123, 31, 6, 158},
{86, 40, 64, 135, 148, 224, 45, 183, 128},
{22, 26, 17, 131, 240, 154, 14, 1, 209},
{45, 16, 21, 91, 64, 222, 7, 1, 197},
{56, 21, 39, 155, 60, 138, 23, 102, 213},
{83, 12, 13, 54, 192, 255, 68, 47, 28},
{85, 26, 85, 85, 128, 128, 32, 146, 171},
{18, 11, 7, 63, 144, 171, 4, 4, 246},
{35, 27, 10, 146, 174, 171, 12, 26, 128},
},
{
{190, 80, 35, 99, 180, 80, 126, 54, 45},
{85, 126, 47, 87, 176, 51, 41, 20, 32},
{101, 75, 128, 139, 118, 146, 116, 128, 85},
{56, 41, 15, 176, 236, 85, 37, 9, 62},
{71, 30, 17, 119, 118, 255, 17, 18, 138},
{101, 38, 60, 138, 55, 70, 43, 26, 142},
{146, 36, 19, 30, 171, 255, 97, 27, 20},
{138, 45, 61, 62, 219, 1, 81, 188, 64},
{32, 41, 20, 117, 151, 142, 20, 21, 163},
{112, 19, 12, 61, 195, 128, 48, 4, 24},
},
}
PredProb is the probability table used to tree-code I4 sub-block modes given the modes of the sub-blocks above and to the left (RFC 6386 section 11.5). Indexed [above][left][prob-index 0..8].
var TokenProbUpdateProb = [NumPlanes][NumBands][NumContexts][NumProbs]uint8{
{
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{176, 246, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{223, 241, 252, 255, 255, 255, 255, 255, 255, 255, 255},
{249, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 244, 252, 255, 255, 255, 255, 255, 255, 255, 255},
{234, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 246, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{239, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{251, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{251, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 254, 253, 255, 254, 255, 255, 255, 255, 255, 255},
{250, 255, 254, 255, 254, 255, 255, 255, 255, 255, 255},
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
},
{
{
{217, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{225, 252, 241, 253, 255, 255, 254, 255, 255, 255, 255},
{234, 250, 241, 250, 253, 255, 253, 254, 255, 255, 255},
},
{
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{223, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{238, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 248, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{249, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{247, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
},
{
{
{186, 251, 250, 255, 255, 255, 255, 255, 255, 255, 255},
{234, 251, 244, 254, 255, 255, 255, 255, 255, 255, 255},
{251, 251, 243, 253, 254, 255, 254, 255, 255, 255, 255},
},
{
{255, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{236, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{251, 253, 253, 254, 254, 255, 255, 255, 255, 255, 255},
},
{
{255, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
},
{
{
{248, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{250, 254, 252, 254, 255, 255, 255, 255, 255, 255, 255},
{248, 254, 249, 253, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{246, 253, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{252, 254, 251, 254, 254, 255, 255, 255, 255, 255, 255},
},
{
{255, 254, 252, 255, 255, 255, 255, 255, 255, 255, 255},
{248, 254, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{253, 255, 254, 254, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{245, 251, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{253, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 251, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{249, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255},
{250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
{
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255},
},
},
}
TokenProbUpdateProb is the probability of a token-probability update bit (RFC 6386 section 13.4). The encoder emits 4*8*3*11=1056 arithmetic-coded bits against this table, each indicating whether the corresponding DefaultTokenProb entry is overridden. We currently never override, so every emitted bit is 0; but they must still be emitted or the decoder misaligns.
var VP8Norm = [256]uint8{}/* 256 elements not displayed */
VP8Norm[i] returns the number of left-shifts needed to bring value i into the range [128, 255]. Used during boolean-coder range renormalization. Indexed 0..255; VP8Norm[0] is unused (range can never be zero).
var Zigzag4x4 = [16]int{0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15}
Zigzag4x4 maps DCT zigzag order to raster 4x4 indices (RFC 6386 section 13). IMPORTANT: this is NOT the JPEG zigzag.
Functions ¶
func DequantizeBlock ¶
DequantizeBlock reconstructs coefficients from a quantized block in the zigzag-ordered input `q`. Writes to `coef` in raster 4x4 order. (This is the operation the decoder performs implicitly via the coefficient stream; exposed here for encoder-side reconstruction / RDO.)
func EncodeFrame ¶
EncodeFrame writes a single VP8 keyframe (no RIFF/VP8 chunk wrapper) to w. Callers are responsible for wrapping the output in a VP8 chunk header and a RIFF container when building a full .webp file.
The current encoder implements I16 + UV8 prediction (DC/V/H/TM) with forward DCT + Walsh-Hadamard, deadzone quantization, and token-tree coefficient coding. Mode selection is SSE-based. I4 modes (10 per MB) and rate-distortion optimization are later-phase work.
func EncodeWebP ¶
EncodeWebP wraps EncodeFrame in the RIFF/WEBP/VP8 container format.
func ExtractAlpha ¶
ExtractAlpha returns the 8-bit alpha plane for img, sized exactly (w, h) — no MB padding. Returns nil if the image has no alpha channel or is fully opaque. Used by the ALPH chunk encoder.
func FDCT4x4 ¶
FDCT4x4 performs a forward 4x4 DCT on 16 residual values in src and writes 16 coefficients to dst. Both slices are row-major 4x4 blocks.
This is the libvpx vp8_short_fdct4x4_c form, which pairs exactly with the libvpx IDCT implemented below (and with the decoder at golang.org/x/image/vp8/idct.go).
Known property: because the pass-1 rounding biases (14500, 7500) exceed their >>12 divisor, an all-zero residual produces tiny non-zero outputs in some odd-harmonic positions. These values are smaller than any realistic quantizer and quantize to 0 in practice; encoders rely on the "skip" flag to avoid emitting empty blocks.
Input residual range is [-510, 510] (signed 10-bit). Output fits in int16.
func FWHT4x4 ¶
FWHT4x4 performs the forward Walsh-Hadamard transform on the 16 DC coefficients of an I16 macroblock's Y plane. Input is the 16 DC values (one per 4x4 Y sub-block, in raster order); output is the Y2 block.
func IDCT4x4 ¶
IDCT4x4 performs the inverse 4x4 DCT on 16 coefficients in src, writing 16 reconstructed residuals to dst. Output residuals may overshoot the input range by small amounts and must be clipped to [0, 255] after adding prediction.
func IWHT4x4 ¶
IWHT4x4 performs the inverse WHT on the 16 Y2 coefficients, producing 16 reconstructed Y-DC values in dst.
func PredictI4 ¶
PredictI4 fills dst with the 16 predicted pixels of one 4x4 sub-block for the given mode. Neighbors:
- tl: top-left corner pixel (at y-1, x-1)
- top[0..3]: 4 pixels directly above (at y-1, x..x+3)
- top[4..7]: 4 pixels to the top-right (at y-1, x+4..x+7); for right-column sub-blocks these are the MB-level overhang values (RFC 6386 section 12.2 / x/image/vp8 prepareYBR's column-24..27 fill)
- left[0..3]: 4 pixels along the left column (at y..y+3, x-1)
func PredictI16 ¶
func PredictI16(dst *[256]byte, mode int, topRow, leftCol *[16]byte, topLeft byte, hasTop, hasLeft bool)
PredictI16 fills dst[0..16][0..16] (row-major, stride 16) with the predicted pixels of a 16x16 block, given the reconstructed neighbors:
- topLeft: single pixel at (x-1, y-1)
- topRow: 16 pixels along the top edge at (x..x+15, y-1)
- leftCol: 16 pixels along the left edge at (x-1, y..y+15)
- hasTop, hasLeft indicate whether those neighbors are valid MBs (i.e. mby > 0 for top, mbx > 0 for left). When false, the corresponding side uses the default filler (0x7f for top, 0x81 for left) and DC mode switches to the appropriate variant.
func PredictUV8 ¶
func PredictUV8(dst *[64]byte, mode int, topRow, leftCol *[8]byte, topLeft byte, hasTop, hasLeft bool)
PredictUV8 fills an 8x8 block with predicted chroma values. Semantics match PredictI16 but sized to 8.
func QuantizeBlock ¶
func QuantizeBlock( coef []int16, qOut []int16, dqOut []int16, dcFactor, acFactor uint16, deadzone int32, ) int
QuantizeBlock performs deadzone quantization of 16 coefficients given (dcFactor, acFactor) dequant values and a uniform deadzone bias. It writes the quantized integer coefficients to qOut and the reconstructed (dequantized) coefficients to dqOut. Returns the end-of-block index (1 + position of last non-zero coefficient in zigzag order) or 0 for an all-zero block.
For per-position deadzone tuning (smaller bias on DC, larger on AC), use QuantizeBlockSplit instead.
func QuantizeBlockSplit ¶
func QuantizeBlockSplit( coef []int16, qOut []int16, dqOut []int16, dcFactor, acFactor uint16, dcDeadzone, acDeadzone int32, ) int
QuantizeBlockSplit performs deadzone quantization with separate deadzones for DC (zigzag position 0) and AC (all other positions). Typical use: dcDeadzone=0 (preserve DC accuracy, critical for perceived color and brightness) and acDeadzone=acFactor/4 (zero out small AC noise, saves entropy bits at little perceptual cost).
func SumSquaredError ¶
SumSquaredError returns the sum of squared differences between two equal-length byte slices, reinterpreted as pixel values. Used for mode selection (min-SSE search).
func TrellisTrim ¶
TrellisTrim performs a simple trailing-noise trellis pass on a quantized 4x4 block: examines non-zero coefficients at mid-to-high zigzag positions with magnitude 1 and zeroes them in place. Moving the EOB earlier saves ~3-5 arithmetic-coded bits per coefficient at the cost of a small reconstruction error.
This isn't the full Viterbi trellis (which would track token-context transitions across all 16 positions simultaneously), but captures the common pathology where the last few non-zero coefficients are ±1s that barely survived rounding.
Returns the new EOB (count of coefficients up to and including the last non-zero in zigzag order).
func WriteCoefBlock ¶
func WriteCoefBlock( enc *BoolEncoder, coefs *[16]int16, plane, context int, tokenProb *[NumPlanes][NumBands][NumContexts][NumProbs]uint8, skipFirstCoeff bool, ) int
WriteCoefBlock encodes 16 quantized coefficients (raster order) for one 4x4 block. Returns 1 if the block had any non-zero coefficient, 0 otherwise — matches the decoder's return value, which the caller propagates as the "non-zero" context for subsequent blocks.
coefs is indexed by raster (0..15); the zigzag mapping is applied internally. plane selects the probability plane; context is 0/1/2 from neighbor non-zero counts; tokenProb is the current probability table (we always use DefaultTokenProb, but passed in for future prob-update support). skipFirstCoeff == true for I16 Y1 blocks (DC is in the Y2 block, not this one), starting from zigzag position 1.
func WriteFilterHeader ¶
func WriteFilterHeader(e *BoolEncoder, simple bool, level, sharpness int)
WriteFilterHeader emits the loop-filter header:
simple (1 bit) | level (6 bits) | sharpness (3 bits) | useLFDelta (1 bit)
level=0 disables the filter entirely (RFC 6386 section 15). Otherwise the decoder applies the normal filter (simple=false) or simple filter (simple=true) to the reconstructed frame as a post-processing pass that smooths block boundaries.
func WriteFilterHeaderOff ¶
func WriteFilterHeaderOff(e *BoolEncoder)
WriteFilterHeaderOff is a backward-compatible shortcut for WriteFilterHeader(e, false, 0, 0).
func WriteHeaderInit ¶
func WriteHeaderInit(e *BoolEncoder)
WriteHeaderInit writes the keyframe-only fields at the top of partition 0:
- color_space (1 bit, must be 0)
- clamp_type (1 bit, typically 0 meaning "bicubic clamping")
func WriteLog2NumParts ¶
func WriteLog2NumParts(e *BoolEncoder, log2 int)
WriteLog2NumParts writes the log2 of the number of coefficient partitions (0..3 → 1, 2, 4, 8 partitions).
func WriteMBModes ¶
func WriteMBModes(e *BoolEncoder, predY16, predC8 int)
WriteMBModes writes the per-macroblock mode fields for an I16 MB:
usePredY16 (1 bit at prob 145), predY16, predC8.
Must be called once per MB, after any skip bit, in MB raster order.
func WriteMBModesBPred ¶
func WriteMBModesBPred(e *BoolEncoder, modes *[4][4]int, aboveModes *[4]int, leftModes *[4]int, predC8 int)
WriteMBModesBPred writes the per-macroblock mode fields for a B_PRED MB: usePredY16=0, 16 I4 modes (tree-coded against PredProb[above][left]), then the UV mode.
modes[j][i] is the I4 mode for sub-block at (i, j) in the MB. aboveModes[i] is the mode of the sub-block above sub-block column i
(bottom-row modes of the MB above, or ModeI4DC if on the frame edge).
leftModes is updated in place: on entry, leftModes[j] is the mode of
the sub-block to the left of sub-block row j; on return, leftModes[j] holds the mode of this MB's rightmost sub-block in row j (i.e. the input context for the NEXT MB to the right).
aboveModes is also updated in place to reflect the bottom-row modes of this MB.
func WriteQuantHeader ¶
func WriteQuantHeader(e *BoolEncoder, baseQ int)
WriteQuantHeader emits the quantizer indexer: base Y AC index in 7 bits followed by five optional deltas (Y1 DC, Y2 DC, Y2 AC, UV DC, UV AC). Set all deltas to 0 for simple mode.
func WriteRefreshEntropyProbs ¶
func WriteRefreshEntropyProbs(e *BoolEncoder)
WriteRefreshEntropyProbs emits the single "refresh entropy probs" flag. Keyframe-only. 0 means the next frame does not inherit updated probs (we're still a static image encoder so this is always 0).
func WriteSegmentHeaderOff ¶
func WriteSegmentHeaderOff(e *BoolEncoder)
WriteSegmentHeaderOff emits a "no segmentation" segment header: a single zero bit indicating use_segment is false.
func WriteSkipProb ¶
func WriteSkipProb(e *BoolEncoder, skipProbOn bool, prob uint8)
WriteSkipProb emits mb_no_skip_coeff plus, if true, an 8-bit skip probability. If skipProbOn is true, per-MB skip bits follow; if false, every MB carries full residuals.
func WriteTokenProbUpdates ¶
func WriteTokenProbUpdates(e *BoolEncoder)
WriteTokenProbUpdates emits the 4×8×3×11 = 1056 "should we update this prob?" bits, each coded against TokenProbUpdateProb. We never update, so every emitted bit is 0. The decoder MUST consume exactly this many bits in this exact order.
Types ¶
type BoolEncoder ¶
type BoolEncoder struct {
// contains filtered or unexported fields
}
BoolEncoder is the VP8 boolean arithmetic coder in write (encode) mode.
The algorithm is specified in RFC 6386 section 7 and follows the libvpx reference implementation. The output byte sequence is designed to be decoded by the matching decoder described in section 7.3; we verify this with a round-trip test against a mirror decoder that is bit-compatible with golang.org/x/image/vp8's `partition` type.
Invariants held between calls to WriteBit:
- rng (range) is in [128, 255]
- low holds up to 24 bits of "pending" output
- count tracks bits committed into low but not yet emitted; initial value -24 means we need 24 shift-ins before the first emit.
Carry propagation: when an emitted byte would overflow due to a late addition in low, we propagate a +1 back through any preceding 0xff bytes, turning them into 0x00 and incrementing the first non-0xff byte before the run.
func NewBoolEncoder ¶
func NewBoolEncoder() *BoolEncoder
NewBoolEncoder returns a freshly initialized encoder writing to an internal buffer. Retrieve the output via Bytes after calling Finish.
func (*BoolEncoder) Bytes ¶
func (e *BoolEncoder) Bytes() []byte
Bytes returns the currently encoded bytes without flushing. Only meaningful for diagnostics; call Finish for a decodable stream.
func (*BoolEncoder) Finish ¶
func (e *BoolEncoder) Finish() []byte
Finish flushes any pending bits and returns the encoded byte stream. It emits enough trailing zero bits at prob 128 to drain the internal state, so every previously written bit is recoverable by the decoder.
The returned slice is the encoder's internal buffer; callers that want to retain it across subsequent encodes must copy it.
func (*BoolEncoder) Len ¶
func (e *BoolEncoder) Len() int
Len returns the number of bytes emitted so far.
func (*BoolEncoder) Reset ¶
func (e *BoolEncoder) Reset()
Reset re-initializes the encoder to a fresh state, reusing the backing byte slice's capacity.
func (*BoolEncoder) WriteBit ¶
func (e *BoolEncoder) WriteBit(bit int, prob int)
WriteBit encodes a single bit against the given probability.
prob is an 8-bit probability in [0, 255] where higher values bias toward the "0" branch being taken. 128 is the 50/50 (uniform) probability.
func (*BoolEncoder) WriteFlag ¶
func (e *BoolEncoder) WriteFlag(v bool)
WriteFlag encodes a 1-bit flag against uniform probability (128).
func (*BoolEncoder) WriteInt ¶
func (e *BoolEncoder) WriteInt(v int32, n int, prob int)
WriteInt encodes a signed value as magnitude + sign. Signed values are stored as |v| in n bits followed by a sign bit. Each bit is coded against prob (typically UniformProb).
func (*BoolEncoder) WriteOptionalInt ¶
func (e *BoolEncoder) WriteOptionalInt(v int32, n int, prob int)
WriteOptionalInt encodes a possibly-zero signed value. When v == 0 a single "not present" bit is emitted; otherwise a "present" bit followed by the magnitude+sign encoding.
type CategoryInfo ¶
type CategoryInfo struct {
Base int // base value for this category
Bits []int // probabilities for each extra bit (high bit first)
}
Category extra-bits specifications (RFC 6386 section 13.2).
type EncodeOptions ¶
type EncodeOptions struct {
// Quality maps 0..100 to the VP8 base quantizer index; higher Quality
// → lower QI → finer quantization. Default 75.
Quality float32
// Method is the speed/quality tradeoff; 0 = fastest, 6 = slowest.
// Currently only toggles whether mode search explores all 4 I16/UV8
// modes (>=1) or hard-selects DC (0).
Method int
}
EncodeOptions carries VP8 frame-level tuning that the package-level encoder wrapper translates from gowebp.Options.
type Frame ¶
type Frame struct {
Width, Height int
MBWidth int // ceil(Width/16)
MBHeight int // ceil(Height/16)
Y []byte // YStride * MBHeight*16
Cb []byte // UVStride * MBHeight*8
Cr []byte // UVStride * MBHeight*8
YStride int // == MBWidth*16
UVStride int // == MBWidth*8
}
Frame is a macroblock-aligned YCbCr 4:2:0 image in planar layout.
The display size is (Width, Height) in pixels. The allocated planes are padded up to the next multiple of 16 (luma) or 8 (chroma) so macroblock loops can read uniformly. Edge rows/columns are filled by replicating the last valid pixel, matching libwebp's padding policy.
func NewFrame ¶
NewFrame allocates a Frame with zeroed planes sized for (w, h) display dimensions. The planes are MB-aligned.
func RGBAToFrame ¶
RGBAToFrame converts an image.Image to a macroblock-aligned 4:2:0 YCbCr Frame using BT.601 fixed-point coefficients (matching RFC 6386 and libwebp's picture_csp_enc.c). Padding pixels beyond (Width, Height) replicate the nearest edge pixel.
Alpha is ignored here; ALPH chunk handling is the caller's responsibility.
type Quantizer ¶
type Quantizer struct {
Y1 [2]uint16 // Y AC blocks
Y2 [2]uint16 // Y DC (Walsh) block
UV [2]uint16 // Chroma AC blocks
}
Quantizer bundles the six VP8 dequant factors needed to (de)quantize Y, Y2, and UV blocks. Indices: [0] = DC factor, [1] = AC factor.
func NewQuantizer ¶
NewQuantizer derives dequant factors from a base quantizer index in [0, 127] using the exact lookup + adjustments specified in RFC 6386 section 9.6 (mirrored from x/image/vp8 quant.go).