oops =- add

SVN revision: 2483
This commit is contained in:
Carsten Haitzler 2000-04-13 17:10:50 +00:00
parent a8228e774a
commit ea970ca51a
2 changed files with 253 additions and 0 deletions

214
src/filter.c Normal file
View File

@ -0,0 +1,214 @@
#include "common.h"
#include <X11/Xlib.h>
#include "colormod.h"
#include "image.h"
#include "blend.h"
#include "filter.h"
/*\ Create and return an empty filter struct \*/
ImlibFilter *
__imlib_CreateFilter(int size)
{
ImlibFilter *fil;
fil = malloc(sizeof(ImlibFilter));
if (size > 0) {
fil->alpha.pixels = malloc(size * sizeof(ImlibFilterPixel));
fil->red.pixels = malloc(size * sizeof(ImlibFilterPixel));
fil->green.pixels = malloc(size * sizeof(ImlibFilterPixel));
fil->blue.pixels = malloc(size * sizeof(ImlibFilterPixel));
fil->alpha.size = size;
fil->red.size = size;
fil->green.size = size;
fil->blue.size = size;
} else {
fil->alpha.pixels = 0;
fil->red.pixels = 0;
fil->green.pixels = 0;
fil->blue.pixels = 0;
fil->alpha.size = 0;
fil->red.size = 0;
fil->green.size = 0;
fil->blue.size = 0;
}
fil->alpha.entries = 0;
fil->red.entries = 0;
fil->green.entries = 0;
fil->blue.entries = 0;
fil->alpha.div = 0;
fil->red.div = 0;
fil->green.div = 0;
fil->blue.div = 0;
fil->alpha.cons = 0;
fil->red.cons = 0;
fil->green.cons = 0;
fil->blue.cons = 0;
return fil;
}
/*\ Free a filter struct \*/
void
__imlib_FreeFilter(ImlibFilter *fil)
{
free(fil->alpha.pixels);
free(fil->red.pixels);
free(fil->green.pixels);
free(fil->blue.pixels);
free(fil);
}
void
__imlib_FilterSetColor(ImlibFilterColor *fil, int x, int y,
int a, int r, int g, int b)
{
int i;
ImlibFilterPixel *pix = fil->pixels;
/*\ Look for an entry matching (x, y) \*/
for (i = fil->entries; --i >= 0; ) {
if ((pix[i].xoff == x) && (pix[i].yoff == y))
break;
}
/*\ If all zero, remove the found entry \*/
if (!(a | r | g | b)) {
if (i >= 0) {
while (i < fil->entries) {
pix[i] = pix[i + 1];
}
fil->entries--;
}
return;
}
/*\ No match, then make a new entry \*/
if (i < 0) i = fil->entries;
if (i >= fil->size) {
fil->size += 4;
pix = realloc(pix, (fil->size * sizeof(ImlibFilterPixel)));
if (!pix) return;
fil->pixels = pix;
}
if (i >= fil->entries) fil->entries = i + 1;
pix[i].xoff = x;
pix[i].yoff = y;
pix[i].a = a;
pix[i].r = r;
pix[i].g = g;
pix[i].b = b;
}
/*\ Set the divisors manually \*/
void
__imlib_FilterDivisors(ImlibFilter *fil, int a, int r, int g, int b)
{
fil->alpha.div = a;
fil->red.div = r;
fil->green.div = g;
fil->blue.div = b;
}
/*\ Set the constants \*/
void
__imlib_FilterConstants(ImlibFilter *fil, int a, int r, int g, int b)
{
fil->alpha.cons = a;
fil->red.cons = r;
fil->green.cons = g;
fil->blue.cons = b;
}
static int
__imlib_FilterCalcDiv(ImlibFilterColor *fil)
{
int i, ret;
ImlibFilterPixel *pix;
if (fil->div) return fil->div;
ret = 0;
pix = fil->pixels;
for (i = fil->entries; --i >= 0; ) {
ret += pix->a + pix->r + pix->g + pix->b;
pix++;
}
return ret;
}
static int
__imlib_FilterGet(ImlibFilterColor *fil, DATA32 *data,
int w, int h, int x, int y)
{
int i, off, ret;
ImlibFilterPixel *pix;
DATA32 *p;
ret = fil->cons;
pix = fil->pixels;
for (i = fil->entries; --i >= 0; ) {
off = x + pix->xoff;
if (off < 0) off = 0;
if (off >= w) off = w - 1;
p = data + off;
off = y + pix->yoff;
if (off < 0) off = 0;
if (off >= h) off = h - 1;
p += off * w;
ret += A_VAL(p) * pix->a + R_VAL(p) * pix->r +
G_VAL(p) * pix->g + B_VAL(p) * pix->b;
pix++;
}
return ret;
}
/*\ Correct saturation from [-32768, 32767] to [0, 255] \*/
#define SATURATE(x) ((((x) | (!((x) >> 8) - 1)) & (~((x) >> 31))) & 0xff)
/*\ Filter an image with the a, r, g, b filters in fil
|*| NB: This is currently not very optimal, and could probably be improved
\*/
void
__imlib_FilterImage(ImlibImage *im, ImlibFilter *fil)
{
int x, y, a, r, g, b, ad, rd, gd, bd;
ImlibFilterPixel *pix;
DATA32 *data, *p1, *p2;
data = malloc(im->w * im->h * sizeof(DATA32));
if (!data) return;
ad = __imlib_FilterCalcDiv(&fil->alpha);
rd = __imlib_FilterCalcDiv(&fil->red);
gd = __imlib_FilterCalcDiv(&fil->green);
bd = __imlib_FilterCalcDiv(&fil->blue);
p1 = im->data;
p2 = data;
for (y = 0; y < im->h; y++) {
for (x = 0; x < im->w; x++) {
*p2 = *p1;
if (ad) {
a = __imlib_FilterGet(&fil->alpha, im->data, im->w, im->h, x, y);
a /= ad;
A_VAL(p2) = SATURATE(a);
}
if (rd) {
r = __imlib_FilterGet(&fil->red, im->data, im->w, im->h, x, y);
r /= rd;
R_VAL(p2) = SATURATE(r);
}
if (gd) {
g = __imlib_FilterGet(&fil->green, im->data, im->w, im->h, x, y);
g /= gd;
G_VAL(p2) = SATURATE(g);
}
if (bd) {
b = __imlib_FilterGet(&fil->blue, im->data, im->w, im->h, x, y);
b /= bd;
B_VAL(p2) = SATURATE(b);
}
p1++;
p2++;
}
}
free(im->data);
im->data = data;
}

39
src/filter.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __FILTER
#define __FILTER 1
typedef struct _imlib_filter ImlibFilter;
typedef struct _imlib_filter_color ImlibFilterColor;
typedef struct _imlib_filter_pixel ImlibFilterPixel;
struct _imlib_filter_pixel
{
int xoff, yoff;
int a, r, g, b;
};
struct _imlib_filter_color
{
int size, entries;
int div, cons;
ImlibFilterPixel *pixels;
};
struct _imlib_filter
{
ImlibFilterColor alpha, red, green, blue;
};
ImlibFilter *
__imlib_CreateFilter(int size);
void
__imlib_FreeFilter(ImlibFilter *fil);
void
__imlib_FilterSet(ImlibFilterColor *fil, int x, int y,
int a, int r, int g, int b);
void
__imlib_FilterDivisors(ImlibFilter *fil, int a, int r, int g, int b);
void
__imlib_FilterConstants(ImlibFilter *fil, int a, int r, int g, int b);
void
__imlib_FilterImage(ImlibImage *im, ImlibFilter *fil);
#endif