initial commit, eq circuit emulator
[eqemu] / src / fblur.cc
1 /*
2 eqemu - electronic queue system emulator
3 Copyright (C) 2014  John Tsiombikas <nuclear@member.fsf.org>,
4                     Eleni-Maria Stea <eleni@mutantstargoat.com>
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19 #include <string.h>
20 #include <alloca.h>
21 #include "fblur.h"
22
23 #if  defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
24     (defined(__alpha__) || defined(__alpha)) || \
25      defined(__arm__) || \
26     (defined(__mips__) && defined(__MIPSEL__)) || \
27      defined(__SYMBIAN32__) || \
28      defined(__x86_64__) || \
29      defined(__LITTLE_ENDIAN__)
30 #define FBLUR_LITTLE_ENDIAN
31 #else
32 #define FBLUR_BIG_ENDIAN
33 #endif
34
35 /* some color packing/unpacking macros */
36 #ifdef FBLUR_BIG_ENDIAN
37 #define RSHIFT          24
38 #define GSHIFT          16
39 #define BSHIFT          8
40 #else   /* little endian */
41 #define RSHIFT          0
42 #define GSHIFT          8
43 #define BSHIFT          16
44 #endif
45
46 #define RED(p)                  (((p) >> RSHIFT) & 0xff)
47 #define GREEN(p)                (((p) >> GSHIFT) & 0xff)
48 #define BLUE(p)                 (((p) >> BSHIFT) & 0xff)
49 #define RGB(r, g, b)    \
50         ((((r) & 0xff) << RSHIFT) | \
51          (((g) & 0xff) << GSHIFT) | \
52          (((b) & 0xff) << BSHIFT))
53
54 #define MIN(a, b)       ((a) < (b) ? (a) : (b))
55 #define MAX(a, b)       ((a) > (b) ? (a) : (b))
56
57
58 void fast_blur(int dir, int amount, uint32_t *buf, int x, int y)
59 {
60         int i, j, half;
61         uint32_t *dptr, *sptr, *tmp_buf;
62
63         int blur_len = dir == BLUR_HORIZ ? x : y;
64         int blur_times = dir == BLUR_HORIZ ? y : x;
65
66         if(amount <= 1) return;
67
68         dptr = buf;
69         half = amount / 2;
70
71         tmp_buf = (uint32_t*)alloca(blur_len * sizeof(uint32_t));
72
73         for(i=0; i<blur_times; i++) {
74                 int ar = 0, ag = 0, ab = 0;
75                 int divisor = 0;
76
77                 if(dir == BLUR_HORIZ) {
78                         sptr = tmp_buf;
79                         memcpy(sptr, dptr, x * sizeof(uint32_t));
80                 } else {
81                         dptr = buf + i;
82
83                         sptr = tmp_buf;
84                         for(j=0; j<y; j++) {
85                                 *sptr++ = *dptr;
86                                 dptr += x;
87                         }
88                         dptr = buf + i;
89                         sptr = tmp_buf;
90                 }
91
92
93                 for(j=0; j<half; j++) {
94                         uint32_t pixel = tmp_buf[j];
95                         ar += RED(pixel);
96                         ag += GREEN(pixel);
97                         ab += BLUE(pixel);
98                         divisor++;
99                 }
100
101                 for(j=0; j<blur_len; j++) {
102                         int r, g, b;
103
104                         if(j > half) {
105                                 uint32_t out = *(sptr - half - 1);
106                                 ar -= RED(out);
107                                 ag -= GREEN(out);
108                                 ab -= BLUE(out);
109                                 divisor--;
110                         }
111
112                         if(j < blur_len - half) {
113                                 uint32_t in = *(sptr + half);
114                                 ar += RED(in);
115                                 ag += GREEN(in);
116                                 ab += BLUE(in);
117                                 divisor++;
118                         }
119
120                         r = ar / divisor;
121                         g = ag / divisor;
122                         b = ab / divisor;
123
124                         r = MAX(MIN(r, 255), 0);
125                         g = MAX(MIN(g, 255), 0);
126                         b = MAX(MIN(b, 255), 0);
127
128                         *dptr = RGB(r, g, b);
129                         dptr += dir == BLUR_HORIZ ? 1 : x;
130                         sptr++;
131                 }
132
133         }
134
135         if(dir == BLUR_BOTH) {
136                 fast_blur(BLUR_HORIZ, amount, buf, x, y);
137         }
138 }