1 /*
2  * This file is part of the Advance project.
3  *
4  * Copyright (C) 2003 Andrea Mazzoleni
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * In addition, as a special exception, Andrea Mazzoleni
21  * gives permission to link the code of this program with
22  * the MAME library (or with modified versions of MAME that use the
23  * same license as MAME), and distribute linked combinations including
24  * the two.  You must obey the GNU General Public License in all
25  * respects for all of the code used other than MAME.  If you modify
26  * this file, you may extend this exception to your version of the
27  * file, but you are not obligated to do so.  If you do not wish to
28  * do so, delete this exception statement from your version.
29  */
30 
31 #include "interp.h"
32 
33 unsigned interp_mask[2];
34 unsigned interp_bits_per_pixel;
35 
36 /***************************************************************************/
37 /* HQ2xS C implementation */
38 
39 /*
40  * This effect is derived from the hq2x effect made by Maxim Stepin
41  */
42 
hq2xS_16_def(u16 * dst0,u16 * dst1,const u16 * src0,const u16 * src1,const u16 * src2,unsigned count)43 static void hq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count)
44 {
45   unsigned i;
46 
47   for(i=0;i<count;++i) {
48     unsigned char mask;
49 
50     u16 c[9];
51 
52     c[1] = src0[0];
53     c[4] = src1[0];
54     c[7] = src2[0];
55 
56     c[0] = src0[-1];
57     c[3] = src1[-1];
58     c[6] = src2[-1];
59 
60     c[2] = src0[1];
61     c[5] = src1[1];
62     c[8] = src2[1];
63 
64 	mask = 0;
65 
66 	// hq2xS dynamic edge detection:
67 	// simply comparing the center color against its surroundings will give bad results in many cases,
68 	// so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
69 	int brightArray[9];
70 	int maxBright = 0, minBright = 999999;
71 	for(int j = 0 ; j < 9 ; j++)
72 	{
73 		int r,g,b;
74 		if (interp_bits_per_pixel == 16) {
75 			b = (int)((c[j] & 0x1F)) << 3;
76 			g = (int)((c[j] & 0x7E0)) >> 3;
77 			r = (int)((c[j] & 0xF800)) >> 8;
78 		} else {
79 			b = (int)((c[j] & 0x1F)) << 3;
80 			g = (int)((c[j] & 0x3E0)) >> 2;
81 			r = (int)((c[j] & 0x7C00)) >> 7;
82 		}
83 		const int bright = r+r+r + g+g+g + b+b;
84 		if(bright > maxBright) maxBright = bright;
85 		if(bright < minBright) minBright = bright;
86 
87 		brightArray[j] = bright;
88 	}
89 	int diffBright = ((maxBright - minBright) * 7) >> 4;
90 	if(diffBright > 7)
91 	{
92 		#define ABS(x) ((x) < 0 ? -(x) : (x))
93 
94 		const int centerBright = brightArray[4];
95 		if(ABS(brightArray[0] - centerBright) > diffBright)
96 			mask |= 1 << 0;
97 		if(ABS(brightArray[1] - centerBright) > diffBright)
98 			mask |= 1 << 1;
99 		if(ABS(brightArray[2] - centerBright) > diffBright)
100 			mask |= 1 << 2;
101 		if(ABS(brightArray[3] - centerBright) > diffBright)
102 			mask |= 1 << 3;
103 		if(ABS(brightArray[5] - centerBright) > diffBright)
104 			mask |= 1 << 4;
105 		if(ABS(brightArray[6] - centerBright) > diffBright)
106 			mask |= 1 << 5;
107 		if(ABS(brightArray[7] - centerBright) > diffBright)
108 			mask |= 1 << 6;
109 		if(ABS(brightArray[8] - centerBright) > diffBright)
110 			mask |= 1 << 7;
111 	}
112 
113 #define P0 dst0[0]
114 #define P1 dst0[1]
115 #define P2 dst1[0]
116 #define P3 dst1[1]
117 #define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right
118 #define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right
119 #define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left
120 #define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left
121 #define IC(p0) c[p0]
122 #define I11(p0,p1) interp_16_11(c[p0], c[p1])
123 #define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2])
124 #define I31(p0,p1) interp_16_31(c[p0], c[p1])
125 #define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2])
126 #define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2])
127 #define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2])
128 #define I53(p0,p1) interp_16_53(c[p0], c[p1])
129 #define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2])
130 #define I71(p0,p1) interp_16_71(c[p0], c[p1])
131 #define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2])
132 #define I97(p0,p1) interp_16_97(c[p0], c[p1])
133 #define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2])
134 #define I151(p0,p1) interp_16_151(c[p0], c[p1])
135 
136     switch (mask) {
137 #include "hq2xs.h"
138     }
139 
140 #undef P0
141 #undef P1
142 #undef P2
143 #undef P3
144 #undef MUR
145 #undef MDR
146 #undef MDL
147 #undef MUL
148 #undef IC
149 #undef I11
150 #undef I211
151 #undef I31
152 #undef I332
153 #undef I431
154 #undef I521
155 #undef I53
156 #undef I611
157 #undef I71
158 #undef I772
159 #undef I97
160 #undef I1411
161 #undef I151
162 
163     src0 += 1;
164     src1 += 1;
165     src2 += 1;
166     dst0 += 2;
167     dst1 += 2;
168   }
169 }
170 
hq2xS_32_def(u32 * dst0,u32 * dst1,const u32 * src0,const u32 * src1,const u32 * src2,unsigned count)171 static void hq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count)
172 {
173   unsigned i;
174 
175   for(i=0;i<count;++i) {
176     unsigned char mask;
177 
178     u32 c[9];
179 
180     c[1] = src0[0];
181     c[4] = src1[0];
182     c[7] = src2[0];
183 
184     c[0] = src0[-1];
185     c[3] = src1[-1];
186     c[6] = src2[-1];
187 
188     c[2] = src0[1];
189     c[5] = src1[1];
190     c[8] = src2[1];
191 
192 	mask = 0;
193 
194 	// hq2xS dynamic edge detection:
195 	// simply comparing the center color against its surroundings will give bad results in many cases,
196 	// so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
197 	int brightArray[9];
198 	int maxBright = 0, minBright = 999999;
199 	for(int j = 0 ; j < 9 ; j++)
200 	{
201 		const int b = (int)((c[j] & 0xF8));
202 		const int g = (int)((c[j] & 0xF800)) >> 8;
203 		const int r = (int)((c[j] & 0xF80000)) >> 16;
204 		const int bright = r+r+r + g+g+g + b+b;
205 		if(bright > maxBright) maxBright = bright;
206 		if(bright < minBright) minBright = bright;
207 
208 		brightArray[j] = bright;
209 	}
210 	int diffBright = ((maxBright - minBright) * 7) >> 4;
211 	if(diffBright > 7)
212 	{
213 		#define ABS(x) ((x) < 0 ? -(x) : (x))
214 
215 		const int centerBright = brightArray[4];
216 		if(ABS(brightArray[0] - centerBright) > diffBright)
217 			mask |= 1 << 0;
218 		if(ABS(brightArray[1] - centerBright) > diffBright)
219 			mask |= 1 << 1;
220 		if(ABS(brightArray[2] - centerBright) > diffBright)
221 			mask |= 1 << 2;
222 		if(ABS(brightArray[3] - centerBright) > diffBright)
223 			mask |= 1 << 3;
224 		if(ABS(brightArray[5] - centerBright) > diffBright)
225 			mask |= 1 << 4;
226 		if(ABS(brightArray[6] - centerBright) > diffBright)
227 			mask |= 1 << 5;
228 		if(ABS(brightArray[7] - centerBright) > diffBright)
229 			mask |= 1 << 6;
230 		if(ABS(brightArray[8] - centerBright) > diffBright)
231 			mask |= 1 << 7;
232 	}
233 
234 #define P0 dst0[0]
235 #define P1 dst0[1]
236 #define P2 dst1[0]
237 #define P3 dst1[1]
238 #define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right
239 #define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right
240 #define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left
241 #define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left
242 #define IC(p0) c[p0]
243 #define I11(p0,p1) interp_32_11(c[p0], c[p1])
244 #define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2])
245 #define I31(p0,p1) interp_32_31(c[p0], c[p1])
246 #define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2])
247 #define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2])
248 #define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2])
249 #define I53(p0,p1) interp_32_53(c[p0], c[p1])
250 #define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2])
251 #define I71(p0,p1) interp_32_71(c[p0], c[p1])
252 #define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2])
253 #define I97(p0,p1) interp_32_97(c[p0], c[p1])
254 #define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2])
255 #define I151(p0,p1) interp_32_151(c[p0], c[p1])
256 
257     switch (mask) {
258 #include "hq2xs.h"
259     }
260 
261 #undef P0
262 #undef P1
263 #undef P2
264 #undef P3
265 #undef MUR
266 #undef MDR
267 #undef MDL
268 #undef MUL
269 #undef IC
270 #undef I11
271 #undef I211
272 #undef I31
273 #undef I332
274 #undef I431
275 #undef I521
276 #undef I53
277 #undef I611
278 #undef I71
279 #undef I772
280 #undef I97
281 #undef I1411
282 #undef I151
283 
284     src0 += 1;
285     src1 += 1;
286     src2 += 1;
287     dst0 += 2;
288     dst1 += 2;
289   }
290 }
291 
hq2xS(u8 * srcPtr,u32 srcPitch,u8 *,u8 * dstPtr,u32 dstPitch,int width,int height)292 void hq2xS(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
293           u8 *dstPtr, u32 dstPitch, int width, int height)
294 {
295   u16 *dst0 = (u16 *)dstPtr;
296   u16 *dst1 = dst0 + (dstPitch >> 1);
297 
298   u16 *src0 = (u16 *)srcPtr;
299   u16 *src1 = src0 + (srcPitch >> 1);
300   u16 *src2 = src1 + (srcPitch >> 1);
301 
302   hq2xS_16_def(dst0, dst1, src0, src0, src1, width);
303 
304   int count = height;
305 
306   count -= 2;
307   while(count) {
308     dst0 += dstPitch;
309     dst1 += dstPitch;
310     hq2xS_16_def(dst0, dst1, src0, src1, src2, width);
311     src0 = src1;
312     src1 = src2;
313     src2 += srcPitch >> 1;
314     --count;
315   }
316   dst0 += dstPitch;
317   dst1 += dstPitch;
318   hq2xS_16_def(dst0, dst1, src0, src1, src1, width);
319 }
320 
hq2xS32(u8 * srcPtr,u32 srcPitch,u8 *,u8 * dstPtr,u32 dstPitch,int width,int height)321 void hq2xS32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
322             u8 *dstPtr, u32 dstPitch, int width, int height)
323 {
324   u32 *dst0 = (u32 *)dstPtr;
325   u32 *dst1 = dst0 + (dstPitch >> 2);
326 
327   u32 *src0 = (u32 *)srcPtr;
328   u32 *src1 = src0 + (srcPitch >> 2);
329   u32 *src2 = src1 + (srcPitch >> 2);
330   hq2xS_32_def(dst0, dst1, src0, src0, src1, width);
331 
332   int count = height;
333 
334   count -= 2;
335   while(count) {
336     dst0 += dstPitch >> 1;
337     dst1 += dstPitch >> 1;
338     hq2xS_32_def(dst0, dst1, src0, src1, src2, width);
339     src0 = src1;
340     src1 = src2;
341     src2 += srcPitch >> 2;
342     --count;
343   }
344   dst0 += dstPitch >> 1;
345   dst1 += dstPitch >> 1;
346   hq2xS_32_def(dst0, dst1, src0, src1, src1, width);
347 }
348 
hq2xS_init(unsigned bits_per_pixel)349 void hq2xS_init(unsigned bits_per_pixel)
350 {
351   interp_set(bits_per_pixel);
352 }
353