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
5package 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.
11func nTiles(size int32, bits uint32) int32 {
12	return (size + 1<<bits - 1) >> bits
13}
14
15const (
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.
24type 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
42var inverseTransforms = [nTransformTypes]func(*transform, []byte, int32) []byte{
43	transformTypePredictor:     inversePredictor,
44	transformTypeCrossColor:    inverseCrossColor,
45	transformTypeSubtractGreen: inverseSubtractGreen,
46	transformTypeColorIndexing: inverseColorIndexing,
47}
48
49func 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
190func 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
216func 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
225func 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
268func abs(x int32) int32 {
269	if x < 0 {
270		return -x
271	}
272	return x
273}
274
275func avg2(a, b uint8) uint8 {
276	return uint8((int32(a) + int32(b)) / 2)
277}
278
279func 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
290func 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}
300