98e75f2d |
1 | /* |
2 | Copyright (C) 2003 Rice1964 |
3 | |
4 | This program is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU General Public License |
6 | as published by the Free Software Foundation; either version 2 |
7 | of the License, or (at your option) any later version. |
8 | |
9 | This program is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License |
15 | along with this program; if not, write to the Free Software |
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | |
18 | */ |
19 | |
20 | /* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net> |
21 | * Modified for the Texture Filtering library |
22 | */ |
23 | |
24 | /* 2007 Mudlord - Added hq2xS lq2xS filters */ |
25 | |
26 | #include "TextureFilters.h" |
27 | |
28 | /************************************************************************/ |
29 | /* hq2x filters */ |
30 | /************************************************************************/ |
31 | |
32 | /***************************************************************************/ |
33 | /* Basic types */ |
34 | |
35 | /***************************************************************************/ |
36 | /* interpolation */ |
37 | |
38 | //static unsigned interp_bits_per_pixel; |
39 | |
40 | #if !_16BPP_HACK |
41 | #define INTERP_16_MASK_1_3(v) ((v)&0x0F0F) |
42 | #define INTERP_16_MASK_SHIFT_2_4(v) (((v)&0xF0F0)>>4) |
43 | #define INTERP_16_MASK_SHIFTBACK_2_4(v) ((INTERP_16_MASK_1_3(v))<<4) |
44 | |
45 | static uint16 hq2x_interp_16_521(uint16 p1, uint16 p2, uint16 p3) |
46 | { |
47 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*2 + INTERP_16_MASK_1_3(p3)*1) / 8) |
48 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*2 + INTERP_16_MASK_SHIFT_2_4(p3)*1) / 8); |
49 | } |
50 | |
51 | static uint16 hq2x_interp_16_332(uint16 p1, uint16 p2, uint16 p3) |
52 | { |
53 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)*2) / 8) |
54 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 8); |
55 | } |
56 | |
57 | static uint16 hq2x_interp_16_611(uint16 p1, uint16 p2, uint16 p3) |
58 | { |
59 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*6 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 8) |
60 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*6 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 8); |
61 | } |
62 | |
63 | static uint16 hq2x_interp_16_71(uint16 p1, uint16 p2) |
64 | { |
65 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*7 + INTERP_16_MASK_1_3(p2)) / 8) |
66 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*7 + INTERP_16_MASK_SHIFT_2_4(p2)) / 8); |
67 | } |
68 | |
69 | static uint16 hq2x_interp_16_211(uint16 p1, uint16 p2, uint16 p3) |
70 | { |
71 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*2 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 4) |
72 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*2 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 4); |
73 | } |
74 | |
75 | static uint16 hq2x_interp_16_772(uint16 p1, uint16 p2, uint16 p3) |
76 | { |
77 | return INTERP_16_MASK_1_3(((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2))*7 + INTERP_16_MASK_1_3(p3)*2) / 16) |
78 | | INTERP_16_MASK_SHIFTBACK_2_4(((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2))*7 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 16); |
79 | } |
80 | |
81 | static uint16 hq2x_interp_16_11(uint16 p1, uint16 p2) |
82 | { |
83 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2)) / 2) |
84 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2)) / 2); |
85 | } |
86 | |
87 | static uint16 hq2x_interp_16_31(uint16 p1, uint16 p2) |
88 | { |
89 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)) / 4) |
90 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)) / 4); |
91 | } |
92 | |
93 | static uint16 hq2x_interp_16_1411(uint16 p1, uint16 p2, uint16 p3) |
94 | { |
95 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*14 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 16) |
96 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*14 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 16); |
97 | } |
98 | |
99 | static uint16 hq2x_interp_16_431(uint16 p1, uint16 p2, uint16 p3) |
100 | { |
101 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*4 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)) / 8) |
102 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*4 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)) / 8); |
103 | } |
104 | |
105 | static uint16 hq2x_interp_16_53(uint16 p1, uint16 p2) |
106 | { |
107 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*3) / 8) |
108 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*3) / 8); |
109 | } |
110 | |
111 | static uint16 hq2x_interp_16_151(uint16 p1, uint16 p2) |
112 | { |
113 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*15 + INTERP_16_MASK_1_3(p2)) / 16) |
114 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*15 + INTERP_16_MASK_SHIFT_2_4(p2)) / 16); |
115 | } |
116 | |
117 | static uint16 hq2x_interp_16_97(uint16 p1, uint16 p2) |
118 | { |
119 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*9 + INTERP_16_MASK_1_3(p2)*7) / 16) |
120 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*9 + INTERP_16_MASK_SHIFT_2_4(p2)*7) / 16); |
121 | } |
122 | #endif /* !_16BPP_HACK */ |
123 | |
124 | #define INTERP_32_MASK_1_3(v) ((v)&0x00FF00FF) |
125 | #define INTERP_32_MASK_SHIFT_2_4(v) (((v)&0xFF00FF00)>>8) |
126 | #define INTERP_32_MASK_SHIFTBACK_2_4(v) (((INTERP_32_MASK_1_3(v))<<8)) |
127 | |
128 | static uint32 hq2x_interp_32_521(uint32 p1, uint32 p2, uint32 p3) |
129 | { |
130 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*5 + INTERP_32_MASK_1_3(p2)*2 + INTERP_32_MASK_1_3(p3)*1) / 8) |
131 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*5 + INTERP_32_MASK_SHIFT_2_4(p2)*2 + INTERP_32_MASK_SHIFT_2_4(p3)*1) / 8); |
132 | } |
133 | |
134 | static uint32 hq2x_interp_32_332(uint32 p1, uint32 p2, uint32 p3) |
135 | { |
136 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)*3 + INTERP_32_MASK_1_3(p3)*2) / 8) |
137 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)*3 + INTERP_32_MASK_SHIFT_2_4(p3)*2) / 8); |
138 | } |
139 | |
140 | static uint32 hq2x_interp_32_211(uint32 p1, uint32 p2, uint32 p3) |
141 | { |
142 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*2 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 4) |
143 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*2 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 4); |
144 | } |
145 | |
146 | static uint32 hq2x_interp_32_611(uint32 p1, uint32 p2, uint32 p3) |
147 | { |
148 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*6 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 8) |
149 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*6 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 8); |
150 | } |
151 | |
152 | static uint32 hq2x_interp_32_31(uint32 p1, uint32 p2) |
153 | { |
154 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)) / 4) |
155 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)) / 4); |
156 | } |
157 | |
158 | static uint32 hq2x_interp_32_1411(uint32 p1, uint32 p2, uint32 p3) |
159 | { |
160 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*14 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 16) |
161 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*14 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 16); |
162 | } |
163 | |
164 | /***************************************************************************/ |
165 | /* diff */ |
166 | |
167 | #define INTERP_Y_LIMIT (0x30*4) |
168 | #define INTERP_U_LIMIT (0x07*4) |
169 | #define INTERP_V_LIMIT (0x06*8) |
170 | |
171 | #if !_16BPP_HACK |
172 | static int hq2x_interp_16_diff(uint16 p1, uint16 p2) |
173 | { |
174 | int r, g, b; |
175 | int y, u, v; |
176 | |
177 | if (p1 == p2) |
178 | return 0; |
179 | |
180 | b = (int)((p1 & 0x000F) - (p2 & 0x000F)); |
181 | g = (int)((p1 & 0x00F0) - (p2 & 0x00F0)) >> 4; |
182 | r = (int)((p1 & 0x0F00) - (p2 & 0x0F00)) >> 8; |
183 | |
184 | y = r + g + b; |
185 | u = r - b; |
186 | v = -r + 2*g - b; |
187 | |
188 | if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) |
189 | return 1; |
190 | |
191 | if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) |
192 | return 1; |
193 | |
194 | if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) |
195 | return 1; |
196 | |
197 | return 0; |
198 | } |
199 | #endif /* !_16BPP_HACK */ |
200 | |
201 | static int hq2x_interp_32_diff(uint32 p1, uint32 p2) |
202 | { |
203 | int r, g, b; |
204 | int y, u, v; |
205 | |
206 | if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) |
207 | return 0; |
208 | |
209 | b = (int)((p1 & 0xFF) - (p2 & 0xFF)); |
210 | g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; |
211 | r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; |
212 | |
213 | y = r + g + b; |
214 | u = r - b; |
215 | v = -r + 2*g - b; |
216 | |
217 | if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) |
218 | return 1; |
219 | |
220 | if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) |
221 | return 1; |
222 | |
223 | if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) |
224 | return 1; |
225 | |
226 | return 0; |
227 | } |
228 | |
229 | /*static void interp_set(unsigned bits_per_pixel) |
230 | { |
231 | interp_bits_per_pixel = bits_per_pixel; |
232 | }*/ |
233 | |
234 | #if !_16BPP_HACK |
235 | static void hq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) |
236 | { |
237 | unsigned i; |
238 | |
239 | for(i=0;i<count;++i) { |
240 | unsigned char mask; |
241 | |
242 | uint16 c[9]; |
243 | |
244 | c[1] = src0[0]; |
245 | c[4] = src1[0]; |
246 | c[7] = src2[0]; |
247 | |
248 | if (i>0) { |
249 | c[0] = src0[-1]; |
250 | c[3] = src1[-1]; |
251 | c[6] = src2[-1]; |
252 | } else { |
253 | c[0] = c[1]; |
254 | c[3] = c[4]; |
255 | c[6] = c[7]; |
256 | } |
257 | |
258 | if (i<count-1) { |
259 | c[2] = src0[1]; |
260 | c[5] = src1[1]; |
261 | c[8] = src2[1]; |
262 | } else { |
263 | c[2] = c[1]; |
264 | c[5] = c[4]; |
265 | c[8] = c[7]; |
266 | } |
267 | |
268 | mask = 0; |
269 | |
270 | if (hq2x_interp_16_diff(c[0], c[4])) |
271 | mask |= 1 << 0; |
272 | if (hq2x_interp_16_diff(c[1], c[4])) |
273 | mask |= 1 << 1; |
274 | if (hq2x_interp_16_diff(c[2], c[4])) |
275 | mask |= 1 << 2; |
276 | if (hq2x_interp_16_diff(c[3], c[4])) |
277 | mask |= 1 << 3; |
278 | if (hq2x_interp_16_diff(c[5], c[4])) |
279 | mask |= 1 << 4; |
280 | if (hq2x_interp_16_diff(c[6], c[4])) |
281 | mask |= 1 << 5; |
282 | if (hq2x_interp_16_diff(c[7], c[4])) |
283 | mask |= 1 << 6; |
284 | if (hq2x_interp_16_diff(c[8], c[4])) |
285 | mask |= 1 << 7; |
286 | |
287 | #define P0 dst0[0] |
288 | #define P1 dst0[1] |
289 | #define P2 dst1[0] |
290 | #define P3 dst1[1] |
291 | #define HQ2X_MUR hq2x_interp_16_diff(c[1], c[5]) |
292 | #define HQ2X_MDR hq2x_interp_16_diff(c[5], c[7]) |
293 | #define HQ2X_MDL hq2x_interp_16_diff(c[7], c[3]) |
294 | #define HQ2X_MUL hq2x_interp_16_diff(c[3], c[1]) |
295 | #define IC(p0) c[p0] |
296 | #define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) |
297 | #define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) |
298 | #define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) |
299 | #define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) |
300 | #define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) |
301 | #define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) |
302 | #define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) |
303 | #define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) |
304 | #define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) |
305 | #define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) |
306 | #define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) |
307 | #define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) |
308 | #define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) |
309 | |
310 | switch (mask) { |
311 | #include "TextureFilters_hq2x.h" |
312 | } |
313 | |
314 | #undef P0 |
315 | #undef P1 |
316 | #undef P2 |
317 | #undef P3 |
318 | #undef HQ2X_MUR |
319 | #undef HQ2X_MDR |
320 | #undef HQ2X_MDL |
321 | #undef HQ2X_MUL |
322 | #undef IC |
323 | #undef I11 |
324 | #undef I211 |
325 | #undef I31 |
326 | #undef I332 |
327 | #undef I431 |
328 | #undef I521 |
329 | #undef I53 |
330 | #undef I611 |
331 | #undef I71 |
332 | #undef I772 |
333 | #undef I97 |
334 | #undef I1411 |
335 | #undef I151 |
336 | |
337 | src0 += 1; |
338 | src1 += 1; |
339 | src2 += 1; |
340 | dst0 += 2; |
341 | dst1 += 2; |
342 | } |
343 | } |
344 | |
345 | static void hq2xS_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) |
346 | { |
347 | unsigned i; |
348 | |
349 | for(i=0;i<count;++i) { |
350 | unsigned char mask; |
351 | |
352 | uint16 c[9]; |
353 | |
354 | c[1] = src0[0]; |
355 | c[4] = src1[0]; |
356 | c[7] = src2[0]; |
357 | |
358 | if (i>0) { |
359 | c[0] = src0[-1]; |
360 | c[3] = src1[-1]; |
361 | c[6] = src2[-1]; |
362 | } else { |
363 | c[0] = c[1]; |
364 | c[3] = c[4]; |
365 | c[6] = c[7]; |
366 | } |
367 | |
368 | if (i<count-1) { |
369 | c[2] = src0[1]; |
370 | c[5] = src1[1]; |
371 | c[8] = src2[1]; |
372 | } else { |
373 | c[2] = c[1]; |
374 | c[5] = c[4]; |
375 | c[8] = c[7]; |
376 | } |
377 | |
378 | mask = 0; |
379 | |
380 | // hq2xS dynamic edge detection: |
381 | // simply comparing the center color against its surroundings will give bad results in many cases, |
382 | // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block |
383 | int brightArray[9]; |
384 | int maxBright = 0, minBright = 999999; |
385 | for(int j = 0 ; j < 9 ; j++) { |
386 | int r,g,b; |
387 | if (interp_bits_per_pixel == 16) { |
388 | b = (int)((c[j] & 0x1F)) << 3; |
389 | g = (int)((c[j] & 0x7E0)) >> 3; |
390 | r = (int)((c[j] & 0xF800)) >> 8; |
391 | } else { |
392 | b = (int)((c[j] & 0x1F)) << 3; |
393 | g = (int)((c[j] & 0x3E0)) >> 2; |
394 | r = (int)((c[j] & 0x7C00)) >> 7; |
395 | } |
396 | const int bright = r+r+r + g+g+g + b+b; |
397 | if(bright > maxBright) maxBright = bright; |
398 | if(bright < minBright) minBright = bright; |
399 | |
400 | brightArray[j] = bright; |
401 | } |
402 | int diffBright = ((maxBright - minBright) * 7) >> 4; |
403 | if(diffBright > 7) { |
404 | #define ABS(x) ((x) < 0 ? -(x) : (x)) |
405 | |
406 | const int centerBright = brightArray[4]; |
407 | if(ABS(brightArray[0] - centerBright) > diffBright) |
408 | mask |= 1 << 0; |
409 | if(ABS(brightArray[1] - centerBright) > diffBright) |
410 | mask |= 1 << 1; |
411 | if(ABS(brightArray[2] - centerBright) > diffBright) |
412 | mask |= 1 << 2; |
413 | if(ABS(brightArray[3] - centerBright) > diffBright) |
414 | mask |= 1 << 3; |
415 | if(ABS(brightArray[5] - centerBright) > diffBright) |
416 | mask |= 1 << 4; |
417 | if(ABS(brightArray[6] - centerBright) > diffBright) |
418 | mask |= 1 << 5; |
419 | if(ABS(brightArray[7] - centerBright) > diffBright) |
420 | mask |= 1 << 6; |
421 | if(ABS(brightArray[8] - centerBright) > diffBright) |
422 | mask |= 1 << 7; |
423 | } |
424 | |
425 | #define P0 dst0[0] |
426 | #define P1 dst0[1] |
427 | #define P2 dst1[0] |
428 | #define P3 dst1[1] |
429 | #define HQ2X_MUR false |
430 | #define HQ2X_MDR false |
431 | #define HQ2X_MDL false |
432 | #define HQ2X_MUL false |
433 | #define IC(p0) c[p0] |
434 | #define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) |
435 | #define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) |
436 | #define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) |
437 | #define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) |
438 | #define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) |
439 | #define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) |
440 | #define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) |
441 | #define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) |
442 | #define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) |
443 | #define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) |
444 | #define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) |
445 | #define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) |
446 | #define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) |
447 | |
448 | switch (mask) { |
449 | #include "TextureFilters_hq2x.h" |
450 | } |
451 | |
452 | #undef P0 |
453 | #undef P1 |
454 | #undef P2 |
455 | #undef P3 |
456 | #undef HQ2X_MUR |
457 | #undef HQ2X_MDR |
458 | #undef HQ2X_MDL |
459 | #undef HQ2X_MUL |
460 | #undef IC |
461 | #undef I11 |
462 | #undef I211 |
463 | #undef I31 |
464 | #undef I332 |
465 | #undef I431 |
466 | #undef I521 |
467 | #undef I53 |
468 | #undef I611 |
469 | #undef I71 |
470 | #undef I772 |
471 | #undef I97 |
472 | #undef I1411 |
473 | #undef I151 |
474 | |
475 | src0 += 1; |
476 | src1 += 1; |
477 | src2 += 1; |
478 | dst0 += 2; |
479 | dst1 += 2; |
480 | } |
481 | } |
482 | #endif /* !_16BPP_HACK */ |
483 | |
484 | static void hq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) |
485 | { |
486 | unsigned i; |
487 | |
488 | for(i=0;i<count;++i) { |
489 | unsigned char mask; |
490 | |
491 | uint32 c[9]; |
492 | |
493 | c[1] = src0[0]; |
494 | c[4] = src1[0]; |
495 | c[7] = src2[0]; |
496 | |
497 | if (i>0) { |
498 | c[0] = src0[-1]; |
499 | c[3] = src1[-1]; |
500 | c[6] = src2[-1]; |
501 | } else { |
502 | c[0] = src0[0]; |
503 | c[3] = src1[0]; |
504 | c[6] = src2[0]; |
505 | } |
506 | |
507 | if (i<count-1) { |
508 | c[2] = src0[1]; |
509 | c[5] = src1[1]; |
510 | c[8] = src2[1]; |
511 | } else { |
512 | c[2] = src0[0]; |
513 | c[5] = src1[0]; |
514 | c[8] = src2[0]; |
515 | } |
516 | |
517 | mask = 0; |
518 | |
519 | if (hq2x_interp_32_diff(c[0], c[4])) |
520 | mask |= 1 << 0; |
521 | if (hq2x_interp_32_diff(c[1], c[4])) |
522 | mask |= 1 << 1; |
523 | if (hq2x_interp_32_diff(c[2], c[4])) |
524 | mask |= 1 << 2; |
525 | if (hq2x_interp_32_diff(c[3], c[4])) |
526 | mask |= 1 << 3; |
527 | if (hq2x_interp_32_diff(c[5], c[4])) |
528 | mask |= 1 << 4; |
529 | if (hq2x_interp_32_diff(c[6], c[4])) |
530 | mask |= 1 << 5; |
531 | if (hq2x_interp_32_diff(c[7], c[4])) |
532 | mask |= 1 << 6; |
533 | if (hq2x_interp_32_diff(c[8], c[4])) |
534 | mask |= 1 << 7; |
535 | |
536 | #define P0 dst0[0] |
537 | #define P1 dst0[1] |
538 | #define P2 dst1[0] |
539 | #define P3 dst1[1] |
540 | #define HQ2X_MUR hq2x_interp_32_diff(c[1], c[5]) |
541 | #define HQ2X_MDR hq2x_interp_32_diff(c[5], c[7]) |
542 | #define HQ2X_MDL hq2x_interp_32_diff(c[7], c[3]) |
543 | #define HQ2X_MUL hq2x_interp_32_diff(c[3], c[1]) |
544 | #define IC(p0) c[p0] |
545 | #define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) |
546 | #define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) |
547 | #define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) |
548 | #define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) |
549 | #define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) |
550 | #define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) |
551 | |
552 | switch (mask) { |
553 | #include "TextureFilters_hq2x.h" |
554 | } |
555 | |
556 | #undef P0 |
557 | #undef P1 |
558 | #undef P2 |
559 | #undef P3 |
560 | #undef HQ2X_MUR |
561 | #undef HQ2X_MDR |
562 | #undef HQ2X_MDL |
563 | #undef HQ2X_MUL |
564 | #undef IC |
565 | #undef I211 |
566 | #undef I31 |
567 | #undef I332 |
568 | #undef I521 |
569 | #undef I611 |
570 | #undef I1411 |
571 | |
572 | src0 += 1; |
573 | src1 += 1; |
574 | src2 += 1; |
575 | dst0 += 2; |
576 | dst1 += 2; |
577 | } |
578 | } |
579 | |
580 | static void hq2xS_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) |
581 | { |
582 | unsigned i; |
583 | |
584 | for(i=0;i<count;++i) { |
585 | unsigned char mask; |
586 | |
587 | uint32 c[9]; |
588 | |
589 | c[1] = src0[0]; |
590 | c[4] = src1[0]; |
591 | c[7] = src2[0]; |
592 | |
593 | if (i>0) { |
594 | c[0] = src0[-1]; |
595 | c[3] = src1[-1]; |
596 | c[6] = src2[-1]; |
597 | } else { |
598 | c[0] = src0[0]; |
599 | c[3] = src1[0]; |
600 | c[6] = src2[0]; |
601 | } |
602 | |
603 | if (i<count-1) { |
604 | c[2] = src0[1]; |
605 | c[5] = src1[1]; |
606 | c[8] = src2[1]; |
607 | } else { |
608 | c[2] = src0[0]; |
609 | c[5] = src1[0]; |
610 | c[8] = src2[0]; |
611 | } |
612 | |
613 | mask = 0; |
614 | // hq2xS dynamic edge detection: |
615 | // simply comparing the center color against its surroundings will give bad results in many cases, |
616 | // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block |
617 | int brightArray[9]; |
618 | int maxBright = 0, minBright = 999999; |
619 | for(int j = 0 ; j < 9 ; j++) { |
620 | const int b = (int)((c[j] & 0xF8)); |
621 | const int g = (int)((c[j] & 0xF800)) >> 8; |
622 | const int r = (int)((c[j] & 0xF80000)) >> 16; |
623 | const int bright = r+r+r + g+g+g + b+b; |
624 | if(bright > maxBright) maxBright = bright; |
625 | if(bright < minBright) minBright = bright; |
626 | |
627 | brightArray[j] = bright; |
628 | } |
629 | int diffBright = ((maxBright - minBright) * 7) >> 4; |
630 | if(diffBright > 7) { |
631 | #define ABS(x) ((x) < 0 ? -(x) : (x)) |
632 | |
633 | const int centerBright = brightArray[4]; |
634 | if(ABS(brightArray[0] - centerBright) > diffBright) |
635 | mask |= 1 << 0; |
636 | if(ABS(brightArray[1] - centerBright) > diffBright) |
637 | mask |= 1 << 1; |
638 | if(ABS(brightArray[2] - centerBright) > diffBright) |
639 | mask |= 1 << 2; |
640 | if(ABS(brightArray[3] - centerBright) > diffBright) |
641 | mask |= 1 << 3; |
642 | if(ABS(brightArray[5] - centerBright) > diffBright) |
643 | mask |= 1 << 4; |
644 | if(ABS(brightArray[6] - centerBright) > diffBright) |
645 | mask |= 1 << 5; |
646 | if(ABS(brightArray[7] - centerBright) > diffBright) |
647 | mask |= 1 << 6; |
648 | if(ABS(brightArray[8] - centerBright) > diffBright) |
649 | mask |= 1 << 7; |
650 | } |
651 | #define P0 dst0[0] |
652 | #define P1 dst0[1] |
653 | #define P2 dst1[0] |
654 | #define P3 dst1[1] |
655 | #define HQ2X_MUR false |
656 | #define HQ2X_MDR false |
657 | #define HQ2X_MDL false |
658 | #define HQ2X_MUL false |
659 | #define IC(p0) c[p0] |
660 | #define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) |
661 | #define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) |
662 | #define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) |
663 | #define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) |
664 | #define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) |
665 | #define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) |
666 | |
667 | switch (mask) { |
668 | #include "TextureFilters_hq2x.h" |
669 | } |
670 | |
671 | #undef P0 |
672 | #undef P1 |
673 | #undef P2 |
674 | #undef P3 |
675 | #undef HQ2X_MUR |
676 | #undef HQ2X_MDR |
677 | #undef HQ2X_MDL |
678 | #undef HQ2X_MUL |
679 | #undef IC |
680 | #undef I211 |
681 | #undef I31 |
682 | #undef I332 |
683 | #undef I521 |
684 | #undef I611 |
685 | #undef I1411 |
686 | |
687 | src0 += 1; |
688 | src1 += 1; |
689 | src2 += 1; |
690 | dst0 += 2; |
691 | dst1 += 2; |
692 | } |
693 | } |
694 | |
695 | /***************************************************************************/ |
696 | /* LQ2x C implementation */ |
697 | |
698 | /* |
699 | * This effect is derived from the hq2x effect made by Maxim Stepin |
700 | */ |
701 | |
702 | #if !_16BPP_HACK |
703 | static void lq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) |
704 | { |
705 | unsigned i; |
706 | |
707 | for(i=0;i<count;++i) { |
708 | unsigned char mask; |
709 | |
710 | uint16 c[9]; |
711 | |
712 | c[1] = src0[0]; |
713 | c[4] = src1[0]; |
714 | c[7] = src2[0]; |
715 | |
716 | if (i>0) { |
717 | c[0] = src0[-1]; |
718 | c[3] = src1[-1]; |
719 | c[6] = src2[-1]; |
720 | } else { |
721 | c[0] = c[1]; |
722 | c[3] = c[4]; |
723 | c[6] = c[7]; |
724 | } |
725 | |
726 | if (i<count-1) { |
727 | c[2] = src0[1]; |
728 | c[5] = src1[1]; |
729 | c[8] = src2[1]; |
730 | } else { |
731 | c[2] = c[1]; |
732 | c[5] = c[4]; |
733 | c[8] = c[7]; |
734 | } |
735 | |
736 | mask = 0; |
737 | |
738 | if (c[0] != c[4]) |
739 | mask |= 1 << 0; |
740 | if (c[1] != c[4]) |
741 | mask |= 1 << 1; |
742 | if (c[2] != c[4]) |
743 | mask |= 1 << 2; |
744 | if (c[3] != c[4]) |
745 | mask |= 1 << 3; |
746 | if (c[5] != c[4]) |
747 | mask |= 1 << 4; |
748 | if (c[6] != c[4]) |
749 | mask |= 1 << 5; |
750 | if (c[7] != c[4]) |
751 | mask |= 1 << 6; |
752 | if (c[8] != c[4]) |
753 | mask |= 1 << 7; |
754 | |
755 | #define P0 dst0[0] |
756 | #define P1 dst0[1] |
757 | #define P2 dst1[0] |
758 | #define P3 dst1[1] |
759 | #define HQ2X_MUR (c[1] != c[5]) |
760 | #define HQ2X_MDR (c[5] != c[7]) |
761 | #define HQ2X_MDL (c[7] != c[3]) |
762 | #define HQ2X_MUL (c[3] != c[1]) |
763 | #define IC(p0) c[p0] |
764 | #define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) |
765 | #define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) |
766 | #define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) |
767 | #define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) |
768 | #define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) |
769 | #define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) |
770 | #define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) |
771 | #define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) |
772 | #define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) |
773 | #define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) |
774 | #define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) |
775 | #define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) |
776 | #define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) |
777 | |
778 | switch (mask) { |
779 | #include "TextureFilters_lq2x.h" |
780 | } |
781 | |
782 | #undef P0 |
783 | #undef P1 |
784 | #undef P2 |
785 | #undef P3 |
786 | #undef HQ2X_MUR |
787 | #undef HQ2X_MDR |
788 | #undef HQ2X_MDL |
789 | #undef HQ2X_MUL |
790 | #undef IC |
791 | #undef I11 |
792 | #undef I211 |
793 | #undef I31 |
794 | #undef I332 |
795 | #undef I431 |
796 | #undef I521 |
797 | #undef I53 |
798 | #undef I611 |
799 | #undef I71 |
800 | #undef I772 |
801 | #undef I97 |
802 | #undef I1411 |
803 | #undef I151 |
804 | |
805 | src0 += 1; |
806 | src1 += 1; |
807 | src2 += 1; |
808 | dst0 += 2; |
809 | dst1 += 2; |
810 | } |
811 | } |
812 | |
813 | static void lq2xS_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) |
814 | { |
815 | unsigned i; |
816 | |
817 | for(i=0;i<count;++i) { |
818 | unsigned char mask; |
819 | |
820 | uint16 c[9]; |
821 | |
822 | c[1] = src0[0]; |
823 | c[4] = src1[0]; |
824 | c[7] = src2[0]; |
825 | |
826 | if (i>0) { |
827 | c[0] = src0[-1]; |
828 | c[3] = src1[-1]; |
829 | c[6] = src2[-1]; |
830 | } else { |
831 | c[0] = c[1]; |
832 | c[3] = c[4]; |
833 | c[6] = c[7]; |
834 | } |
835 | |
836 | if (i<count-1) { |
837 | c[2] = src0[1]; |
838 | c[5] = src1[1]; |
839 | c[8] = src2[1]; |
840 | } else { |
841 | c[2] = c[1]; |
842 | c[5] = c[4]; |
843 | c[8] = c[7]; |
844 | } |
845 | |
846 | // hq2xS dynamic edge detection: |
847 | // simply comparing the center color against its surroundings will give bad results in many cases, |
848 | // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block |
849 | int brightArray[9]; |
850 | int maxBright = 0, minBright = 999999; |
851 | for(int j = 0 ; j < 9 ; j++) { |
852 | const int b = (int)((c[j] & 0xF8)); |
853 | const int g = (int)((c[j] & 0xF800)) >> 8; |
854 | const int r = (int)((c[j] & 0xF80000)) >> 16; |
855 | const int bright = r+r+r + g+g+g + b+b; |
856 | if(bright > maxBright) maxBright = bright; |
857 | if(bright < minBright) minBright = bright; |
858 | |
859 | brightArray[j] = bright; |
860 | } |
861 | int diffBright = ((maxBright - minBright) * 7) >> 4; |
862 | if(diffBright > 7) { |
863 | #define ABS(x) ((x) < 0 ? -(x) : (x)) |
864 | |
865 | const int centerBright = brightArray[4]; |
866 | if(ABS(brightArray[0] - centerBright) > diffBright) |
867 | mask |= 1 << 0; |
868 | if(ABS(brightArray[1] - centerBright) > diffBright) |
869 | mask |= 1 << 1; |
870 | if(ABS(brightArray[2] - centerBright) > diffBright) |
871 | mask |= 1 << 2; |
872 | if(ABS(brightArray[3] - centerBright) > diffBright) |
873 | mask |= 1 << 3; |
874 | if(ABS(brightArray[5] - centerBright) > diffBright) |
875 | mask |= 1 << 4; |
876 | if(ABS(brightArray[6] - centerBright) > diffBright) |
877 | mask |= 1 << 5; |
878 | if(ABS(brightArray[7] - centerBright) > diffBright) |
879 | mask |= 1 << 6; |
880 | if(ABS(brightArray[8] - centerBright) > diffBright) |
881 | mask |= 1 << 7; |
882 | } |
883 | |
884 | #define P0 dst0[0] |
885 | #define P1 dst0[1] |
886 | #define P2 dst1[0] |
887 | #define P3 dst1[1] |
888 | #define HQ2X_MUR false |
889 | #define HQ2X_MDR false |
890 | #define HQ2X_MDL false |
891 | #define HQ2X_MUL false |
892 | #define IC(p0) c[p0] |
893 | #define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) |
894 | #define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) |
895 | #define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) |
896 | #define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) |
897 | #define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) |
898 | #define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) |
899 | #define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) |
900 | #define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) |
901 | #define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) |
902 | #define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) |
903 | #define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) |
904 | #define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) |
905 | #define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) |
906 | |
907 | switch (mask) { |
908 | #include "TextureFilters_lq2x.h" |
909 | } |
910 | |
911 | #undef P0 |
912 | #undef P1 |
913 | #undef P2 |
914 | #undef P3 |
915 | #undef HQ2X_MUR |
916 | #undef HQ2X_MDR |
917 | #undef HQ2X_MDL |
918 | #undef HQ2X_MUL |
919 | #undef IC |
920 | #undef I11 |
921 | #undef I211 |
922 | #undef I31 |
923 | #undef I332 |
924 | #undef I431 |
925 | #undef I521 |
926 | #undef I53 |
927 | #undef I611 |
928 | #undef I71 |
929 | #undef I772 |
930 | #undef I97 |
931 | #undef I1411 |
932 | #undef I151 |
933 | |
934 | src0 += 1; |
935 | src1 += 1; |
936 | src2 += 1; |
937 | dst0 += 2; |
938 | dst1 += 2; |
939 | } |
940 | } |
941 | #endif /* !_16BPP_HACK */ |
942 | |
943 | static void lq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) |
944 | { |
945 | unsigned i; |
946 | |
947 | for(i=0;i<count;++i) { |
948 | unsigned char mask; |
949 | |
950 | uint32 c[9]; |
951 | |
952 | c[1] = src0[0]; |
953 | c[4] = src1[0]; |
954 | c[7] = src2[0]; |
955 | |
956 | if (i>0) { |
957 | c[0] = src0[-1]; |
958 | c[3] = src1[-1]; |
959 | c[6] = src2[-1]; |
960 | } else { |
961 | c[0] = c[1]; |
962 | c[3] = c[4]; |
963 | c[6] = c[7]; |
964 | } |
965 | |
966 | if (i<count-1) { |
967 | c[2] = src0[1]; |
968 | c[5] = src1[1]; |
969 | c[8] = src2[1]; |
970 | } else { |
971 | c[2] = c[1]; |
972 | c[5] = c[4]; |
973 | c[8] = c[7]; |
974 | } |
975 | |
976 | mask = 0; |
977 | |
978 | if (c[0] != c[4]) |
979 | mask |= 1 << 0; |
980 | if (c[1] != c[4]) |
981 | mask |= 1 << 1; |
982 | if (c[2] != c[4]) |
983 | mask |= 1 << 2; |
984 | if (c[3] != c[4]) |
985 | mask |= 1 << 3; |
986 | if (c[5] != c[4]) |
987 | mask |= 1 << 4; |
988 | if (c[6] != c[4]) |
989 | mask |= 1 << 5; |
990 | if (c[7] != c[4]) |
991 | mask |= 1 << 6; |
992 | if (c[8] != c[4]) |
993 | mask |= 1 << 7; |
994 | |
995 | #define P0 dst0[0] |
996 | #define P1 dst0[1] |
997 | #define P2 dst1[0] |
998 | #define P3 dst1[1] |
999 | #define HQ2X_MUR (c[1] != c[5]) |
1000 | #define HQ2X_MDR (c[5] != c[7]) |
1001 | #define HQ2X_MDL (c[7] != c[3]) |
1002 | #define HQ2X_MUL (c[3] != c[1]) |
1003 | #define IC(p0) c[p0] |
1004 | #define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) |
1005 | #define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) |
1006 | #define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) |
1007 | #define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) |
1008 | #define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) |
1009 | #define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) |
1010 | |
1011 | switch (mask) { |
1012 | #include "TextureFilters_lq2x.h" |
1013 | } |
1014 | |
1015 | #undef P0 |
1016 | #undef P1 |
1017 | #undef P2 |
1018 | #undef P3 |
1019 | #undef HQ2X_MUR |
1020 | #undef HQ2X_MDR |
1021 | #undef HQ2X_MDL |
1022 | #undef HQ2X_MUL |
1023 | #undef IC |
1024 | #undef I211 |
1025 | #undef I31 |
1026 | #undef I332 |
1027 | #undef I521 |
1028 | #undef I611 |
1029 | #undef I1411 |
1030 | |
1031 | src0 += 1; |
1032 | src1 += 1; |
1033 | src2 += 1; |
1034 | dst0 += 2; |
1035 | dst1 += 2; |
1036 | } |
1037 | } |
1038 | |
1039 | static void lq2xS_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) |
1040 | { |
1041 | unsigned i; |
1042 | |
1043 | for(i=0;i<count;++i) { |
1044 | unsigned char mask = 0; |
1045 | |
1046 | uint32 c[9]; |
1047 | |
1048 | c[1] = src0[0]; |
1049 | c[4] = src1[0]; |
1050 | c[7] = src2[0]; |
1051 | |
1052 | if (i>0) { |
1053 | c[0] = src0[-1]; |
1054 | c[3] = src1[-1]; |
1055 | c[6] = src2[-1]; |
1056 | } else { |
1057 | c[0] = c[1]; |
1058 | c[3] = c[4]; |
1059 | c[6] = c[7]; |
1060 | } |
1061 | |
1062 | if (i<count-1) { |
1063 | c[2] = src0[1]; |
1064 | c[5] = src1[1]; |
1065 | c[8] = src2[1]; |
1066 | } else { |
1067 | c[2] = c[1]; |
1068 | c[5] = c[4]; |
1069 | c[8] = c[7]; |
1070 | } |
1071 | |
1072 | // hq2xS dynamic edge detection: |
1073 | // simply comparing the center color against its surroundings will give bad results in many cases, |
1074 | // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block |
1075 | int brightArray[9]; |
1076 | int maxBright = 0, minBright = 999999; |
1077 | for(int j = 0 ; j < 9 ; j++) { |
1078 | const int b = (int)((c[j] & 0xF8)); |
1079 | const int g = (int)((c[j] & 0xF800)) >> 8; |
1080 | const int r = (int)((c[j] & 0xF80000)) >> 16; |
1081 | const int bright = r+r+r + g+g+g + b+b; |
1082 | if(bright > maxBright) maxBright = bright; |
1083 | if(bright < minBright) minBright = bright; |
1084 | |
1085 | brightArray[j] = bright; |
1086 | } |
1087 | int diffBright = ((maxBright - minBright) * 7) >> 4; |
1088 | if(diffBright > 7) { |
1089 | #define ABS(x) ((x) < 0 ? -(x) : (x)) |
1090 | |
1091 | const int centerBright = brightArray[4]; |
1092 | if(ABS(brightArray[0] - centerBright) > diffBright) |
1093 | mask |= 1 << 0; |
1094 | if(ABS(brightArray[1] - centerBright) > diffBright) |
1095 | mask |= 1 << 1; |
1096 | if(ABS(brightArray[2] - centerBright) > diffBright) |
1097 | mask |= 1 << 2; |
1098 | if(ABS(brightArray[3] - centerBright) > diffBright) |
1099 | mask |= 1 << 3; |
1100 | if(ABS(brightArray[5] - centerBright) > diffBright) |
1101 | mask |= 1 << 4; |
1102 | if(ABS(brightArray[6] - centerBright) > diffBright) |
1103 | mask |= 1 << 5; |
1104 | if(ABS(brightArray[7] - centerBright) > diffBright) |
1105 | mask |= 1 << 6; |
1106 | if(ABS(brightArray[8] - centerBright) > diffBright) |
1107 | mask |= 1 << 7; |
1108 | } |
1109 | |
1110 | #define P0 dst0[0] |
1111 | #define P1 dst0[1] |
1112 | #define P2 dst1[0] |
1113 | #define P3 dst1[1] |
1114 | #define HQ2X_MUR false |
1115 | #define HQ2X_MDR false |
1116 | #define HQ2X_MDL false |
1117 | #define HQ2X_MUL false |
1118 | #define IC(p0) c[p0] |
1119 | #define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) |
1120 | #define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) |
1121 | #define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) |
1122 | #define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) |
1123 | #define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) |
1124 | #define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) |
1125 | |
1126 | switch (mask) { |
1127 | #include "TextureFilters_lq2x.h" |
1128 | } |
1129 | |
1130 | #undef P0 |
1131 | #undef P1 |
1132 | #undef P2 |
1133 | #undef P3 |
1134 | #undef HQ2X_MUR |
1135 | #undef HQ2X_MDR |
1136 | #undef HQ2X_MDL |
1137 | #undef HQ2X_MUL |
1138 | #undef IC |
1139 | #undef I211 |
1140 | #undef I31 |
1141 | #undef I332 |
1142 | #undef I521 |
1143 | #undef I611 |
1144 | #undef I1411 |
1145 | |
1146 | src0 += 1; |
1147 | src1 += 1; |
1148 | src2 += 1; |
1149 | dst0 += 2; |
1150 | dst1 += 2; |
1151 | } |
1152 | } |
1153 | |
1154 | #if !_16BPP_HACK |
1155 | void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1156 | { |
1157 | uint16 *dst0 = (uint16 *)dstPtr; |
1158 | uint16 *dst1 = dst0 + (dstPitch >> 1); |
1159 | |
1160 | uint16 *src0 = (uint16 *)srcPtr; |
1161 | uint16 *src1 = src0 + (srcPitch >> 1); |
1162 | uint16 *src2 = src1 + (srcPitch >> 1); |
1163 | |
1164 | int count; |
1165 | |
1166 | hq2x_16_def(dst0, dst1, src0, src0, src1, width); |
1167 | if( height == 1 ) return; |
1168 | |
1169 | count = height; |
1170 | |
1171 | count -= 2; |
1172 | while(count>0) { |
1173 | dst0 += dstPitch; |
1174 | dst1 += dstPitch; |
1175 | hq2x_16_def(dst0, dst1, src0, src1, src2, width); |
1176 | src0 = src1; |
1177 | src1 = src2; |
1178 | src2 += srcPitch >> 1; |
1179 | --count; |
1180 | } |
1181 | dst0 += dstPitch; |
1182 | dst1 += dstPitch; |
1183 | hq2x_16_def(dst0, dst1, src0, src1, src1, width); |
1184 | } |
1185 | |
1186 | |
1187 | void hq2xS_16(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, |
1188 | u8 *dstPtr, u32 dstPitch, int width, int height) |
1189 | { |
1190 | u16 *dst0 = (u16 *)dstPtr; |
1191 | u16 *dst1 = dst0 + (dstPitch >> 1); |
1192 | |
1193 | u16 *src0 = (u16 *)srcPtr; |
1194 | u16 *src1 = src0 + (srcPitch >> 1); |
1195 | u16 *src2 = src1 + (srcPitch >> 1); |
1196 | |
1197 | hq2xS_16_def(dst0, dst1, src0, src0, src1, width); |
1198 | |
1199 | int count = height; |
1200 | |
1201 | count -= 2; |
1202 | while(count) { |
1203 | dst0 += dstPitch; |
1204 | dst1 += dstPitch; |
1205 | hq2xS_16_def(dst0, dst1, src0, src1, src2, width); |
1206 | src0 = src1; |
1207 | src1 = src2; |
1208 | src2 += srcPitch >> 1; |
1209 | --count; |
1210 | } |
1211 | dst0 += dstPitch; |
1212 | dst1 += dstPitch; |
1213 | hq2xS_16_def(dst0, dst1, src0, src1, src1, width); |
1214 | } |
1215 | #endif /* !_16BPP_HACK */ |
1216 | |
1217 | void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1218 | { |
1219 | uint32 *dst0 = (uint32 *)dstPtr; |
1220 | uint32 *dst1 = dst0 + (dstPitch >> 2); |
1221 | |
1222 | uint32 *src0 = (uint32 *)srcPtr; |
1223 | uint32 *src1 = src0 + (srcPitch >> 2); |
1224 | uint32 *src2 = src1 + (srcPitch >> 2); |
1225 | |
1226 | int count; |
1227 | |
1228 | hq2x_32_def(dst0, dst1, src0, src0, src1, width); |
1229 | if( height == 1 ) return; |
1230 | |
1231 | count = height; |
1232 | |
1233 | count -= 2; |
1234 | while(count>0) { |
1235 | dst0 += dstPitch >> 1; |
1236 | dst1 += dstPitch >> 1; |
1237 | hq2x_32_def(dst0, dst1, src0, src1, src2, width); |
1238 | src0 = src1; |
1239 | src1 = src2; |
1240 | src2 += srcPitch >> 2; |
1241 | --count; |
1242 | } |
1243 | dst0 += dstPitch >> 1; |
1244 | dst1 += dstPitch >> 1; |
1245 | hq2x_32_def(dst0, dst1, src0, src1, src1, width); |
1246 | } |
1247 | |
1248 | void hq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1249 | { |
1250 | uint32 *dst0 = (uint32 *)dstPtr; |
1251 | uint32 *dst1 = dst0 + (dstPitch >> 2); |
1252 | |
1253 | uint32 *src0 = (uint32 *)srcPtr; |
1254 | uint32 *src1 = src0 + (srcPitch >> 2); |
1255 | uint32 *src2 = src1 + (srcPitch >> 2); |
1256 | hq2xS_32_def(dst0, dst1, src0, src0, src1, width); |
1257 | |
1258 | int count = height; |
1259 | |
1260 | count -= 2; |
1261 | while(count) { |
1262 | dst0 += dstPitch >> 1; |
1263 | dst1 += dstPitch >> 1; |
1264 | hq2xS_32_def(dst0, dst1, src0, src1, src2, width); |
1265 | src0 = src1; |
1266 | src1 = src2; |
1267 | src2 += srcPitch >> 2; |
1268 | --count; |
1269 | } |
1270 | dst0 += dstPitch >> 1; |
1271 | dst1 += dstPitch >> 1; |
1272 | hq2xS_32_def(dst0, dst1, src0, src1, src1, width); |
1273 | } |
1274 | |
1275 | #if !_16BPP_HACK |
1276 | void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1277 | { |
1278 | uint16 *dst0 = (uint16 *)dstPtr; |
1279 | uint16 *dst1 = dst0 + (dstPitch >> 1); |
1280 | |
1281 | uint16 *src0 = (uint16 *)srcPtr; |
1282 | uint16 *src1 = src0 + (srcPitch >> 1); |
1283 | uint16 *src2 = src1 + (srcPitch >> 1); |
1284 | |
1285 | int count; |
1286 | |
1287 | lq2x_16_def(dst0, dst1, src0, src0, src1, width); |
1288 | if( height == 1 ) return; |
1289 | |
1290 | count = height; |
1291 | |
1292 | count -= 2; |
1293 | while(count>0) { |
1294 | dst0 += dstPitch; |
1295 | dst1 += dstPitch; |
1296 | hq2x_16_def(dst0, dst1, src0, src1, src2, width); |
1297 | src0 = src1; |
1298 | src1 = src2; |
1299 | src2 += srcPitch >> 1; |
1300 | --count; |
1301 | } |
1302 | dst0 += dstPitch; |
1303 | dst1 += dstPitch; |
1304 | lq2x_16_def(dst0, dst1, src0, src1, src1, width); |
1305 | } |
1306 | |
1307 | void lq2xS_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1308 | { |
1309 | uint16 *dst0 = (uint16 *)dstPtr; |
1310 | uint16 *dst1 = dst0 + (dstPitch >> 1); |
1311 | |
1312 | uint16 *src0 = (uint16 *)srcPtr; |
1313 | uint16 *src1 = src0 + (srcPitch >> 1); |
1314 | uint16 *src2 = src1 + (srcPitch >> 1); |
1315 | |
1316 | int count; |
1317 | |
1318 | lq2xS_16_def(dst0, dst1, src0, src0, src1, width); |
1319 | if( height == 1 ) return; |
1320 | |
1321 | count = height; |
1322 | |
1323 | count -= 2; |
1324 | while(count>0) { |
1325 | dst0 += dstPitch; |
1326 | dst1 += dstPitch; |
1327 | hq2x_16_def(dst0, dst1, src0, src1, src2, width); |
1328 | src0 = src1; |
1329 | src1 = src2; |
1330 | src2 += srcPitch >> 1; |
1331 | --count; |
1332 | } |
1333 | dst0 += dstPitch; |
1334 | dst1 += dstPitch; |
1335 | lq2xS_16_def(dst0, dst1, src0, src1, src1, width); |
1336 | } |
1337 | #endif /* !_16BPP_HACK */ |
1338 | |
1339 | void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1340 | { |
1341 | uint32 *dst0 = (uint32 *)dstPtr; |
1342 | uint32 *dst1 = dst0 + (dstPitch >> 2); |
1343 | |
1344 | uint32 *src0 = (uint32 *)srcPtr; |
1345 | uint32 *src1 = src0 + (srcPitch >> 2); |
1346 | uint32 *src2 = src1 + (srcPitch >> 2); |
1347 | |
1348 | int count; |
1349 | |
1350 | lq2x_32_def(dst0, dst1, src0, src0, src1, width); |
1351 | if( height == 1 ) return; |
1352 | |
1353 | count = height; |
1354 | |
1355 | count -= 2; |
1356 | while(count>0) { |
1357 | dst0 += dstPitch >> 1; |
1358 | dst1 += dstPitch >> 1; |
1359 | hq2x_32_def(dst0, dst1, src0, src1, src2, width); |
1360 | src0 = src1; |
1361 | src1 = src2; |
1362 | src2 += srcPitch >> 2; |
1363 | --count; |
1364 | } |
1365 | dst0 += dstPitch >> 1; |
1366 | dst1 += dstPitch >> 1; |
1367 | lq2x_32_def(dst0, dst1, src0, src1, src1, width); |
1368 | } |
1369 | |
1370 | void lq2xS_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
1371 | { |
1372 | uint32 *dst0 = (uint32 *)dstPtr; |
1373 | uint32 *dst1 = dst0 + (dstPitch >> 2); |
1374 | |
1375 | uint32 *src0 = (uint32 *)srcPtr; |
1376 | uint32 *src1 = src0 + (srcPitch >> 2); |
1377 | uint32 *src2 = src1 + (srcPitch >> 2); |
1378 | |
1379 | int count; |
1380 | |
1381 | lq2xS_32_def(dst0, dst1, src0, src0, src1, width); |
1382 | if( height == 1 ) return; |
1383 | |
1384 | count = height; |
1385 | |
1386 | count -= 2; |
1387 | while(count>0) { |
1388 | dst0 += dstPitch >> 1; |
1389 | dst1 += dstPitch >> 1; |
1390 | hq2x_32_def(dst0, dst1, src0, src1, src2, width); |
1391 | src0 = src1; |
1392 | src1 = src2; |
1393 | src2 += srcPitch >> 2; |
1394 | --count; |
1395 | } |
1396 | dst0 += dstPitch >> 1; |
1397 | dst1 += dstPitch >> 1; |
1398 | lq2xS_32_def(dst0, dst1, src0, src1, src1, width); |
1399 | } |
1400 | |
1401 | /************************************************************************/ |
1402 | /* hq3x filters */ |
1403 | /************************************************************************/ |
1404 | |
1405 | /************************************************************************/ |
1406 | /* scale2x filters */ |
1407 | /************************************************************************/ |
1408 | |
1409 | /************************************************************************/ |
1410 | /* scale3x filters */ |
1411 | /************************************************************************/ |
1412 | |