diff options
author | Bernie Innocenti <bernie@codewiz.org> | 2010-05-03 21:53:47 (GMT) |
---|---|---|
committer | Bernie Innocenti <bernie@codewiz.org> | 2010-05-03 21:53:47 (GMT) |
commit | 1030dc837b10a03a02a85d5504cbeec168ce49e2 (patch) | |
tree | 698eefa87ac437deaf36a4141b326f8ce7986692 /src/engine/anti.c |
Import XaoS r489 (trunk after version 3.5)
Diffstat (limited to 'src/engine/anti.c')
-rw-r--r-- | src/engine/anti.c | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/src/engine/anti.c b/src/engine/anti.c new file mode 100644 index 0000000..819d33e --- /dev/null +++ b/src/engine/anti.c @@ -0,0 +1,358 @@ +#include <config.h> +#ifndef _plan9_ +#ifndef __cplusplus +#include <math.h> +#endif +#ifndef NO_MALLOC_H +#include <malloc.h> +#endif +#include <string.h> +#include <config.h> +#include <stdio.h> +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif +#include <stdlib.h> +#else +#include <u.h> +#include <libc.h> +#include <stdio.h> +#endif +#include <xerror.h> +#include <filter.h> +#include <fractal.h> +#include <xthread.h> +struct antidata { + int shift; +}; +static int requirement(struct filter *f, struct requirements *r) +{ + f->req = *r; + r->nimages = 1; + r->supportedmask = TRUECOLOR24 | TRUECOLOR | TRUECOLOR16 | GRAYSCALE; + return (f->next->action->requirement(f->next, r)); +} + +static int initialize(struct filter *f, struct initdata *i) +{ + struct antidata *s = (struct antidata *) f->data; + if (i->image->width * i->image->height * i->image->bytesperpixel * 2 * + 16 > 15 * 1024 * 1024) { + s->shift = 1; + } else { + s->shift = 2; + } + inhermisc(f, i); + if (!inherimage + (f, i, TOUCHIMAGE | IMAGEDATA, + (int) (((unsigned int) i->image->width) << s->shift), + (int) (((unsigned int) i->image->height) << s->shift), NULL, 0, + 0)) + return 0; + if (i->image == NULL) { + return 0; + } + return (f->previous->action->initialize(f->previous, i)); +} + +static struct filter *getinstance(CONST struct filteraction *a) +{ + struct filter *f = createfilter(a); + struct antidata *i = (struct antidata *) calloc(1, sizeof(*i)); + f->childimage = NULL; + f->data = i; + f->name = "Antialiasing"; + return (f); +} + +static void destroyinstance(struct filter *f) +{ + destroyinheredimage(f); + free(f->data); + free(f); +} + +static void antigray(void *data, struct taskinfo *task, int r1, int r2) +{ + struct filter *f = (struct filter *) data; + struct image *srci = f->childimage, *desti = f->image; + struct antidata *s = (struct antidata *) f->data; + register unsigned char *src; + unsigned char *destend, *dest; + unsigned int ystart, y; + unsigned int xstart; + register unsigned int sum; + unsigned int xstep = (1U << (s->shift)); + int i; + for (i = r1; i < r2; i++) { + dest = (unsigned char *) desti->currlines[i]; + destend = dest + desti->width; + ystart = ((unsigned int) i) << s->shift; + xstart = 0; + for (; dest < destend; dest++) { + if (xstep > 2) { + sum = 0; + for (y = 0; y < 4; y++) { + src = + (unsigned char *) srci->currlines[y + ystart] + + xstart; + sum += (unsigned int) src[0]; + sum += (unsigned int) src[1]; + sum += (unsigned int) src[2]; + sum += (unsigned int) src[3]; + } + sum >>= 4; + } else { + src = (unsigned char *) srci->currlines[ystart] + xstart; + sum = (unsigned int) src[0]; + sum += (unsigned int) src[1]; + src = + (unsigned char *) srci->currlines[ystart + 1] + xstart; + sum += (unsigned int) src[0]; + sum += (unsigned int) src[1]; + sum >>= 2; + } + *dest = (pixel8_t) sum; + xstart += xstep; + } + } +} + +#ifdef STRUECOLOR24 +static void anti24(void *data, struct taskinfo *task, int r1, int r2) +{ + struct filter *f = (struct filter *) data; + struct image *srci = f->childimage, *desti = f->image; + struct antidata *s = (struct antidata *) f->data; + register unsigned char *src; + unsigned char *destend, *dest; + unsigned int ystart, y; + unsigned int xstart; + register unsigned int sum; + unsigned int xstep = ((1U << s->shift) - 1) * 3; + int c = 0; + int i; + if (!srci->palette->info.truec.byteexact) { + x_fatalerror + ("Antialiasing filter:Unsupported colormask! Ask authors to add support for this :)"); + } + for (i = r1; i < r2; i++) { + dest = (unsigned char *) desti->currlines[i]; + destend = dest + desti->width * 3; + ystart = ((unsigned int) i) << s->shift; + xstart = 0; + c = 1; + for (; dest < destend; dest++) { + if (s->shift > 1) { + sum = 0; + for (y = 0; y < 4; y++) { + src = + (unsigned char *) srci->currlines[y + ystart] + + xstart; + sum += (unsigned int) src[0]; + sum += (unsigned int) src[3]; + sum += (unsigned int) src[6]; + sum += (unsigned int) src[9]; + } + sum >>= 4; + } else { + src = (unsigned char *) srci->currlines[ystart] + xstart; + sum = (unsigned int) src[0]; + sum += (unsigned int) src[3]; + src = + (unsigned char *) srci->currlines[ystart + 1] + xstart; + sum += (unsigned int) src[0]; + sum += (unsigned int) src[3]; + sum >>= 2; + } + *dest = (unsigned char) sum; + if (c == 3) + c = 0, xstart += xstep; + c++; + xstart++; + } + } +} +#endif +#ifdef SUPPORT16 +#define MASKR1 ((unsigned int)((31+31744)+(31*65536*32))) +#define MASKR2 ((unsigned int)((31+31744)*(65536/32)+31)) + +#define MASKRH1 (31+31744) +#define MASKRH2 (31*32) +static void anti16(void *data, struct taskinfo *task, int r1, int r2) +{ + struct filter *f = (struct filter *) data; + struct image *srci = f->childimage, *desti = f->image; + struct antidata *s = (struct antidata *) f->data; + register unsigned int *src; + unsigned short *destend, *dest; + int ystart, y; + int xstart; + register unsigned int sum1 = 0, sum2 = 0, sum; + unsigned int xstep = 1U << (s->shift - 1); + int i; + unsigned int mask1 = + (srci->palette->info.truec. + mask2 | (srci->palette->info.truec.mask1 << 16)) >> 4; + unsigned int mask2 = + srci->palette->info.truec.mask1 | (srci->palette->info.truec. + mask2 << 16); + for (i = r1; i < r2; i++) { + dest = (unsigned short *) desti->currlines[i]; + destend = dest + desti->width; + ystart = ((unsigned int) i) << s->shift; + xstart = 0; + for (; dest < destend; dest++) { + if (xstep > 2) { + sum1 = sum2 = 0; + for (y = 0; y < 4; y++) { + src = + (unsigned int *) srci->currlines[y + ystart] + + xstart; + sum1 += ((unsigned int) src[0] >> 4) & mask1; + sum2 += ((unsigned int) src[0] >> 4) & mask2; + sum1 += (unsigned int) src[1] & mask1; + sum2 += (unsigned int) src[1] & mask2; + } + sum = ((sum1 >> 4) + (sum2 >> 16)) >> 4; + sum1 = (sum2 + (sum1 >> 12)) >> 4; + } else { + src = (unsigned int *) srci->currlines[ystart] + xstart; + sum1 = ((unsigned int) src[0] >> 4) & mask1; + sum2 = (unsigned int) src[0] & mask2; + src = + (unsigned int *) srci->currlines[ystart + 1] + xstart; + sum1 += ((unsigned int) src[0] >> 4) & mask1; + sum2 += (unsigned int) src[0] & mask2; + sum = ((sum1 << 4) + (sum2 >> 16)) >> 2; + sum1 = (sum2 + (sum1 >> 12)) >> 2; + } + *dest = + (sum & srci->palette->info.truec. + mask2) | (sum1 & srci->palette->info.truec.mask1); + xstart += xstep; + } + } +} +#endif + + +#define MASK1 0x00ff00ff +static void anti32(void *data, struct taskinfo *task, int r1, int r2) +{ + struct filter *f = (struct filter *) data; + struct image *srci = f->childimage, *desti = f->image; + struct antidata *s = (struct antidata *) f->data; + register unsigned int *src; + unsigned int *destend, *dest; + unsigned int ystart, y; + unsigned int xstart; + register unsigned int sum1 = 0, sum2 = 0; + unsigned int xstep = 1U << s->shift; + int i; + if (!srci->palette->info.truec.byteexact) { + x_fatalerror + ("Antialiasing filter:Unsupported colormask2! ask authors to add support for this :)"); + } + for (i = r1; i < r2; i++) { + dest = (unsigned int *) desti->currlines[i]; + destend = dest + desti->width; + ystart = ((unsigned int) i) << s->shift; + xstart = 0; + for (; dest < destend; dest++) { + if (xstep > 2) { + sum1 = sum2 = 0; + for (y = 0; y < 4; y++) { + src = + (unsigned int *) srci->currlines[y + ystart] + + xstart; + sum1 += (unsigned int) src[0] & MASK1; + sum2 += ((unsigned int) src[0] >> 8) & MASK1; + sum1 += (unsigned int) src[1] & MASK1; + sum2 += ((unsigned int) src[1] >> 8) & MASK1; + sum1 += (unsigned int) src[2] & MASK1; + sum2 += ((unsigned int) src[2] >> 8) & MASK1; + sum1 += (unsigned int) src[3] & MASK1; + sum2 += ((unsigned int) src[3] >> 8) & MASK1; + } + sum1 >>= 4; + sum2 >>= 4; + } else { + src = (unsigned int *) srci->currlines[ystart] + xstart; + sum1 = (unsigned int) src[0] & MASK1; + sum2 = ((unsigned int) src[0] >> 8) & MASK1; + sum1 += (unsigned int) src[1] & MASK1; + sum2 += ((unsigned int) src[1] >> 8) & MASK1; + src = + (unsigned int *) srci->currlines[ystart + 1] + xstart; + sum1 += (unsigned int) src[0] & MASK1; + sum2 += ((unsigned int) src[0] >> 8) & MASK1; + sum1 += (unsigned int) src[1] & MASK1; + sum2 += ((unsigned int) src[1] >> 8) & MASK1; + sum1 >>= 2; + sum2 >>= 2; + } + *dest = (sum1 & MASK1) | ((sum2 & MASK1) << 8); + xstart += xstep; + } + } +} + +static int doit(struct filter *f, int flags, int time1) +{ + int val; + updateinheredimage(f); + val = f->previous->action->doit(f->previous, flags, time1); + switch (f->image->palette->type) { + case GRAYSCALE: + xth_function(antigray, f, f->image->height); + break; +#ifdef STRUECOLOR24 + case TRUECOLOR24: + xth_function(anti24, f, f->image->height); + break; +#endif +#ifdef SUPPORT16 + case TRUECOLOR16: + xth_function(anti16, f, f->image->height); + break; +#endif + case TRUECOLOR: + xth_function(anti32, f, f->image->height); + break; + } + xth_sync(); + return val; +} + +static void convertup(struct filter *f, int *x, int *y) +{ + struct antidata *s = (struct antidata *) f->data; + *x >>= s->shift; + *y >>= s->shift; + f->next->action->convertup(f->next, x, y); +} + +static void convertdown(struct filter *f, int *x, int *y) +{ + struct antidata *s = (struct antidata *) f->data; + *x <<= s->shift; + *y <<= s->shift; + f->previous->action->convertdown(f->previous, x, y); +} + + +CONST struct filteraction antialias_filter = { + "Antialiasing", + "anti", + 0, + getinstance, + destroyinstance, + doit, + requirement, + initialize, + convertup, + convertdown, + NULL, +}; |