/*
 * Raster graphics library
 *
 * Copyright (c) 1997-2003 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;
		RReleaseImage(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) + 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 + 1) + 3 * *(ptr + 1 + w);
		*(ptr + 1) = v / 6;
		v = 3 * *(ptr + 2) + 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
