forked from old/legacy-imlib2
parent
a8228e774a
commit
ea970ca51a
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue