diff options
Diffstat (limited to 'src/engine/interlace.c')
-rw-r--r-- | src/engine/interlace.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/engine/interlace.c b/src/engine/interlace.c new file mode 100644 index 0000000..0971a5a --- /dev/null +++ b/src/engine/interlace.c @@ -0,0 +1,134 @@ +#include <config.h> +#ifndef _plan9_ +#ifdef NO_MALLOC_H +#include <stdlib.h> +#else +#include <malloc.h> +#endif +#include <stdio.h> /*for NULL */ +#include <string.h> /*for memcpy */ +#else +#include <u.h> +#include <libc.h> +#include <stdio.h> +#endif +#include <filter.h> +struct intdata { + unsigned char *lastent; + int changed; + int first; +}; +static int requirement(struct filter *f, struct requirements *r) +{ + r->nimages = 1; + r->flags |= IMAGEDATA; + return (f->next->action->requirement(f->next, r)); +} + +static int initialize(struct filter *f, struct initdata *i) +{ + int x; + struct intdata *d = (struct intdata *) f->data; + pixel_t **lines1 = + (pixel_t **) malloc(sizeof(*lines1) * i->image->height / 2), + **lines2 = + (pixel_t **) malloc(sizeof(*lines2) * i->image->height / 2); + if (lines1 == NULL) + return 0; + inhermisc(f, i); + d->first = 1; + if (lines2 == NULL) { + free(lines1); + return 0; + } + if (f->childimage != NULL) + destroy_image(f->childimage); + f->image = i->image; + f->image->flags |= PROTECTBUFFERS; + i->flags |= DATALOST; + for (x = 0; x < (i->image->height) / 2; x++) { + lines1[x] = i->image->currlines[x * 2]; + lines2[x] = i->image->currlines[x * 2 + 1]; + } + f->childimage = i->image = + create_image_lines(i->image->width, (i->image->height) / 2, 2, + lines1, lines2, i->image->palette, NULL, + FREELINES | PROTECTBUFFERS, + f->image->pixelwidth, + f->image->pixelheight * 2); + if (i->image == NULL) { + free(lines1); + free(lines2); + return 0; + } + return (f->previous->action->initialize(f->previous, i)); +} + +static struct filter *getinstance(CONST struct filteraction *a) +{ + struct filter *f = createfilter(a); + struct intdata *i = (struct intdata *) calloc(1, sizeof(*i)); + f->data = i; + f->name = "Interlace filter"; + return (f); +} + +static void destroyinstance(struct filter *f) +{ + free(f->data); + if (f->childimage != NULL) + destroy_image(f->childimage); + free(f); +} + +static int doit(struct filter *f, int flags, int time) +{ + struct intdata *i = (struct intdata *) f->data; + int val; + if (!(f->req.flags & IMAGEDATA) + && f->childimage->currlines[0] == i->lastent) + f->childimage->flip(f->childimage); + i->lastent = f->childimage->currlines[0]; + val = f->previous->action->doit(f->previous, flags, time); + if (i->first) { + int y; + for (y = 0; y < f->childimage->height; y++) + memcpy(f->childimage->oldlines[y], f->childimage->currlines[y], + f->childimage->width * f->childimage->bytesperpixel); + i->first = 0; + } + if (val & CHANGED) + i->changed = 1, val |= ANIMATION; + else { + if (i->changed) + val |= CHANGED; + i->changed = 0; + } + return (val); +} + +static void convertup(struct filter *f, int *x, int *y) +{ + *y *= 2; + f->next->action->convertup(f->next, x, y); +} + +static void convertdown(struct filter *f, int *x, int *y) +{ + *y /= 2; + f->previous->action->convertdown(f->previous, x, y); +} + +CONST struct filteraction interlace_filter = { + "Interlace filter", + "interlace", + 0, + getinstance, + destroyinstance, + doit, + requirement, + initialize, + convertup, + convertdown, + NULL +}; |