1 | //hq2xa filter |
1 | /* |
2 | //---------------------------------------------------------- |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
|
|
3 | * |
|
|
4 | * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team |
|
|
5 | * Copyright (©) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
3 | //Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) |
6 | * Copyright (©) 2003 MaxSt <maxst@hiend3d.com> |
4 | //Copyright (C) 2006 Marc Lehmann <pcg@goof.com> |
7 | * |
5 | // converted to RGBA, cleaned up |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
6 | |
9 | * the terms of the Affero GNU General Public License as published by the |
7 | //This program is free software; you can redistribute it and/or |
10 | * Free Software Foundation, either version 3 of the License, or (at your |
8 | //modify it under the terms of the GNU Lesser General Public |
11 | * option) any later version. |
9 | //License as published by the Free Software Foundation; either |
12 | * |
10 | //version 2.1 of the License, or (at your option) any later version. |
|
|
11 | // |
|
|
12 | //This program is distributed in the hope that it will be useful, |
13 | * This program is distributed in the hope that it will be useful, |
13 | //but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | //Lesser General Public License for more details. |
16 | * GNU General Public License for more details. |
16 | // |
17 | * |
17 | //You should have received a copy of the GNU Lesser General Public |
18 | * You should have received a copy of the Affero GNU General Public License |
18 | //License along with this program; if not, write to the Free Software |
19 | * and the GNU General Public License along with this program. If not, see |
19 | //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | * <http://www.gnu.org/licenses/>. |
|
|
21 | * |
|
|
22 | * The authors can be reached via e-mail to <support@deliantra.net> |
|
|
23 | */ |
|
|
24 | |
|
|
25 | // note: the original code was released under the LGPL version 2.1 |
20 | |
26 | |
21 | #include <cstdio> |
27 | #include <cstdio> |
22 | #include <cstring> |
28 | #include <cstring> |
23 | #include <stdlib.h> |
29 | #include <stdlib.h> |
24 | #include <stdint.h> |
30 | #include <stdint.h> |
… | |
… | |
48 | # define trY 0x30 |
54 | # define trY 0x30 |
49 | # define trU 0x11 |
55 | # define trU 0x11 |
50 | # define trV 0x10 |
56 | # define trV 0x10 |
51 | # define trA 0x40 |
57 | # define trA 0x40 |
52 | |
58 | |
|
|
59 | static int32_t |
|
|
60 | udiff (uint32_t a, uint32_t b) |
|
|
61 | { |
|
|
62 | return a > b ? a - b : b - a; |
|
|
63 | |
|
|
64 | } |
|
|
65 | |
53 | static inline pixel lerp (pixel c1, int w1, pixel c2, int w2, pixel c3, int w3, int shift) |
66 | static inline pixel lerp (pixel c1, int w1, pixel c2, int w2, pixel c3, int w3, int shift) |
54 | { |
67 | { |
55 | #if 0 |
68 | #if 0 |
56 | if (!(c1 >> Ashift) & Cmask) w1 = 0; |
69 | if (!(c1 >> Ashift) & Cmask) w1 = 0; |
57 | if (!(c2 >> Ashift) & Cmask) w2 = 0; |
70 | if (!(c2 >> Ashift) & Cmask) w2 = 0; |
… | |
… | |
61 | int w = w1 + w2 + w3; |
74 | int w = w1 + w2 + w3; |
62 | |
75 | |
63 | return ((((c1 >> shift) & Cmask) * w1 + ((c2 >> shift) & Cmask) * w2 + ((c3 >> shift) & Cmask) * w3 + w / 2) / w) << shift; |
76 | return ((((c1 >> shift) & Cmask) * w1 + ((c2 >> shift) & Cmask) * w2 + ((c3 >> shift) & Cmask) * w3 + w / 2) / w) << shift; |
64 | } |
77 | } |
65 | |
78 | |
66 | inline void lerp (unsigned char *pc, pixel c1, int w1, pixel c2, int w2, pixel c3 = 0, int w3 = 0) |
79 | static inline void lerp (unsigned char *pc, pixel c1, int w1, pixel c2, int w2, pixel c3 = 0, int w3 = 0) |
67 | { |
80 | { |
68 | *(pixel *)pc = lerp (c1, w1, c2, w2, c3, w3, Rshift) |
81 | *(pixel *)pc = lerp (c1, w1, c2, w2, c3, w3, Rshift) |
69 | | lerp (c1, w1, c2, w2, c3, w3, Gshift) |
82 | | lerp (c1, w1, c2, w2, c3, w3, Gshift) |
70 | | lerp (c1, w1, c2, w2, c3, w3, Bshift) |
83 | | lerp (c1, w1, c2, w2, c3, w3, Bshift) |
71 | | lerp (c1, w1, c2, w2, c3, w3, Ashift); |
84 | | lerp (c1, w1, c2, w2, c3, w3, Ashift); |
72 | } |
85 | } |
73 | |
86 | |
74 | inline void Interp1 (unsigned char *pc, pixel c1, pixel c2) |
87 | static inline void Interp1 (unsigned char *pc, pixel c1, pixel c2) |
75 | { |
88 | { |
76 | lerp (pc, c1, 3, c2, 1); |
89 | lerp (pc, c1, 3, c2, 1); |
77 | } |
90 | } |
78 | |
91 | |
79 | inline void Interp2 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
92 | static inline void Interp2 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
80 | { |
93 | { |
81 | lerp (pc, c1, 2, c2, 1, c3, 1); |
94 | lerp (pc, c1, 2, c2, 1, c3, 1); |
82 | } |
95 | } |
83 | |
96 | |
84 | inline void Interp5 (unsigned char *pc, pixel c1, pixel c2) |
97 | static inline void Interp5 (unsigned char *pc, pixel c1, pixel c2) |
85 | { |
98 | { |
86 | lerp (pc, c1, 1, c2, 1); |
99 | lerp (pc, c1, 1, c2, 1); |
87 | } |
100 | } |
88 | |
101 | |
89 | inline void Interp6 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
102 | static inline void Interp6 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
90 | { |
103 | { |
91 | lerp (pc, c1, 5, c2, 2, c3, 1); |
104 | lerp (pc, c1, 5, c2, 2, c3, 1); |
92 | } |
105 | } |
93 | |
106 | |
94 | inline void Interp7 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
107 | static inline void Interp7 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
95 | { |
108 | { |
96 | lerp (pc, c1, 6, c2, 1, c3, 1); |
109 | lerp (pc, c1, 6, c2, 1, c3, 1); |
97 | } |
110 | } |
98 | |
111 | |
99 | inline void Interp9 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
112 | static inline void Interp9 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
100 | { |
113 | { |
101 | lerp (pc, c1, 2, c2, 3, c2, 3); |
114 | lerp (pc, c1, 2, c2, 3, c2, 3); |
102 | } |
115 | } |
103 | |
116 | |
104 | inline void Interp10 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
117 | static inline void Interp10 (unsigned char *pc, pixel c1, pixel c2, pixel c3) |
105 | { |
118 | { |
106 | lerp (pc, c1, 14, c2, 1, c3, 1); |
119 | lerp (pc, c1, 14, c2, 1, c3, 1); |
107 | } |
120 | } |
108 | |
121 | |
109 | #define PIXEL00_0 *((pixel *)(pOut)) = w[5]; |
122 | #define PIXEL00_0 *((pixel *)(pOut)) = w[5]; |
… | |
… | |
153 | #define PIXEL11_61 Interp6(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
166 | #define PIXEL11_61 Interp6(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
154 | #define PIXEL11_70 Interp7(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
167 | #define PIXEL11_70 Interp7(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
155 | #define PIXEL11_90 Interp9(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
168 | #define PIXEL11_90 Interp9(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
156 | #define PIXEL11_100 Interp10(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
169 | #define PIXEL11_100 Interp10(pOut+BpL + sizeof (pixel), w[5], w[6], w[8]); |
157 | |
170 | |
158 | inline pixel RGBAtoYUVA (pixel w) |
171 | static inline pixel RGBAtoYUVA (pixel w) |
159 | { |
172 | { |
160 | int r = (w >> Rshift) & Cmask; |
173 | int r = (w >> Rshift) & Cmask; |
161 | int g = (w >> Gshift) & Cmask; |
174 | int g = (w >> Gshift) & Cmask; |
162 | int b = (w >> Bshift) & Cmask; |
175 | int b = (w >> Bshift) & Cmask; |
163 | int a = (w >> Ashift) & Cmask; |
176 | int a = (w >> Ashift) & Cmask; |
… | |
… | |
170 | | (u << Gshift) |
183 | | (u << Gshift) |
171 | | (v << Bshift) |
184 | | (v << Bshift) |
172 | | (a << Ashift); |
185 | | (a << Ashift); |
173 | } |
186 | } |
174 | |
187 | |
175 | inline bool Diff (pixel w1, pixel w2) |
188 | static inline bool Diff (pixel w1, pixel w2) |
176 | { |
189 | { |
177 | pixel YUV1 = RGBAtoYUVA (w1); |
190 | pixel YUV1 = RGBAtoYUVA (w1); |
178 | pixel YUV2 = RGBAtoYUVA (w2); |
191 | pixel YUV2 = RGBAtoYUVA (w2); |
179 | |
192 | |
180 | return ((abs (((YUV1 >> Rshift) & Cmask) - ((YUV2 >> Rshift) & Cmask)) > trY) || |
193 | return ((udiff ((YUV1 >> Rshift) & Cmask, (YUV2 >> Rshift) & Cmask) > trY) || |
181 | (abs (((YUV1 >> Gshift) & Cmask) - ((YUV2 >> Gshift) & Cmask)) > trU) || |
194 | (udiff ((YUV1 >> Gshift) & Cmask, (YUV2 >> Gshift) & Cmask) > trU) || |
182 | (abs (((YUV1 >> Bshift) & Cmask) - ((YUV2 >> Bshift) & Cmask)) > trV) || |
195 | (udiff ((YUV1 >> Bshift) & Cmask, (YUV2 >> Bshift) & Cmask) > trV) || |
183 | (abs (((YUV1 >> Ashift) & Cmask) - ((YUV2 >> Ashift) & Cmask)) > trA) ); |
196 | (udiff ((YUV1 >> Ashift) & Cmask, (YUV2 >> Ashift) & Cmask) > trA) ); |
184 | } |
197 | } |
185 | |
198 | |
186 | void |
199 | static void |
187 | hq2x_32 (unsigned char *pIn, unsigned char *pOut, int Xres, int Yres, int BpL, bool wrap) |
200 | hq2x_32 (unsigned char *pIn, unsigned char *pOut, int Xres, int Yres, int BpL, bool wrap) |
188 | { |
201 | { |
189 | int i, j, k; |
202 | int i, j, k; |
190 | int prevline, nextline; |
203 | int prevline, nextline; |
191 | pixel w[10]; |
204 | pixel w[10]; |
192 | |
205 | |
193 | // +----+----+----+ |
206 | // +--+--+--+ |
194 | // | | | | |
|
|
195 | // | w1 | w2 | w3 | |
207 | // |w1|w2|w3| |
196 | // +----+----+----+ |
208 | // +--+--+--+ |
197 | // | | | | |
|
|
198 | // | w4 | w5 | w6 | |
209 | // |w4|w5|w6| |
199 | // +----+----+----+ |
210 | // +--+--+--+ |
200 | // | | | | |
|
|
201 | // | w7 | w8 | w9 | |
211 | // |w7|w8|w9| |
202 | // +----+----+----+ |
212 | // +--+--+--+ |
203 | |
213 | |
204 | for (j = 0; j < Yres; j++) |
214 | for (j = 0; j < Yres; j++) |
205 | { |
215 | { |
206 | if (j > 0) |
216 | if (j > 0) |
207 | prevline = -Xres * sizeof (pixel); |
217 | prevline = -Xres * sizeof (pixel); |