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