Added some typedef'ed functions for readability.
[wmaker-crm.git] / wrlib / convolve.c
blob08f4237cd72a8ff589944d7fb68094a1ee649e3c
1 /*
2 * Raster graphics library
3 *
4 * Copyright (c) 1997-2000 Alfredo K. Kojima
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <config.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <X11/Xlib.h>
28 #include "wraster.h"
32 *----------------------------------------------------------------------
33 * RBlurImage--
34 * Apply 3x3 1 1 1 low pass, convolution mask to image.
35 * 1 2 1
36 * 1 1 1 /10
37 *----------------------------------------------------------------------
39 int
40 RBlurImage(RImage *image)
42 register int x, y;
43 register int tmp;
44 unsigned char *ptr, *nptr;
45 unsigned char *pptr=NULL, *tmpp;
46 int ch = image->format == RRGBAFormat ? 4 : 3;
48 pptr = malloc(image->width * ch);
49 if (!pptr) {
50 RErrorCode = RERR_NOMEMORY;
51 return False;
54 #define MASK(prev, cur, next, ch)\
55 (*(prev-ch) + *prev + *(prev+ch)\
56 +*(cur-ch) + 2 * *cur + *(cur+ch)\
57 +*(next-ch) + *next + *(next+ch)) / 10
59 memcpy(pptr, image->data, image->width * ch);
61 ptr = image->data;
62 nptr = ptr + image->width*ch;
63 tmpp = pptr;
65 if (ch == 3) {
66 ptr+=3;
67 nptr+=3;
68 pptr+=3;
70 for (y = 1; y < image->height-1; y++) {
72 for (x = 1; x < image->width-1; x++) {
73 tmp = *ptr;
74 *ptr = MASK(pptr, ptr, nptr, 3);
75 *pptr = tmp;
76 ptr++; nptr++; pptr++;
78 tmp = *ptr;
79 *ptr = MASK(pptr, ptr, nptr, 3);
80 *pptr = tmp;
81 ptr++; nptr++; pptr++;
83 tmp = *ptr;
84 *ptr = MASK(pptr, ptr, nptr, 3);
85 *pptr = tmp;
86 ptr++; nptr++; pptr++;
88 pptr = tmpp;
89 ptr+=6;
90 nptr+=6;
91 pptr+=6;
93 } else {
94 ptr+=4;
95 nptr+=4;
96 pptr+=4;
98 for (y = 1; y < image->height-1; y++) {
99 for (x = 1; x < image->width-1; x++) {
100 tmp = *ptr;
101 *ptr = MASK(pptr, ptr, nptr, 4);
102 *pptr = tmp;
103 ptr++; nptr++; pptr++;
105 tmp = *ptr;
106 *ptr = MASK(pptr, ptr, nptr, 4);
107 *pptr = tmp;
108 ptr++; nptr++; pptr++;
110 tmp = *ptr;
111 *ptr = MASK(pptr, ptr, nptr, 4);
112 *pptr = tmp;
113 ptr++; nptr++; pptr++;
115 tmp = *ptr;
116 *ptr = MASK(pptr, ptr, nptr, 4);
117 *pptr = tmp;
118 ptr++; nptr++; pptr++;
120 pptr = tmpp;
121 ptr+=8;
122 nptr+=8;
123 pptr+=8;
128 return True;
132 #if 0
134 REdgeDetectImage(RImage *image)
136 register int x, y, d1, d2, d3, d4, rsum;
137 int w;
138 unsigned char *r, *g, *b, *a;
139 unsigned char *dr, *dg, *db, *da;
140 unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL;
141 RImage *image2;
144 image2 = RCloneImage(image);
146 pr = alloca(image->width*sizeof(char));
147 if (!pr)
148 goto outofmem;
150 pg = alloca(image->width*sizeof(char));
151 if (!pg)
152 goto outofmem;
154 pb = alloca(image->width*sizeof(char));
155 if (!pb)
156 goto outofmem;
158 pa = alloca(image->width*sizeof(char));
159 if (!pa)
160 goto outofmem;
163 r = image->data[0];
164 g = image->data[1];
165 b = image->data[2];
166 a = image->data[3];
168 dr = image2->data[0];
169 dg = image2->data[1];
170 db = image2->data[2];
171 da = image2->data[3];
174 for (x=0; x<image->width; x++) {
175 *(dr++) = *(r++);
176 *(dg++) = *(g++);
177 *(db++) = *(b++);
180 w = image->width;
182 for (y=1; y<image->height-1; y++) {
183 dr[w-1] = r[w-1];
184 dg[w-1] = g[w-1];
185 db[w-1] = b[w-1];
187 *(dr++) = *(r++);
188 *(dg++) = *(g++);
189 *(db++) = *(b++);
191 for (x=1; x<image->width-1; x++) {
192 d1 = r[w+1] - r[-w-1];
193 d2 = r[1] - r[-1];
194 d3 = r[-w+1] - r[w-1];
195 d4 = r[-w] - r[w];
197 rsum = d1 + d2 + d3;
198 if (rsum < 0) rsum = -rsum;
199 d1 = d1 - d2 - d4; /* vertical gradient */
200 if (d1 < 0) d1 = -d1;
201 if (d1 > rsum) rsum = d1;
202 rsum /= 3;
204 *(dr++) = rsum;
206 d1 = g[w+1] - g[-w-1];
207 d2 = g[1] - g[-1];
208 d3 = g[-w+1] - g[w-1];
209 d4 = g[-w] - g[w];
211 rsum = d1 + d2 + d3;
212 if (rsum < 0) rsum = -rsum;
213 d1 = d1 - d2 - d4; /* vertical gradient */
214 if (d1 < 0) d1 = -d1;
215 if (d1 > rsum) rsum = d1;
216 rsum /= 3;
218 *(dg++) = rsum;
220 d1 = b[w+1] - b[-w-1];
221 d2 = b[1] - b[-1];
222 d3 = b[-w+1] - b[w-1];
223 d4 = b[-w] - b[w];
225 rsum = d1 + d2 + d3;
226 if (rsum < 0) rsum = -rsum;
227 d1 = d1 - d2 - d4; /* vertical gradient */
228 if (d1 < 0) d1 = -d1;
229 if (d1 > rsum) rsum = d1;
230 rsum /= 3;
232 *(db++) = rsum;
234 r++;
235 g++;
236 b++;
238 r++;
239 g++;
240 b++;
242 dr++;
243 dg++;
244 db++;
247 r = image->data[0];
248 image2->data[0] = r;
249 g = image->data[1];
250 image2->data[1] = g;
251 b = image->data[2];
252 image2->data[2] = b;
253 RDestroyImage(image2);
256 #undef MASK
258 return True;
263 RSmoothImage(RImage *image)
265 register int x, y;
266 register int v, w;
267 unsigned char *ptr;
268 int ch = image->format == RRGBAFormat;
270 ptr = image->data;
273 w = image->width*ch;
274 for (y=0; y<image->height - 1; y++) {
275 for (x=0; x<image->width - 1; x++) {
276 v = *ptr + 2 * *(ptr + ch) + 2 * *(ptr + w) + *(ptr + w + ch);
277 *ptr = v/6;
278 v = *(ptr+1) + 2 * *(ptr+1 + ch) + 2 * *(ptr+1 + w) + *(ptr+1 + w + ch);
279 *(ptr+1) = v/6;
280 v = *ptr + 2 * *(ptr+2 + ch) + 2 * *(ptr+2 + w) + *(ptr+2 + w + ch);
281 *(ptr+2) = v/6;
283 ptr+= ch;
285 /* last column */
286 v = 3 * *ptr + 3 * *(ptr + w);
287 *ptr = v/6;
288 v = 3 * *ptr + 3 * *(ptr+1 + w);
289 *(ptr+1) = v/6;
290 v = 3 * *ptr + 3 * *(ptr+2 + w);
291 *(ptr+2) = v/6;
293 ptr+= ch;
296 /* last line */
297 for (x=0; x<image->width - 1; x++) {
298 v = 3 * *ptr + 3 * *(ptr + ch);
299 *ptr = v/6;
300 v = 3 * *(ptr+1) + 3 * *(ptr+1 + ch);
301 *(ptr+1) = v/6;
302 v = 3 * *(ptr+2) + 3 * *(ptr+2 + ch);
303 *(ptr+2) = v/6;
305 ptr+= ch;
308 return True;
310 #endif