twitchapon-anim

Basic Twitchapon Receiver/Visuals
git clone git://bsandro.tech/twitchapon-anim
Log | Files | Refs | README | LICENSE

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 }