Initial revision
[wmaker-crm.git] / wrlib / convolve.c
blob8631adc3e9c2f6bf06dfa6ea06ef661e3ce18f0b
1 /*
2 * Raster graphics library
3 *
4 * Copyright (c) 1997 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>
23 /* AIX requires this to be the first thing in the file. */
24 #ifdef __GNUC__
25 # define alloca __builtin_alloca
26 #else
27 # if HAVE_ALLOCA_H
28 # include <alloca.h>
29 # else
30 # ifdef _AIX
31 # pragma alloca
32 # else
33 # ifndef alloca /* predefined by HP cc +Olibcalls */
34 char *alloca ();
35 # endif
36 # endif
37 # endif
38 #endif
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <X11/Xlib.h>
45 #include "wraster.h"
49 *----------------------------------------------------------------------
50 * RBlurImage--
51 * Apply 3x3 1 1 1 low pass, convolution mask to image.
52 * 1 1 1
53 * 1 1 1 /9
54 *----------------------------------------------------------------------
56 int
57 RBlurImage(RImage *image)
59 register int x, y;
60 register int w, tmp;
61 unsigned char *r, *g, *b, *a;
62 unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL;
64 #define MASK(c,pc,p) ((*c + *(c-1) + *(c+1) + pc[p] + pc[p-1] + pc[p+1] \
65 + *(c+w) + *(c+w-1) + *(c+w+1))/9)
67 pr = (unsigned char*)alloca(image->width*sizeof(char));
68 if (!pr)
69 goto outofmem;
71 pg = (unsigned char*)alloca(image->width*sizeof(char));
72 if (!pg)
73 goto outofmem;
75 pb = (unsigned char*)alloca(image->width*sizeof(char));
76 if (!pb)
77 goto outofmem;
79 pa = (unsigned char*)alloca(image->width*sizeof(char));
80 if (!pa)
81 goto outofmem;
84 r = image->data[0];
85 g = image->data[1];
86 b = image->data[2];
87 a = image->data[3];
90 for (x=0; x<image->width; x++) {
91 pr[x] = *(r++);
92 pg[x] = *(g++);
93 pb[x] = *(b++);
96 w = image->width;
98 for (y=1; y<image->height-1; y++) {
99 pr[w-1] = r[w-1];
100 pg[w-1] = g[w-1];
101 pb[w-1] = b[w-1];
103 pr[0] = *(r++);
104 pg[0] = *(g++);
105 pb[0] = *(b++);
107 for (x=1; x<image->width-1; x++) {
108 tmp = *r;
109 *(r++) = MASK(r,pr,x);
110 pr[x] = tmp;
112 tmp = *g;
113 *(g++) = MASK(g,pg,x);
114 pg[x] = tmp;
116 tmp = *b;
117 *(b++) = MASK(b,pb,x);
118 pb[x] = tmp;
120 r++;
121 g++;
122 b++;
125 #undef MASK
127 #ifdef C_ALLOCA
128 alloca(0);
129 #endif
130 return True;
132 outofmem:
133 sprintf(RErrorString, "out of memory");
134 #ifdef C_ALLOCA
135 alloca(0);
136 #endif
137 return False;
145 #if 0
147 REdgeDetectImage(RImage *image)
149 register int x, y, d1, d2, d3, d4, rsum;
150 int w;
151 unsigned char *r, *g, *b, *a;
152 unsigned char *dr, *dg, *db, *da;
153 unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL;
154 RImage *image2;
157 image2 = RCloneImage(image);
159 pr = alloca(image->width*sizeof(char));
160 if (!pr)
161 goto outofmem;
163 pg = alloca(image->width*sizeof(char));
164 if (!pg)
165 goto outofmem;
167 pb = alloca(image->width*sizeof(char));
168 if (!pb)
169 goto outofmem;
171 pa = alloca(image->width*sizeof(char));
172 if (!pa)
173 goto outofmem;
176 r = image->data[0];
177 g = image->data[1];
178 b = image->data[2];
179 a = image->data[3];
181 dr = image2->data[0];
182 dg = image2->data[1];
183 db = image2->data[2];
184 da = image2->data[3];
187 for (x=0; x<image->width; x++) {
188 *(dr++) = *(r++);
189 *(dg++) = *(g++);
190 *(db++) = *(b++);
193 w = image->width;
195 for (y=1; y<image->height-1; y++) {
196 dr[w-1] = r[w-1];
197 dg[w-1] = g[w-1];
198 db[w-1] = b[w-1];
200 *(dr++) = *(r++);
201 *(dg++) = *(g++);
202 *(db++) = *(b++);
204 for (x=1; x<image->width-1; x++) {
205 d1 = r[w+1] - r[-w-1];
206 d2 = r[1] - r[-1];
207 d3 = r[-w+1] - r[w-1];
208 d4 = r[-w] - r[w];
210 rsum = d1 + d2 + d3;
211 if (rsum < 0) rsum = -rsum;
212 d1 = d1 - d2 - d4; /* vertical gradient */
213 if (d1 < 0) d1 = -d1;
214 if (d1 > rsum) rsum = d1;
215 rsum /= 3;
217 *(dr++) = rsum;
219 d1 = g[w+1] - g[-w-1];
220 d2 = g[1] - g[-1];
221 d3 = g[-w+1] - g[w-1];
222 d4 = g[-w] - g[w];
224 rsum = d1 + d2 + d3;
225 if (rsum < 0) rsum = -rsum;
226 d1 = d1 - d2 - d4; /* vertical gradient */
227 if (d1 < 0) d1 = -d1;
228 if (d1 > rsum) rsum = d1;
229 rsum /= 3;
231 *(dg++) = rsum;
233 d1 = b[w+1] - b[-w-1];
234 d2 = b[1] - b[-1];
235 d3 = b[-w+1] - b[w-1];
236 d4 = b[-w] - b[w];
238 rsum = d1 + d2 + d3;
239 if (rsum < 0) rsum = -rsum;
240 d1 = d1 - d2 - d4; /* vertical gradient */
241 if (d1 < 0) d1 = -d1;
242 if (d1 > rsum) rsum = d1;
243 rsum /= 3;
245 *(db++) = rsum;
247 r++;
248 g++;
249 b++;
251 r++;
252 g++;
253 b++;
255 dr++;
256 dg++;
257 db++;
260 r = image->data[0];
261 image2->data[0] = r;
262 g = image->data[1];
263 image2->data[1] = g;
264 b = image->data[2];
265 image2->data[2] = b;
266 RDestroyImage(image2);
269 #undef MASK
271 return True;
276 RSmoothImage(RImage *image)
278 register int x, y;
279 register int v, w;
280 unsigned char *r, *g, *b, *a;
282 r = image->data[0];
283 g = image->data[1];
284 b = image->data[2];
285 a = image->data[3];
287 w = image->width;
288 for (y=0; y<image->height - 1; y++) {
289 for (x=0; x<image->width - 1; x++) {
290 v = *r + 2 * *(r + 1) + 2 * *(r + w) + *(r + w + 1);
291 *(r++) = v/6;
293 v = *g + 2 * *(g + 1) + 2 * *(g + w) + *(g + w + 1);
294 *(g++) = v/6;
296 v = *b + 2 * *(b + 1) + 2 * *(b + w) + *(b + w + 1);
297 *(b++) = v/6;
300 /* last column */
301 v = 3 * *r + 3 * *(r + w);
302 *(r++) = v/6;
304 v = 3 * *g + 3 * *(g + w);
305 *(g++) = v/6;
307 v = 3 * *b + 3 * *(b + w);
308 *(b++) = v/6;
311 /* last line */
312 for (x=0; x<image->width - 1; x++) {
313 v = 3 * *r + 3 * *(r + 1);
314 *(r++) = v/6;
316 v = 3 * *g + 3 * *(g + 1);
317 *(g++) = v/6;
319 v = 3 * *b + 3 * *(b + 1);
320 *(b++) = v/6;
323 return True;
325 #endif