1 /*
2  * OpenBOR - http://www.LavaLit.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2011 OpenBOR Team
7  */
8 
9 #include <math.h>
10 #include "filters.h"
11 
12 /* 2X SAI Filter */
13 
14 #define BLUE_MASK565 0x001F001F
15 #define RED_MASK565 0xF800F800
16 #define GREEN_MASK565 0x07E007E0
17 
18 #define BLUE_MASK555 0x001F001F
19 #define RED_MASK555 0x7C007C00
20 #define GREEN_MASK555 0x03E003E0
21 
22 static u32 colorMask = 0xF7DEF7DE;
23 static u32 lowPixelMask = 0x08210821;
24 static u32 qcolorMask = 0xE79CE79C;
25 static u32 qlowpixelMask = 0x18631863;
26 static u32 redblueMask = 0xF81F;
27 static u32 greenMask = 0x7E0;
28 
29 
INTERPOLATE(u32 A,u32 B)30 u32 INTERPOLATE(u32 A, u32 B)
31 {
32 	if(A != B) return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + (A & B & lowPixelMask));
33 	else return A;
34 }
35 
Q_INTERPOLATE(u32 A,u32 B,u32 C,u32 D)36 u32 Q_INTERPOLATE(u32 A, u32 B, u32 C, u32 D)
37 {
38 	register u32 x = ((A & qcolorMask) >> 2) +	((B & qcolorMask) >> 2) + ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2);
39 	register u32 y = (A & qlowpixelMask) +	(B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask);
40 	y = (y >> 2) & qlowpixelMask;
41 	return x + y;
42 }
43 
44 
45 
filter_tv2x(u8 * srcPtr,u32 srcPitch,u8 * deltaPtr,u8 * dstPtr,u32 dstPitch,int width,int height)46 void filter_tv2x(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, int width, int height)
47 {
48 	const u32 nextlineSrc = srcPitch / sizeof(u16);
49 	const u32 nextlineDst = dstPitch / sizeof(u16);
50 	const u16 *p = (u16 *)srcPtr;
51 	u16 *q = (u16 *)dstPtr;
52 
53 	while(height--)
54 	{
55 	    int i = 0, j = 0;
56 		for(; i < width; ++i, j += 2)
57 		{
58 			u16 p1 = *(p + i);
59 		    u32 pi;
60 			pi = (((p1 & redblueMask) * 7) >> 3) & redblueMask;
61 			pi |= (((p1 & greenMask) * 7) >> 3) & greenMask;
62 	        *(q + j) = p1;
63 		    *(q + j + 1) = p1;
64 			*(q + j + nextlineDst) = pi;
65 			*(q + j + nextlineDst + 1) = pi;
66 	  }
67 	  p += nextlineSrc;
68 	  q += nextlineDst << 1;
69 	}
70 }
71 
filter_normal2x(u8 * srcPtr,u32 srcPitch,u8 * deltaPtr,u8 * dstPtr,u32 dstPitch,int width,int height)72 void filter_normal2x(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, int width, int height)
73 {
74 	const u32 nextlineSrc = srcPitch / sizeof(u16);
75 	const u32 nextlineDst = dstPitch / sizeof(u16);
76 	const u16 *p = (u16 *)srcPtr;
77 	u16 *q = (u16 *)dstPtr;
78 
79 	while(height--)
80 	{
81 	    int i = 0, j = 0;
82 		for(; i < width; ++i, j += 2)
83 		{
84 			u16 color = *(p + i);
85 			*(q + j) = color;
86 			*(q + j + 1) = color;
87 			*(q + j + nextlineDst) = color;
88 			*(q + j + nextlineDst + 1) = color;
89 		}
90 		p += nextlineSrc;
91 		q += nextlineDst << 1;
92 	}
93 }
94 
filter_scan50(u8 * srcPtr,u32 srcPitch,u8 * deltaPtr,u8 * dstPtr,u32 dstPitch,int width,int height)95 void filter_scan50(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, int width, int height)
96 {
97 	const u32 nextlineSrc = srcPitch / sizeof(u16);
98 	const u32 nextlineDst = dstPitch / sizeof(u16);
99 	const u16 *p = (u16 *)srcPtr;
100 	u16 *q = (u16 *)dstPtr;
101 
102 	while(height--)
103 	{
104 		int i = 0, j = 0;
105 	    for(; i < width; ++i, j += 2)
106 		{
107 		    u16 p1 = *(p + i);
108 		    u16 p2 = *(p + i + nextlineSrc);
109 	 	    // 0111 1011 1110 1111 == 0x7BEF
110 		    u16 pm = ((p1 + p2) >> 2) & 0x7BEF;
111 		    *(q + j) = p1;
112 	        *(q + j + 1) = p1;
113 			*(q + j + nextlineDst) = pm;
114 			*(q + j + nextlineDst + 1) = pm;
115 		}
116 		p += nextlineSrc;
117 		q += nextlineDst << 1;
118 	}
119 }
120 
filter_scan100(u8 * srcPtr,u32 srcPitch,u8 * deltaPtr,u8 * dstPtr,u32 dstPitch,int width,int height)121 void filter_scan100(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, int width, int height)
122 {
123 	const u32 nextlineSrc = srcPitch / sizeof(u16);
124 	const u32 nextlineDst = dstPitch / sizeof(u16);
125 	const u16 *p = (u16 *)srcPtr;
126 	u16 *q = (u16 *)dstPtr;
127 
128 	while(height--)
129 	{
130 		int i = 0, j = 0;
131 	    for(; i < width; ++i, j += 2)
132 		{
133 			*(q + j) = *(q + j + 1) = *(p + i);
134 	    }
135 		p += nextlineSrc;
136 		q += nextlineDst << 1;
137 	}
138 }
139 
DOT_16(u16 c,int j,int i)140 static u16 DOT_16(u16 c, int j, int i)
141 {
142 	static const u16 dotmatrix[16] = {
143 		0x01E0, 0x0007, 0x3800, 0x0000,
144 		0x39E7, 0x0000, 0x39E7, 0x0000,
145 		0x3800, 0x0000, 0x01E0, 0x0007,
146 	    0x39E7, 0x0000, 0x39E7, 0x0000
147 	};
148 	return c - ((c >> 2) & *(dotmatrix + ((j & 3) << 2) + (i & 3)));
149 }
150 
filter_dotmatrix(u8 * srcPtr,u32 srcPitch,u8 * deltaPtr,u8 * dstPtr,u32 dstPitch,int width,int height)151 void filter_dotmatrix(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, int width, int height)
152 {
153 	const u32 nextlineSrc = srcPitch / sizeof(u16);
154 	const u32 nextlineDst = dstPitch / sizeof(u16);
155 	const u16 *p = (u16 *)srcPtr;
156 	u16 *q = (u16 *)dstPtr;
157 	int i, ii, j, jj;
158 
159 	for(j = 0, jj = 0; j < height; ++j, jj += 2)
160 	{
161 		for(i = 0, ii = 0; i < width; ++i, ii += 2)
162 		{
163 			u16 c = *(p + i);
164 			*(q + ii) = DOT_16(c, jj, ii);
165 			*(q + ii + 1) = DOT_16(c, jj, ii + 1);
166 			*(q + ii + nextlineDst) = DOT_16(c, jj + 1, ii);
167 			*(q + ii + nextlineDst + 1) = DOT_16(c, jj + 1, ii + 1);
168 		}
169 		p += nextlineSrc;
170 		q += nextlineDst << 1;
171 	}
172 }
173 
174 // NEED_OPTIMIZE
MULT(u16 c,float * r,float * g,float * b,float alpha)175 static void MULT(u16 c, float* r, float* g, float* b, float alpha)
176 {
177 	*r += alpha * ((c & RED_MASK565  ) >> 11);
178 	*g += alpha * ((c & GREEN_MASK565) >>  5);
179 	*b += alpha * ((c & BLUE_MASK565 ) >>  0);
180 }
181 
MAKE_RGB565(float r,float g,float b)182 static inline u16 MAKE_RGB565(float r, float g, float b)
183 {
184 	return
185 		((((unsigned char)r) << 11) & RED_MASK565  ) |
186 		((((unsigned char)g) <<  5) & GREEN_MASK565) |
187 		((((unsigned char)b) <<  0) & BLUE_MASK565 );
188 }
189 
CUBIC_WEIGHT(float x)190 float CUBIC_WEIGHT(float x)
191 {
192 	// P(x) = { x, x>0 | 0, x<=0 }
193 	// P(x + 2) ^ 3 - 4 * P(x + 1) ^ 3 + 6 * P(x) ^ 3 - 4 * P(x - 1) ^ 3
194 	double r = 0.;
195 	if(x + 2 > 0) r +=      pow(x + 2, 3);
196 	if(x + 1 > 0) r += -4 * pow(x + 1, 3);
197 	if(x     > 0) r +=  6 * pow(x    , 3);
198 	if(x - 1 > 0) r += -4 * pow(x - 1, 3);
199 	return (float)r / 6;
200 }
201 
filter_bicubic(u8 * srcPtr,u32 srcPitch,u8 * deltaPtr,u8 * dstPtr,u32 dstPitch,int width,int height)202 void filter_bicubic(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch, int width, int height)
203 {
204 	const u32 nextlineSrc = srcPitch / sizeof(u16);
205 	const u32 nextlineDst = dstPitch / sizeof(u16);
206 	const u16 *p = (u16 *)srcPtr;
207 	u16 *q = (u16 *)dstPtr;
208 	int dx = width << 1, dy = height << 1;
209 	float fsx = (float)width / dx;
210 	float fsy = (float)height / dy;
211 	float v = 0.0f;
212 	int j = 0;
213 
214 	for(; j < dy; ++j)
215 	{
216 		float u = 0.0f;
217 		int iv = (int)v;
218 		float decy = v - iv;
219 		int i = 0;
220 
221 		for(; i < dx; ++i)
222 		{
223 			int iu = (int)u;
224 			float decx = u - iu;
225 			float r, g, b;
226 			int m;
227 			r = g = b = 0.;
228 
229 			for(m = -1; m <= 2; ++m)
230 			{
231 				float r1 = CUBIC_WEIGHT(decy - m);
232 				int n;
233 
234 				for(n = -1; n <= 2; ++n)
235 				{
236 					float r2 = CUBIC_WEIGHT(n - decx);
237 					const u16* pIn = p + (iu  + n) + (iv + m) * nextlineSrc;
238 					MULT(*pIn, &r, &g, &b, r1 * r2);
239 				}
240 			}
241 			*(q + i) = MAKE_RGB565(r, g, b);
242 			u += fsx;
243 		}
244 	    q += nextlineDst;
245 		v += fsy;
246 	}
247 }
248