git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

vp8l/transform.go (8.2K)

  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 }