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