transform.go (8445B)
1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package vp8l 6 7 // This file deals with image transforms, specified in section 3. 8 9 // nTiles returns the number of tiles needed to cover size pixels, where each 10 // tile's side is 1<<bits pixels long. 11 func nTiles(size int32, bits uint32) int32 { 12 return (size + 1<<bits - 1) >> bits 13 } 14 15 const ( 16 transformTypePredictor = 0 17 transformTypeCrossColor = 1 18 transformTypeSubtractGreen = 2 19 transformTypeColorIndexing = 3 20 nTransformTypes = 4 21 ) 22 23 // transform holds the parameters for an invertible transform. 24 type transform struct { 25 // transformType is the type of the transform. 26 transformType uint32 27 // oldWidth is the width of the image before transformation (or 28 // equivalently, after inverse transformation). The color-indexing 29 // transform can reduce the width. For example, a 50-pixel-wide 30 // image that only needs 4 bits (half a byte) per color index can 31 // be transformed into a 25-pixel-wide image. 32 oldWidth int32 33 // bits is the log-2 size of the transform's tiles, for the predictor 34 // and cross-color transforms. 8>>bits is the number of bits per 35 // color index, for the color-index transform. 36 bits uint32 37 // pix is the tile values, for the predictor and cross-color 38 // transforms, and the color palette, for the color-index transform. 39 pix []byte 40 } 41 42 var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{ 43 transformTypePredictor: inversePredictor, 44 transformTypeCrossColor: inverseCrossColor, 45 transformTypeSubtractGreen: inverseSubtractGreen, 46 transformTypeColorIndexing: inverseColorIndexing, 47 } 48 49 func inversePredictor(t *transform, pix []byte, h int32) []byte { 50 if t.oldWidth == 0 || h == 0 { 51 return pix 52 } 53 // The first pixel's predictor is mode 0 (opaque black). 54 pix[3] += 0xff 55 p, mask := int32(4), int32(1)<<t.bits-1 56 for x := int32(1); x < t.oldWidth; x++ { 57 // The rest of the first row's predictor is mode 1 (L). 58 pix[p+0] += pix[p-4] 59 pix[p+1] += pix[p-3] 60 pix[p+2] += pix[p-2] 61 pix[p+3] += pix[p-1] 62 p += 4 63 } 64 top, tilesPerRow := 0, nTiles(t.oldWidth, t.bits) 65 for y := int32(1); y < h; y++ { 66 // The first column's predictor is mode 2 (T). 67 pix[p+0] += pix[top+0] 68 pix[p+1] += pix[top+1] 69 pix[p+2] += pix[top+2] 70 pix[p+3] += pix[top+3] 71 p, top = p+4, top+4 72 73 q := 4 * (y >> t.bits) * tilesPerRow 74 predictorMode := t.pix[q+1] & 0x0f 75 q += 4 76 for x := int32(1); x < t.oldWidth; x++ { 77 if x&mask == 0 { 78 predictorMode = t.pix[q+1] & 0x0f 79 q += 4 80 } 81 switch predictorMode { 82 case 0: // Opaque black. 83 pix[p+3] += 0xff 84 85 case 1: // L. 86 pix[p+0] += pix[p-4] 87 pix[p+1] += pix[p-3] 88 pix[p+2] += pix[p-2] 89 pix[p+3] += pix[p-1] 90 91 case 2: // T. 92 pix[p+0] += pix[top+0] 93 pix[p+1] += pix[top+1] 94 pix[p+2] += pix[top+2] 95 pix[p+3] += pix[top+3] 96 97 case 3: // TR. 98 pix[p+0] += pix[top+4] 99 pix[p+1] += pix[top+5] 100 pix[p+2] += pix[top+6] 101 pix[p+3] += pix[top+7] 102 103 case 4: // TL. 104 pix[p+0] += pix[top-4] 105 pix[p+1] += pix[top-3] 106 pix[p+2] += pix[top-2] 107 pix[p+3] += pix[top-1] 108 109 case 5: // Average2(Average2(L, TR), T). 110 pix[p+0] += avg2(avg2(pix[p-4], pix[top+4]), pix[top+0]) 111 pix[p+1] += avg2(avg2(pix[p-3], pix[top+5]), pix[top+1]) 112 pix[p+2] += avg2(avg2(pix[p-2], pix[top+6]), pix[top+2]) 113 pix[p+3] += avg2(avg2(pix[p-1], pix[top+7]), pix[top+3]) 114 115 case 6: // Average2(L, TL). 116 pix[p+0] += avg2(pix[p-4], pix[top-4]) 117 pix[p+1] += avg2(pix[p-3], pix[top-3]) 118 pix[p+2] += avg2(pix[p-2], pix[top-2]) 119 pix[p+3] += avg2(pix[p-1], pix[top-1]) 120 121 case 7: // Average2(L, T). 122 pix[p+0] += avg2(pix[p-4], pix[top+0]) 123 pix[p+1] += avg2(pix[p-3], pix[top+1]) 124 pix[p+2] += avg2(pix[p-2], pix[top+2]) 125 pix[p+3] += avg2(pix[p-1], pix[top+3]) 126 127 case 8: // Average2(TL, T). 128 pix[p+0] += avg2(pix[top-4], pix[top+0]) 129 pix[p+1] += avg2(pix[top-3], pix[top+1]) 130 pix[p+2] += avg2(pix[top-2], pix[top+2]) 131 pix[p+3] += avg2(pix[top-1], pix[top+3]) 132 133 case 9: // Average2(T, TR). 134 pix[p+0] += avg2(pix[top+0], pix[top+4]) 135 pix[p+1] += avg2(pix[top+1], pix[top+5]) 136 pix[p+2] += avg2(pix[top+2], pix[top+6]) 137 pix[p+3] += avg2(pix[top+3], pix[top+7]) 138 139 case 10: // Average2(Average2(L, TL), Average2(T, TR)). 140 pix[p+0] += avg2(avg2(pix[p-4], pix[top-4]), avg2(pix[top+0], pix[top+4])) 141 pix[p+1] += avg2(avg2(pix[p-3], pix[top-3]), avg2(pix[top+1], pix[top+5])) 142 pix[p+2] += avg2(avg2(pix[p-2], pix[top-2]), avg2(pix[top+2], pix[top+6])) 143 pix[p+3] += avg2(avg2(pix[p-1], pix[top-1]), avg2(pix[top+3], pix[top+7])) 144 145 case 11: // Select(L, T, TL). 146 l0 := int32(pix[p-4]) 147 l1 := int32(pix[p-3]) 148 l2 := int32(pix[p-2]) 149 l3 := int32(pix[p-1]) 150 c0 := int32(pix[top-4]) 151 c1 := int32(pix[top-3]) 152 c2 := int32(pix[top-2]) 153 c3 := int32(pix[top-1]) 154 t0 := int32(pix[top+0]) 155 t1 := int32(pix[top+1]) 156 t2 := int32(pix[top+2]) 157 t3 := int32(pix[top+3]) 158 l := abs(c0-t0) + abs(c1-t1) + abs(c2-t2) + abs(c3-t3) 159 t := abs(c0-l0) + abs(c1-l1) + abs(c2-l2) + abs(c3-l3) 160 if l < t { 161 pix[p+0] += uint8(l0) 162 pix[p+1] += uint8(l1) 163 pix[p+2] += uint8(l2) 164 pix[p+3] += uint8(l3) 165 } else { 166 pix[p+0] += uint8(t0) 167 pix[p+1] += uint8(t1) 168 pix[p+2] += uint8(t2) 169 pix[p+3] += uint8(t3) 170 } 171 172 case 12: // ClampAddSubtractFull(L, T, TL). 173 pix[p+0] += clampAddSubtractFull(pix[p-4], pix[top+0], pix[top-4]) 174 pix[p+1] += clampAddSubtractFull(pix[p-3], pix[top+1], pix[top-3]) 175 pix[p+2] += clampAddSubtractFull(pix[p-2], pix[top+2], pix[top-2]) 176 pix[p+3] += clampAddSubtractFull(pix[p-1], pix[top+3], pix[top-1]) 177 178 case 13: // ClampAddSubtractHalf(Average2(L, T), TL). 179 pix[p+0] += clampAddSubtractHalf(avg2(pix[p-4], pix[top+0]), pix[top-4]) 180 pix[p+1] += clampAddSubtractHalf(avg2(pix[p-3], pix[top+1]), pix[top-3]) 181 pix[p+2] += clampAddSubtractHalf(avg2(pix[p-2], pix[top+2]), pix[top-2]) 182 pix[p+3] += clampAddSubtractHalf(avg2(pix[p-1], pix[top+3]), pix[top-1]) 183 } 184 p, top = p+4, top+4 185 } 186 } 187 return pix 188 } 189 190 func inverseCrossColor(t *transform, pix []byte, h int32) []byte { 191 var greenToRed, greenToBlue, redToBlue int32 192 p, mask, tilesPerRow := int32(0), int32(1)<<t.bits-1, nTiles(t.oldWidth, t.bits) 193 for y := int32(0); y < h; y++ { 194 q := 4 * (y >> t.bits) * tilesPerRow 195 for x := int32(0); x < t.oldWidth; x++ { 196 if x&mask == 0 { 197 redToBlue = int32(int8(t.pix[q+0])) 198 greenToBlue = int32(int8(t.pix[q+1])) 199 greenToRed = int32(int8(t.pix[q+2])) 200 q += 4 201 } 202 red := pix[p+0] 203 green := pix[p+1] 204 blue := pix[p+2] 205 red += uint8(uint32(greenToRed*int32(int8(green))) >> 5) 206 blue += uint8(uint32(greenToBlue*int32(int8(green))) >> 5) 207 blue += uint8(uint32(redToBlue*int32(int8(red))) >> 5) 208 pix[p+0] = red 209 pix[p+2] = blue 210 p += 4 211 } 212 } 213 return pix 214 } 215 216 func inverseSubtractGreen(t *transform, pix []byte, h int32) []byte { 217 for p := 0; p < len(pix); p += 4 { 218 green := pix[p+1] 219 pix[p+0] += green 220 pix[p+2] += green 221 } 222 return pix 223 } 224 225 func inverseColorIndexing(t *transform, pix []byte, h int32) []byte { 226 if t.bits == 0 { 227 for p := 0; p < len(pix); p += 4 { 228 i := 4 * uint32(pix[p+1]) 229 pix[p+0] = t.pix[i+0] 230 pix[p+1] = t.pix[i+1] 231 pix[p+2] = t.pix[i+2] 232 pix[p+3] = t.pix[i+3] 233 } 234 return pix 235 } 236 237 vMask, xMask, bitsPerPixel := uint32(0), int32(0), uint32(8>>t.bits) 238 switch t.bits { 239 case 1: 240 vMask, xMask = 0x0f, 0x01 241 case 2: 242 vMask, xMask = 0x03, 0x03 243 case 3: 244 vMask, xMask = 0x01, 0x07 245 } 246 247 d, p, v, dst := 0, 0, uint32(0), make([]byte, 4*t.oldWidth*h) 248 for y := int32(0); y < h; y++ { 249 for x := int32(0); x < t.oldWidth; x++ { 250 if x&xMask == 0 { 251 v = uint32(pix[p+1]) 252 p += 4 253 } 254 255 i := 4 * (v & vMask) 256 dst[d+0] = t.pix[i+0] 257 dst[d+1] = t.pix[i+1] 258 dst[d+2] = t.pix[i+2] 259 dst[d+3] = t.pix[i+3] 260 d += 4 261 262 v >>= bitsPerPixel 263 } 264 } 265 return dst 266 } 267 268 func abs(x int32) int32 { 269 if x < 0 { 270 return -x 271 } 272 return x 273 } 274 275 func avg2(a, b uint8) uint8 { 276 return uint8((int32(a) + int32(b)) / 2) 277 } 278 279 func clampAddSubtractFull(a, b, c uint8) uint8 { 280 x := int32(a) + int32(b) - int32(c) 281 if x < 0 { 282 return 0 283 } 284 if x > 255 { 285 return 255 286 } 287 return uint8(x) 288 } 289 290 func clampAddSubtractHalf(a, b uint8) uint8 { 291 x := int32(a) + (int32(a)-int32(b))/2 292 if x < 0 { 293 return 0 294 } 295 if x > 255 { 296 return 255 297 } 298 return uint8(x) 299 }