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