1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 12:28:22 +01:00
Files
wmaker/wrlib/convolve.c

311 lines
6.2 KiB
C

/*
* Raster graphics library
*
* Copyright (c) 1997-2000 Alfredo K. Kojima
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include "wraster.h"
/*
*----------------------------------------------------------------------
* RBlurImage--
* Apply 3x3 1 1 1 low pass, convolution mask to image.
* 1 2 1
* 1 1 1 /10
*----------------------------------------------------------------------
*/
int
RBlurImage(RImage *image)
{
register int x, y;
register int tmp;
unsigned char *ptr, *nptr;
unsigned char *pptr=NULL, *tmpp;
int ch = image->format == RRGBAFormat ? 4 : 3;
pptr = malloc(image->width * ch);
if (!pptr) {
RErrorCode = RERR_NOMEMORY;
return False;
}
#define MASK(prev, cur, next, ch)\
(*(prev-ch) + *prev + *(prev+ch)\
+*(cur-ch) + 2 * *cur + *(cur+ch)\
+*(next-ch) + *next + *(next+ch)) / 10
memcpy(pptr, image->data, image->width * ch);
ptr = image->data;
nptr = ptr + image->width*ch;
tmpp = pptr;
if (ch == 3) {
ptr+=3;
nptr+=3;
pptr+=3;
for (y = 1; y < image->height-1; y++) {
for (x = 1; x < image->width-1; x++) {
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 3);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 3);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 3);
*pptr = tmp;
ptr++; nptr++; pptr++;
}
pptr = tmpp;
ptr+=6;
nptr+=6;
pptr+=6;
}
} else {
ptr+=4;
nptr+=4;
pptr+=4;
for (y = 1; y < image->height-1; y++) {
for (x = 1; x < image->width-1; x++) {
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
tmp = *ptr;
*ptr = MASK(pptr, ptr, nptr, 4);
*pptr = tmp;
ptr++; nptr++; pptr++;
}
pptr = tmpp;
ptr+=8;
nptr+=8;
pptr+=8;
}
}
return True;
}
#if 0
int
REdgeDetectImage(RImage *image)
{
register int x, y, d1, d2, d3, d4, rsum;
int w;
unsigned char *r, *g, *b, *a;
unsigned char *dr, *dg, *db, *da;
unsigned char *pr=NULL, *pg=NULL, *pb=NULL, *pa=NULL;
RImage *image2;
image2 = RCloneImage(image);
pr = alloca(image->width*sizeof(char));
if (!pr)
goto outofmem;
pg = alloca(image->width*sizeof(char));
if (!pg)
goto outofmem;
pb = alloca(image->width*sizeof(char));
if (!pb)
goto outofmem;
pa = alloca(image->width*sizeof(char));
if (!pa)
goto outofmem;
r = image->data[0];
g = image->data[1];
b = image->data[2];
a = image->data[3];
dr = image2->data[0];
dg = image2->data[1];
db = image2->data[2];
da = image2->data[3];
for (x=0; x<image->width; x++) {
*(dr++) = *(r++);
*(dg++) = *(g++);
*(db++) = *(b++);
}
w = image->width;
for (y=1; y<image->height-1; y++) {
dr[w-1] = r[w-1];
dg[w-1] = g[w-1];
db[w-1] = b[w-1];
*(dr++) = *(r++);
*(dg++) = *(g++);
*(db++) = *(b++);
for (x=1; x<image->width-1; x++) {
d1 = r[w+1] - r[-w-1];
d2 = r[1] - r[-1];
d3 = r[-w+1] - r[w-1];
d4 = r[-w] - r[w];
rsum = d1 + d2 + d3;
if (rsum < 0) rsum = -rsum;
d1 = d1 - d2 - d4; /* vertical gradient */
if (d1 < 0) d1 = -d1;
if (d1 > rsum) rsum = d1;
rsum /= 3;
*(dr++) = rsum;
d1 = g[w+1] - g[-w-1];
d2 = g[1] - g[-1];
d3 = g[-w+1] - g[w-1];
d4 = g[-w] - g[w];
rsum = d1 + d2 + d3;
if (rsum < 0) rsum = -rsum;
d1 = d1 - d2 - d4; /* vertical gradient */
if (d1 < 0) d1 = -d1;
if (d1 > rsum) rsum = d1;
rsum /= 3;
*(dg++) = rsum;
d1 = b[w+1] - b[-w-1];
d2 = b[1] - b[-1];
d3 = b[-w+1] - b[w-1];
d4 = b[-w] - b[w];
rsum = d1 + d2 + d3;
if (rsum < 0) rsum = -rsum;
d1 = d1 - d2 - d4; /* vertical gradient */
if (d1 < 0) d1 = -d1;
if (d1 > rsum) rsum = d1;
rsum /= 3;
*(db++) = rsum;
r++;
g++;
b++;
}
r++;
g++;
b++;
dr++;
dg++;
db++;
}
{
r = image->data[0];
image2->data[0] = r;
g = image->data[1];
image2->data[1] = g;
b = image->data[2];
image2->data[2] = b;
RDestroyImage(image2);
}
#undef MASK
return True;
}
int
RSmoothImage(RImage *image)
{
register int x, y;
register int v, w;
unsigned char *ptr;
int ch = image->format == RRGBAFormat;
ptr = image->data;
w = image->width*ch;
for (y=0; y<image->height - 1; y++) {
for (x=0; x<image->width - 1; x++) {
v = *ptr + 2 * *(ptr + ch) + 2 * *(ptr + w) + *(ptr + w + ch);
*ptr = v/6;
v = *(ptr+1) + 2 * *(ptr+1 + ch) + 2 * *(ptr+1 + w) + *(ptr+1 + w + ch);
*(ptr+1) = v/6;
v = *ptr + 2 * *(ptr+2 + ch) + 2 * *(ptr+2 + w) + *(ptr+2 + w + ch);
*(ptr+2) = v/6;
ptr+= ch;
}
/* last column */
v = 3 * *ptr + 3 * *(ptr + w);
*ptr = v/6;
v = 3 * *ptr + 3 * *(ptr+1 + w);
*(ptr+1) = v/6;
v = 3 * *ptr + 3 * *(ptr+2 + w);
*(ptr+2) = v/6;
ptr+= ch;
}
/* last line */
for (x=0; x<image->width - 1; x++) {
v = 3 * *ptr + 3 * *(ptr + ch);
*ptr = v/6;
v = 3 * *(ptr+1) + 3 * *(ptr+1 + ch);
*(ptr+1) = v/6;
v = 3 * *(ptr+2) + 3 * *(ptr+2 + ch);
*(ptr+2) = v/6;
ptr+= ch;
}
return True;
}
#endif