struct image * create_image_mem (int width, int height, int nimages, struct palette *palette, float pixelwidth, float pixelheight) { unsigned char *data = (unsigned char *) calloc (((width + 3) & ~3) * height, bytesperpixel (palette->type)); unsigned char *data1 = (unsigned char *) (nimages == 2 ? calloc (((width + 3) & ~3) * height, bytesperpixel (palette->type)) : NULL); struct image *img; if (data == NULL) { #ifdef DEBUG printf ("Image:out of memory\n"); #endif return (NULL); } if (nimages == 2 && data1 == NULL) { free (data); #ifdef DEBUG printf ("Image:out of memory2\n"); #endif return NULL; } img = create_image_cont (width, height, ((width + 3) & ~3) * bytesperpixel (palette->type), nimages, data, data1, palette, NULL, 0, pixelwidth, pixelheight); if (img == NULL) { free (data); if (data1 != NULL) free (data1); return NULL; } img->flags |= FREEDATA; return (img); }
struct image * create_image_lines (int width, int height, int nimages, pixel_t ** lines1, pixel_t ** lines2, struct palette *palette, void (*flip) (struct image * img), int flags, float pixelwidth, float pixelheight) { int i; static int version = 1; struct image *img = (struct image *) calloc (1, sizeof (*img)); if (img == NULL) return NULL; if (flip == NULL) flip = flipgeneric; img->width = width; img->height = height; img->nimages = nimages; img->bytesperpixel = bytesperpixel (palette->type); img->palette = palette; img->currimage = 0; img->flip = flip; img->flags = flags; img->version = version; version += 65535; img->currlines = lines1; img->oldlines = lines2; img->pixelwidth = pixelwidth; img->pixelheight = pixelheight; if (lines1 != NULL && (nimages != 2 || lines2 != NULL)) { img->scanline = (int) (lines1[1] - lines1[0]); if (img->scanline < 0) img->scanline = -1; else { for (i = 0; i < height; i++) { if (lines1[0] - lines1[i] != img->scanline * i) { img->scanline = -1; break; } if (nimages == 2 && lines2[0] - lines2[i] != img->scanline * i) { img->scanline = -1; break; } } } } else img->scanline = -1; return (img); }
struct image * create_subimage (struct image *simg, int width, int height, int nimages, struct palette *palette, float pixelwidth, float pixelheight) { int size = height * bytesperpixel (palette->type); int i; int shift1 = 0, shift2 = 0; struct image *img; if (size > simg->height * simg->bytesperpixel || height > simg->height || (nimages == 2 && simg->nimages == 1)) return (create_image_mem (width, height, nimages, palette, pixelwidth, pixelheight)); nimages = simg->nimages; img = create_image_lines (width, height, nimages, NULL, NULL, palette, NULL, 0, pixelwidth, pixelheight); if (img == NULL) return NULL; if ((img->currlines = (pixel_t **) malloc (sizeof (*img->currlines) * height)) == NULL) { free (img); return NULL; } if (nimages == 2) { if ((img->oldlines = (pixel_t **) malloc (sizeof (*img->oldlines) * height)) == NULL) { free (img->currlines); free (img); return NULL; } } shift1 = simg->height - img->height; shift2 = simg->width * simg->bytesperpixel - img->width * img->bytesperpixel; for (i = 0; i < img->height; i++) { img->currlines[i] = simg->currlines[i + shift1] + shift2; } if (nimages == 2) for (i = 0; i < img->height; i++) { img->oldlines[i] = simg->oldlines[i + shift1] + shift2; } img->flags |= FREELINES; img->currimage = simg->currimage; return (img); }
/* An function helping to filter create new image. * It should be called by filter in inicialization. Filter passes * width,height,pixelwidth, pixelheight * and palette he wants to pass to his child and flags defining how it works * with image(IMAGEDATA if it requires data from previous frames (like blur * filter, TOUCHIMAGE if it changes data in image(like blur or stereogram * filter but unlike interlace and NEWIMAGE if it strictly requires to create * new image) * As palette he should pass NULL to keep parents palette. Same as * (pixel)width/height should be passed 0; * * Function then aplies some heruistic in order to minimize memory * requirements. So it should share image, create image that shares image data * or create new image) * * fills f->image, f->childimage and returns 1 if sucess and 0 if fail(usually * out of memory or it is unable to fit child's requirements) * and prepares data for child call. */ int inherimage(struct filter *f, struct initdata *data, int flags, int width, int height, struct palette *palette, float pixelwidth, float pixelheight) { int newimage = 0; int subimage = 1; int sharedimage = 1; struct image *i; int ddatalost = 0; if (width == 0) width = data->image->width; if (height == 0) height = data->image->height; #ifdef DEBUG printf("Inherimage:%s %i %i imagedata:%i %i\n", f->name, width, height, flags & IMAGEDATA, flags & PROTECTBUFFERS); #endif if (pixelwidth == 0) pixelwidth = data->image->pixelwidth; if (pixelheight == 0) pixelheight = data->image->pixelheight; if (palette == NULL) palette = data->image->palette; if (!(palette->type & f->req.supportedmask)) { #ifdef DEBUG printf ("Initalization of filter %s failed due to unsupported type by child %s-%i,%i\n", f->name, f->previous->name, f->req.supportedmask, palette->type); #endif f->image = data->image; return 0; } if (flags & NEWIMAGE) newimage = 1, sharedimage = 0, subimage = 0; if ((flags & IMAGEDATA) /*|| (data->image->flags & PROTECTBUFFERS) */ ) subimage = 0, sharedimage = 0, newimage = 1; /*if filter touches data but child requires them, create separated image */ if ((flags & TOUCHIMAGE) && ((f->req.flags & IMAGEDATA) || (data->image->flags & PROTECTBUFFERS))) subimage = 0, newimage = 1, sharedimage = 0; /*if required image differs in size or so */ if (width != data->image->width || height != data->image->height || palette != data->image->palette) newimage = 1, sharedimage = 0; if (f->childimage != NULL && (f->flags & ALLOCEDIMAGE)) { /*is an old child image still useable for us purposes? if not burn it it! */ /*We should share image? Why alloc new?? */ if (!newimage && (f->flags & ALLOCEDIMAGE)) destroyinheredimage(f), ddatalost = 1; /*We should share data? but child image dont do that! */ if (subimage && !(f->flags & SHAREDDATA)) destroyinheredimage(f), ddatalost = 1; /*We can't share data but child image does that? */ if (!subimage && (f->flags & SHAREDDATA)) destroyinheredimage(f), ddatalost = 1; /*When image changed, child image must be recreated too */ if (f->flags & SHAREDDATA && ((data->flags & DATALOST) || f->imageversion != data->image->version)) destroyinheredimage(f), ddatalost = 1; /*We should share image with filter? Why keep created new one? */ if (sharedimage) destroyinheredimage(f), ddatalost = 1; /*When child image don't fit out needs */ if (f->childimage != NULL && (f->childimage->width != width || f->childimage->height != height || f->childimage->palette != palette || f->childimage->bytesperpixel != bytesperpixel(palette->type) || f->childimage->nimages < f->req.nimages)) destroyinheredimage(f), ddatalost = 1; /*Well now child image seems to be heavily probed */ } i = f->childimage; if (newimage) { /*Create new image when required */ if (!(f->flags & ALLOCEDIMAGE)) { if (subimage) { i = create_subimage(data->image, width, height, f->req.nimages, palette, pixelwidth, pixelheight); f->flags |= ALLOCEDIMAGE | SHAREDDATA; ddatalost = 1; } else { i = create_image_mem(width, height, f->req.nimages, palette, pixelwidth, pixelheight); f->flags |= ALLOCEDIMAGE; ddatalost = 1; } } } #ifdef DEBUG printf("Filter:%s newimage:%i subimage:%i sharedimage:%i\n", f->name, newimage, subimage, sharedimage); #endif if (i == NULL) { f->image = data->image; return 0; } if (sharedimage) i = data->image, ddatalost = (data->flags & DATALOST) || (f->childimage != data->image); if (sharedimage && datalost(f, data)) ddatalost = 1; else if ((f->flags | SHAREDDATA) && datalost(f, data) && !(i->flags & FREEDATA)) ddatalost = 1; if (ddatalost) data->flags |= DATALOST; else data->flags &= ~DATALOST; f->image = data->image; f->childimage = i; f->imageversion = data->image->version; data->image = i; #ifdef DEBUG printf("OK %i datalost:%i\n", f->flags, ddatalost); #endif #ifdef DEBUG printf("Inherimage2:%s %i %i\n", f->name, width, height); #endif return 1; }