Exemplo n.º 1
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   C a t c h E x c e p t i o n                                               %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  CatchException() returns if no exceptions is found otherwise it reports
%  the exception as a warning, error, or fatal depending on the severity.
%
%  The format of the CatchException method is:
%
%      CatchException(ExceptionInfo *exception)
%
%  A description of each parameter follows:
%
%    o exception: the exception info.
%
*/
MagickExport void CatchException(ExceptionInfo *exception)
{
  register const ExceptionInfo
    *p;

  assert(exception != (ExceptionInfo *) NULL);
  assert(exception->signature == MagickSignature);
  if (exception->exceptions  == (void *) NULL)
    return;
  LockSemaphoreInfo(exception->semaphore);
  ResetLinkedListIterator((LinkedListInfo *) exception->exceptions);
  p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
    exception->exceptions);
  while (p != (const ExceptionInfo *) NULL)
  {
    if ((p->severity >= WarningException) && (p->severity < ErrorException))
      MagickWarning(p->severity,p->reason,p->description);
    if ((p->severity >= ErrorException) && (p->severity < FatalErrorException))
      MagickError(p->severity,p->reason,p->description);
    if (p->severity >= FatalErrorException)
      MagickFatalError(p->severity,p->reason,p->description);
    p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *)
      exception->exceptions);
  }
  UnlockSemaphoreInfo(exception->semaphore);
  ClearMagickException(exception);
}
Exemplo n.º 2
0
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                             %
%                                                                             %
%                                                                             %
%   S e t M a g i c k I n f o                                                 %
%                                                                             %
%                                                                             %
%                                                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Method SetMagickInfo allocates a MagickInfo structure and initializes the
%  members to default values.
%
%  The format of the SetMagickInfo method is:
%
%      MagickInfo *SetMagickInfo(const char *tag)
%
%  A description of each parameter follows:
%
%    o magick_info: Method SetMagickInfo returns the allocated and initialized
%      MagickInfo structure.
%
%    o tag: a character string that represents the image format associated
%      with the MagickInfo structure.
%
%
*/
Export MagickInfo *SetMagickInfo(const char *tag)
{
  MagickInfo
    *entry;

  entry=(MagickInfo *) AllocateMemory(sizeof(MagickInfo));
  if (entry == (MagickInfo *) NULL)
    MagickError(ResourceLimitError,"Unable to allocate image",
      "Memory allocation failed");
  entry->tag=AllocateString(tag);
  entry->decoder=(Image *(*)(const ImageInfo *)) NULL;
  entry->encoder=(unsigned int (*)(const ImageInfo *,Image *)) NULL;
  entry->magick=
    (unsigned int (*)(const unsigned char *,const unsigned int)) NULL;
  entry->adjoin=True;
  entry->blob_support=True;
  entry->raw=False;
  entry->description=(char *) NULL;
  entry->data=(void *) NULL;
  entry->previous=(MagickInfo *) NULL;
  entry->next=(MagickInfo *) NULL;
  return(entry);
}
int tc_filter(frame_list_t *ptr_, char *options)
{
	vframe_list_t *ptr = (vframe_list_t *)ptr_;
	int instance = ptr->filter_id;
	Image *pattern, *resized, *orig = 0;
	ImageInfo *image_info;

	PixelPacket *pixel_packet;
	pixelsMask *pixel_last;
	ExceptionInfo exception_info;

	if(ptr->tag & TC_FILTER_GET_CONFIG) {
		char buf[128];
		optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION,
				   MOD_AUTHOR, "VRYMO", "1");

		tc_snprintf(buf, 128, "/dev/null");
		optstr_param(options, "pattern", "Pattern image file path", "%s", buf);
		tc_snprintf(buf, 128, "results.dat");
		optstr_param(options, "results", "Results file path" , "%s", buf);
		tc_snprintf(buf, 128, "%f", compare[instance]->delta);
		optstr_param(options, "delta", "Delta error", "%f",buf,"0.0", "100.0");
		return 0;
	}

	//----------------------------------
	//
	// filter init
	//
	//----------------------------------


	if(ptr->tag & TC_FILTER_INIT)
	{

		unsigned int t,r,index;
		pixelsMask *temp;

		compare[instance] = tc_malloc(sizeof(compareData));
		if(compare[instance] == NULL)
			return (-1);

		compare[instance]->vob = tc_get_vob();
		if(compare[instance]->vob ==NULL)
            return(-1);

		compare[instance]->delta=DELTA_COLOR;
		compare[instance]->step=1;
		compare[instance]->width=0;
		compare[instance]->height=0;
		compare[instance]->frames = 0;
		compare[instance]->pixel_mask = NULL;
		pixel_last = NULL;

		compare[instance]->width = compare[instance]->vob->ex_v_width;
		compare[instance]->height = compare[instance]->vob->ex_v_height;

		if (options != NULL) {
			char pattern_name[PATH_MAX];
			char results_name[PATH_MAX];
			memset(pattern_name,0,PATH_MAX);
			memset(results_name,0,PATH_MAX);

			if(verbose) tc_log_info(MOD_NAME, "options=%s", options);

			optstr_get(options, "pattern", "%[^:]", pattern_name);
			optstr_get(options, "results", "%[^:]", results_name);
			optstr_get(options, "delta", "%f", &compare[instance]->delta);

			if (verbose > 1) {
				tc_log_info(MOD_NAME, "Compare Image Settings:");
				tc_log_info(MOD_NAME, "      pattern = %s\n", pattern_name);
				tc_log_info(MOD_NAME, "      results = %s\n", results_name);
				tc_log_info(MOD_NAME, "        delta = %f\n", compare[instance]->delta);
			}

			if (strlen(results_name) == 0) {
				// Ponemos el nombre del fichero al original con extension dat
				strlcpy(results_name, "/tmp/compare.dat", sizeof(results_name));

			}
			if (!(compare[instance]->results = fopen(results_name, "w")))
			{
				tc_log_perror(MOD_NAME, "could not open file for writing");
			}

			InitializeMagick("");
			if (verbose > 1)
                tc_log_info(MOD_NAME, "Magick Initialized successfully");

			GetExceptionInfo(&exception_info);
			image_info = CloneImageInfo ((ImageInfo *) NULL);
			strlcpy(image_info->filename, pattern_name, MaxTextExtent);
			if (verbose > 1)
			     tc_log_info(MOD_NAME, "Trying to open image");
			orig = ReadImage(image_info,
					 &exception_info);

			if (orig == (Image *) NULL) {
				MagickWarning(exception_info.severity,
					      exception_info.reason,
					      exception_info.description);
				strlcpy(pattern_name, "/dev/null", sizeof(pattern_name));
			}else{
			       if (verbose > 1)
			       		tc_log_info(MOD_NAME, "Image loaded successfully");
			     }
		}

		else{
			tc_log_perror(MOD_NAME, "Not image provided");
		}

		if (options != NULL)
			if (optstr_lookup (options, "help")) {
				help_optstr();
			}


		fprintf(compare[instance]->results,"#fps:%f\n",compare[instance]->vob->fps);

		if (orig != NULL){
                        // Flip and resize
			if (compare[instance]->vob->im_v_codec == CODEC_YUV)
				TransformRGBImage(orig,YCbCrColorspace);
			if (verbose > 1) tc_log_info(MOD_NAME, "Resizing the Image");
			resized = ResizeImage(orig,
					      compare[instance]->width,
					      compare[instance]->height,
					      GaussianFilter,
					      1,
					      &exception_info);
			if (verbose > 1)
				tc_log_info(MOD_NAME, "Flipping the Image");
			pattern = FlipImage(resized, &exception_info);
			if (pattern == (Image *) NULL) {
				MagickError (exception_info.severity,
					     exception_info.reason,
					     exception_info.description);
			}

			// Filling the matrix with the pixels values not
			// alpha

			if (verbose > 1) tc_log_info(MOD_NAME, "GetImagePixels");
			pixel_packet = GetImagePixels(pattern,0,0,
						      pattern->columns,
						      pattern->rows);

			if (verbose > 1) tc_log_info(MOD_NAME, "Filling the Image matrix");
			for (t = 0; t < pattern->rows; t++)
				for (r = 0; r < pattern->columns; r++){
					index = t*pattern->columns + r;
					if (pixel_packet[index].opacity == 0){
						temp=tc_malloc(sizeof(struct pixelsMask));
						temp->row=t;
						temp->col=r;
						temp->r = (uint8_t)ScaleQuantumToChar(pixel_packet[index].red);
						temp->g = (uint8_t)ScaleQuantumToChar(pixel_packet[index].green);
						temp->b = (uint8_t)ScaleQuantumToChar(pixel_packet[index].blue);
						temp->next=NULL;

						if (pixel_last == NULL){
							pixel_last = temp;
							compare[instance]->pixel_mask = temp;
						}else{
							pixel_last->next = temp;
							pixel_last = temp;
						}
					}
				}

			if (verbose)
                tc_log_info(MOD_NAME, "%s %s",
					    MOD_VERSION, MOD_CAP);
		}
		return(0);
	}


	//----------------------------------
	//
	// filter close
	//
	//----------------------------------


	if(ptr->tag & TC_FILTER_CLOSE) {

		if (compare[instance] != NULL) {
			fclose(compare[instance]->results);
			free(compare[instance]);
		}
		DestroyMagick();
		compare[instance]=NULL;

		return(0);

	} /* filter close */

	//----------------------------------
	//
	// filter frame routine
	//
	//----------------------------------


	// tag variable indicates, if we are called before
	// transcodes internal video/audio frame processing routines
	// or after and determines video/audio context

	if((ptr->tag & TC_POST_M_PROCESS) && (ptr->tag & TC_VIDEO))  {
		// For now I only support RGB color space
		pixelsMask *item = NULL;
		double sr,sg,sb;
		double avg_dr,avg_dg,avg_db;

		if (compare[instance]->vob->im_v_codec == CODEC_RGB){

			int r,g,b,c;
			double width_long;

			if (compare[instance]->pixel_mask != NULL)
			{
				item = compare[instance]->pixel_mask;
				c = 0;

				sr = 0.0;
				sg = 0.0;
				sb = 0.0;

				width_long = compare[instance]->width*3;
				while(item){
					r = item->row*width_long + item->col*3;
					g = item->row*width_long
						+ item->col*3 + 1;
					b = item->row*width_long
						+ item->col*3 + 2;

				// diff between points
				// Interchange RGB values if necesary
					sr = sr + (double)abs((unsigned char)ptr->video_buf[r] - item->r);
					sg = sg + (double)abs((unsigned char)ptr->video_buf[g] - item->g);
					sb = sb + (double)abs((unsigned char)ptr->video_buf[b] - item->b);
					item = item->next;
					c++;
				}

				avg_dr = sr/(double)c;
				avg_dg = sg/(double)c;
				avg_db = sb/(double)c;

				if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta))
					fprintf(compare[instance]->results,"1");
				else
					fprintf(compare[instance]->results,"n");
				fflush(compare[instance]->results);
			}
			compare[instance]->frames++;
			return(0);
		}else{

                        // The colospace is YUV

                        // FIXME: Doesn't works, I need to code all this part
			// again

			int Y,Cr,Cb,c;

			if (compare[instance]->pixel_mask != NULL)
			{
				item = compare[instance]->pixel_mask;
				c = 0;

				sr = 0.0;
				sg = 0.0;
				sb = 0.0;

				while(item){
					Y  = item->row*compare[instance]->width + item->col;
					Cb = compare[instance]->height*compare[instance]->width
						+ (int)((item->row*compare[instance]->width + item->col)/4);
					Cr = compare[instance]->height*compare[instance]->width
						+ (int)((compare[instance]->height*compare[instance]->width)/4)
						+ (int)((item->row*compare[instance]->width + item->col)/4);

				        // diff between points
				        // Interchange RGB values if necesary

					sr = sr + (double)abs((unsigned char)ptr->video_buf[Y] - item->r);
					sg = sg + (double)abs((unsigned char)ptr->video_buf[Cb] - item->g);
					sb = sb + (double)abs((unsigned char)ptr->video_buf[Cr] - item->b);
					item = item->next;
					c++;
				}

				avg_dr = sr/(double)c;
				avg_dg = sg/(double)c;
				avg_db = sb/(double)c;

				if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta))
					fprintf(compare[instance]->results,"1");
				else
					fprintf(compare[instance]->results,"n");
			}
			compare[instance]->frames++;
			return(0);

		}
	}

	return(0);
}
Exemplo n.º 4
0
unsigned int CGIToArgv(const char *text,int *argc,char ***argv)
{
  char
    **vector;

  const char
    *p,
    *q;

  register int
    i;

  int
    count;

  if (text == (char *) NULL)
    return(False);
  /*
    Determine the number of arguments by scanning for delimiters
  */
  q=text;
  count=0;
  while (1)
  {
    int
      len;

    p=q;
    while (!IsCGIDelimiter(*q))
      q++;
    len=q-p;
    if (len > 0)
      count++;
    if (*q == '\0')
      break;
    q++;
  }
  vector=(char **) AcquireMemory((count+2)*sizeof(char *));
  if (vector == (char **) NULL)
    {
      MagickError(ResourceLimitError,"Unable to convert string to argv",
        "Memory allocation failed");
      return(False);
    }
  /*
    Convert string to an ASCII list.
  */
  vector[0]=AllocateString("isapimagick");
  vector[count+1]=(char *) NULL;
  q=text;
  i=1;
  while (i <= count)
  {
    int
      len;

    p=q;
    while (!IsCGIDelimiter(*q))
      q++;
    /*
       Skip an zero length tokens. This typically happens for the case
       of xxx=& on a CGI GET or POST were the name value pair has no
       value
    */
    len=q-p;
    if (len > 0)
      {
        vector[i]=(char *) AcquireMemory(q-p+1);
        if (vector[i] == (char *) NULL)
          {
            MagickError(ResourceLimitError,"Unable to convert string to argv",
              "Memory allocation failed");
            return(False);
          }
        (void) strncpy(vector[i],p,q-p);
        vector[i][q-p]='\0';
        /*
          Convert any special HTML codes in place back to ASCII
        */
        HttpUnescape(vector[i], (char *) NULL);
        i++;
      }
    q++;
  }
  *argc=count+1;
  *argv=vector;
  return(True);
}
Exemplo n.º 5
0
Arquivo: main.c Projeto: anovmari/main
gboolean isTennisFree()
{
	gboolean
		res = FALSE;

	ExceptionInfo
		*exception;

	Image
		*image;

	ImageInfo
		*image_info;

	unsigned long
		colors;

	ColorPacket
		*histogram;

	unsigned long
		i = 0;
	char*
		img_path = "video.jpg";

	getImg();

	exception = AcquireExceptionInfo();
	image_info = CloneImageInfo((ImageInfo *) NULL);
	strcpy(image_info->filename, img_path);
	image = ReadImage(image_info,exception);
	if (exception->severity != UndefinedException)
	{
		CatchException(exception);
	}
	if (image == (Image *) NULL)
	{
		return FALSE;
//exit(1);
	}
	histogram = GetImageHistogram(image, &colors, exception);
	qsort((void *) histogram, (size_t) colors, sizeof(*histogram), myHistogramCompare);
	if (histogram == (ColorPacket*) NULL)
	{
		MagickError(exception->severity, exception->reason, exception->description);
	}
	if(colors > 0)
	{
		if(histogram[i].count > 5000
			&& ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.red)) < 35
			&& ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.green)) < 35
			&& ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.blue)) < 35)
		{
			res = TRUE;
			printf("Empty\n");
		}
		else
		{
			res = FALSE;
			printf("Busy\n");
		}
//		printf("%d %d %d %d\n", (int)histogram[i].count, ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.red)), ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.green)), ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.blue)));
	}
//	remove(img_path);
	histogram = (ColorPacket *) RelinquishMagickMemory(histogram);
	DestroyImage(image);
	image_info=DestroyImageInfo(image_info);
	exception=DestroyExceptionInfo(exception);
	return res;
}
Exemplo n.º 6
0
int main(int argc,char **argv)
{
	ExceptionInfo
		*exception;

	Image
		*image;

	ImageInfo
		*image_info;

	unsigned long
		colors;

	ColorPacket
		*histogram;

	unsigned long
		i = 0;
	char*
		img_path = "video.jpg";

	getImg();

	MagickCoreGenesis(*argv,MagickTrue);
	exception = AcquireExceptionInfo();
	image_info = CloneImageInfo((ImageInfo *) NULL);
	strcpy(image_info->filename, img_path);
	image = ReadImage(image_info,exception);
	if (exception->severity != UndefinedException)
	{
		CatchException(exception);
	}
	if (image == (Image *) NULL)
	{
		exit(1);
	}
	histogram = GetImageHistogram(image, &colors, exception);
	qsort((void *) histogram, (size_t) colors, sizeof(*histogram), myHistogramCompare);
	if (histogram == (ColorPacket*) NULL)
	{
		MagickError(exception->severity, exception->reason, exception->description);
	}
	if(colors > 0)
	{
		if(histogram[i].count > 10000
			&& ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.red)) < 35
			&& ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.green)) < 35
			&& ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.blue)) < 35)
		{
			printf("Empty\n");
		}
		else
		{
			printf("Busy\n");
		}
//		printf("%u %d %d %d\n", histogram[i].count, ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.red)), ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.green)), ScaleQuantumToChar(RoundToQuantum(histogram[i].pixel.blue)));
	}
	remove(img_path);
	histogram = (ColorPacket *) RelinquishMagickMemory(histogram);
	DestroyImage(image);
	image_info=DestroyImageInfo(image_info);
	exception=DestroyExceptionInfo(exception);
	MagickCoreTerminus();
	return(0);
}
Exemplo n.º 7
0
int tc_filter(frame_list_t *ptr_, char *options)
{
    vframe_list_t *ptr = (vframe_list_t *)ptr_;
    vob_t         *vob = NULL;

    int instance = ptr->filter_id;
    MyFilterData  *mfd = mfd_all[instance];

    if (mfd != NULL) {
        vob = mfd->vob;
    }

    //----------------------------------
    //
    // filter init
    //
    //----------------------------------


    if (ptr->tag & TC_FILTER_GET_CONFIG) {
        optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYO", "1");
        // buf, name, comment, format, val, from, to
        optstr_param(options, "file",   "Image filename",    "%s",    "logo.png");
        optstr_param(options, "posdef", "Position (0=None, 1=TopL, 2=TopR, 3=BotL, 4=BotR, 5=Center)",  "%d", "0", "0", "5");
        optstr_param(options, "pos",    "Position (0-width x 0-height)",  "%dx%d", "0x0", "0", "width", "0", "height");
        optstr_param(options, "range",  "Restrict rendering to framerange",  "%u-%u", "0-0", "0", "oo", "0", "oo");
        optstr_param(options, "fade",   "Fade image in/out (# of frames)",  "%u-%u", "0-0", "0", "oo", "0", "oo");
        // bools
        optstr_param(options, "ignoredelay", "Ignore delay specified in animations", "", "0");
        optstr_param(options, "rgbswap", "Swap red/blue colors", "", "0");
        optstr_param(options, "grayout", "YUV only: don't write Cb and Cr, makes a nice effect", "",  "0");
        optstr_param(options, "hqconv",  "YUV only: do high quality rgb->yuv img conversion", "",  "0");
        optstr_param(options, "flip",    "Mirror image",  "", "0");

        return 0;
    }

    if (ptr->tag & TC_FILTER_INIT) {
        Image         *timg;
        Image         *nimg;
        ImageInfo     *image_info;
        ExceptionInfo  exception_info;

        int rgb_off = 0;

        vob_t *tmpvob;

        tmpvob = tc_get_vob();
        if (tmpvob == NULL)
            return -1;
        mfd_all[instance] = tc_zalloc(sizeof(MyFilterData));
        if (mfd_all[instance] == NULL)
            return -1;

        mfd = mfd_all[instance];

        strlcpy(mfd->file, "logo.png", PATH_MAX);
        mfd->end = (unsigned int)-1;
        mfd->vob = tmpvob;
        vob      = mfd->vob;

        if (options != NULL) {
            if (verbose)
                tc_log_info(MOD_NAME, "options=%s", options);

            optstr_get(options, "file",     "%[^:]", mfd->file);
            optstr_get(options, "posdef",   "%d",    (int *)&mfd->pos);
            optstr_get(options, "pos",      "%dx%d", &mfd->posx,  &mfd->posy);
            optstr_get(options, "range",    "%u-%u", &mfd->start, &mfd->end);
            optstr_get(options, "fade",     "%u-%u", &mfd->fadein, &mfd->fadeout);

            if (optstr_lookup(options, "ignoredelay") != NULL)
                mfd->ignoredelay = !mfd->ignoredelay;
            if (optstr_lookup(options, "flip") != NULL)
                mfd->flip    = !mfd->flip;
            if (optstr_lookup(options, "rgbswap") != NULL)
                mfd->rgbswap = !mfd->rgbswap;
            if (optstr_lookup(options, "grayout") != NULL)
                mfd->grayout = !mfd->grayout;
            if (optstr_lookup(options, "hqconv") != NULL)
                mfd->hqconv  = !mfd->hqconv;

            if (optstr_lookup (options, "help") != NULL)
                flogo_help_optstr();
        }

        if (verbose > 1) {
            tc_log_info(MOD_NAME, " Logo renderer Settings:");
            tc_log_info(MOD_NAME, "         file = %s",    mfd->file);
            tc_log_info(MOD_NAME, "       posdef = %d",    mfd->pos);
            tc_log_info(MOD_NAME, "          pos = %dx%d", mfd->posx,
                                                           mfd->posy);
            tc_log_info(MOD_NAME, "        range = %u-%u", mfd->start,
                                                           mfd->end);
            tc_log_info(MOD_NAME, "         fade = %u-%u", mfd->fadein,
                                                           mfd->fadeout);
            tc_log_info(MOD_NAME, "         flip = %d",    mfd->flip);
            tc_log_info(MOD_NAME, "  ignoredelay = %d",    mfd->ignoredelay);
            tc_log_info(MOD_NAME, "      rgbswap = %d",    mfd->rgbswap);
            tc_log_info(MOD_NAME, "      grayout = %d",    mfd->grayout);
            tc_log_info(MOD_NAME, "       hqconv = %d",    mfd->hqconv);
        }

        /* Transcode serializes module execution, so this does not need a
         * semaphore.
         */
        magick_usecount++;
        if (!IsMagickInstantiated()) {
            InitializeMagick("");
        }

        GetExceptionInfo(&exception_info);
        image_info = CloneImageInfo((ImageInfo *) NULL);
        strlcpy(image_info->filename, mfd->file, MaxTextExtent);

        mfd->image = ReadImage(image_info, &exception_info);
        if (mfd->image == (Image *) NULL) {
            MagickWarning(exception_info.severity,
                          exception_info.reason,
                          exception_info.description);
            strlcpy(mfd->file, "/dev/null", PATH_MAX);
            return 0;
        }
        DestroyImageInfo(image_info);

        if (mfd->image->columns > vob->ex_v_width
         || mfd->image->rows    > vob->ex_v_height
        ) {
            tc_log_error(MOD_NAME, "\"%s\" is too large", mfd->file);
            return -1;
        }

        if (vob->im_v_codec == TC_CODEC_YUV420P) {
            if ((mfd->image->columns & 1) || (mfd->image->rows & 1)) {
                tc_log_error(MOD_NAME, "\"%s\" has odd sizes", mfd->file);
                return -1;
            }
        }

        mfd->images = (Image *)GetFirstImageInList(mfd->image);
        nimg = NewImageList();

        while (mfd->images != (Image *)NULL) {
            if (mfd->flip || flip) {
                timg = FlipImage(mfd->images, &exception_info);
                if (timg == (Image *) NULL) {
                    MagickError(exception_info.severity,
                                exception_info.reason,
                                exception_info.description);
                    return -1;
                }
                AppendImageToList(&nimg, timg);
            }

            mfd->images = GetNextImageInList(mfd->images);
            mfd->nr_of_images++;
        }

        // check for memleaks;
        //DestroyImageList(image);
        if (mfd->flip || flip) {
            mfd->image = nimg;
        }

        /* initial delay. real delay = 1/100 sec * delay */
        mfd->cur_delay = mfd->image->delay*vob->fps/100;

        if (verbose & TC_DEBUG)
            tc_log_info(MOD_NAME, "Nr: %d Delay: %d mfd->image->del %lu|",
                        mfd->nr_of_images, mfd->cur_delay, mfd->image->delay);

        if (vob->im_v_codec == TC_CODEC_YUV420P) {
            /* convert Magick RGB image format to YUV */
            /* todo: convert the magick image if it's not rgb! (e.g. cmyk) */
            Image   *image;
            uint8_t *yuv_hqbuf = NULL;

            /* Round up for odd-size images */
            unsigned long width  = mfd->image->columns;
            unsigned long height = mfd->image->rows;
            int do_rgbswap  = (rgbswap || mfd->rgbswap);
            int i;

            /* Allocate buffers for the YUV420P frames. mfd->nr_of_images
             * will be 1 unless this is an animated GIF or MNG.
             * This buffer needs to be large enough to store a temporary
             * 24-bit RGB image (extracted from the ImageMagick handle).
             */
            mfd->yuv = flogo_yuvbuf_alloc(width*height * 3, mfd->nr_of_images);
            if (mfd->yuv == NULL) {
                tc_log_error(MOD_NAME, "(%d) out of memory\n", __LINE__);
                return -1;
            }

            if (mfd->hqconv) {
                /* One temporary buffer, to hold full Y, U, and V planes. */
                yuv_hqbuf = tc_malloc(width*height * 3);
                if (yuv_hqbuf == NULL) {
                    tc_log_error(MOD_NAME, "(%d) out of memory\n", __LINE__);
                    return -1;
                }
            }

            mfd->tcvhandle = tcv_init();
            if (mfd->tcvhandle == NULL) {
                tc_log_error(MOD_NAME, "image conversion init failed");
                return -1;
            }

            image = GetFirstImageInList(mfd->image);

            for (i = 0; i < mfd->nr_of_images; i++) {
                if (!mfd->hqconv) {
                    flogo_convert_image(mfd->tcvhandle, image, mfd->yuv[i],
                                        IMG_YUV420P, do_rgbswap);
                } else {
                    flogo_convert_image(mfd->tcvhandle, image, yuv_hqbuf,
                                        IMG_YUV444P, do_rgbswap);

                    // Copy over Y data from the 444 image
                    ac_memcpy(mfd->yuv[i], yuv_hqbuf, width * height);

                    // Resize U plane by 1/2 in each dimension, into the
                    // mfd YUV buffer
                    tcv_zoom(mfd->tcvhandle,
                             yuv_hqbuf + (width * height),
                             mfd->yuv[i] + (width * height),
                             width,
                             height,
                             1,
                             width / 2,
                             height / 2,
                             TCV_ZOOM_LANCZOS3
                    );

                    // Do the same with the V plane
                    tcv_zoom(mfd->tcvhandle,
                             yuv_hqbuf + 2*width*height,
                             mfd->yuv[i] + width*height + (width/2)*(height/2),
                             width,
                             height,
                             1,
                             width / 2,
                             height / 2,
                             TCV_ZOOM_LANCZOS3
                    );
                }
                image = GetNextImageInList(image);
            }

            if (mfd->hqconv)
                tc_free(yuv_hqbuf);

            tcv_free(mfd->tcvhandle);
        } else {
            /* for RGB format is origin bottom left */
            /* for RGB, rgbswap is done in the frame routine */
            rgb_off = vob->ex_v_height - mfd->image->rows;
            mfd->posy = rgb_off - mfd->posy;
        }

        switch (mfd->pos) {
          case NONE: /* 0 */
            break;
          case TOP_LEFT:
            mfd->posx = 0;
            mfd->posy = rgb_off;
            break;
          case TOP_RIGHT:
            mfd->posx = vob->ex_v_width  - mfd->image->columns;
            break;
          case BOT_LEFT:
            mfd->posy = vob->ex_v_height - mfd->image->rows - rgb_off;
            break;
          case BOT_RIGHT:
            mfd->posx = vob->ex_v_width  - mfd->image->columns;
            mfd->posy = vob->ex_v_height - mfd->image->rows - rgb_off;
            break;
          case CENTER:
            mfd->posx = (vob->ex_v_width - mfd->image->columns)/2;
            mfd->posy = (vob->ex_v_height- mfd->image->rows)/2;
            /* align to not cause color disruption */
            if (mfd->posx & 1)
                mfd->posx++;
            if (mfd->posy & 1)
                mfd->posy++;
            break;
        }


        if (mfd->posy < 0 || mfd->posx < 0
         || (mfd->posx + mfd->image->columns) > vob->ex_v_width
         || (mfd->posy + mfd->image->rows)    > vob->ex_v_height) {
            tc_log_error(MOD_NAME, "invalid position");
            return -1;
        }

        /* for running through image sequence */
        mfd->images = mfd->image;


        /* Set up image/video coefficient lookup tables */
        if (img_coeff_lookup[0] < 0) {
            int i;
            float maxrgbval = (float)MaxRGB; // from ImageMagick

            for (i = 0; i <= MAX_UINT8_VAL; i++) {
                float x = (float)ScaleCharToQuantum(i);

                /* Alternatively:
                 *  img_coeff = (maxrgbval - x) / maxrgbval;
                 *  vid_coeff = x / maxrgbval;
                 */
                img_coeff_lookup[i] = 1.0 - (x / maxrgbval);
                vid_coeff_lookup[i] = 1.0 - img_coeff_lookup[i];
            }
        }

        // filter init ok.
        if (verbose)
            tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);

        return 0;
    }


    //----------------------------------
    //
    // filter close
    //
    //----------------------------------
    if (ptr->tag & TC_FILTER_CLOSE) {
        if (mfd) {
            flogo_yuvbuf_free(mfd->yuv, mfd->nr_of_images);
            mfd->yuv = NULL;

            if (mfd->image) {
                DestroyImage(mfd->image);
            }

            tc_free(mfd);
            mfd = NULL;
            mfd_all[instance] = NULL;
        }

        magick_usecount--;
        if (magick_usecount == 0 && IsMagickInstantiated()) {
            DestroyMagick();
        }

        return 0;
    } /* filter close */


    //----------------------------------
    //
    // filter frame routine
    //
    //----------------------------------


    // tag variable indicates, if we are called before
    // transcodes internal video/audo frame processing routines
    // or after and determines video/audio context

    if ((ptr->tag & TC_POST_M_PROCESS)
        && (ptr->tag & TC_VIDEO)
        && !(ptr->attributes & TC_FRAME_IS_SKIPPED)
    ) {
        PixelPacket *pixel_packet;
        uint8_t     *video_buf;

        int   do_fade    = 0;
        float fade_coeff = 0.0;
        float img_coeff, vid_coeff;

        /* Note: ImageMagick defines opacity = 0 as fully visible, and
         * opacity = MaxRGB as fully transparent.
         */
        Quantum opacity;

        int row, col;

        if (ptr->id < mfd->start || ptr->id > mfd->end)
            return 0;

        if (strcmp(mfd->file, "/dev/null") == 0)
            return 0;

        if (ptr->id - mfd->start < mfd->fadein) {
            // fading-in
            fade_coeff = (float)(mfd->start - ptr->id + mfd->fadein) / (float)(mfd->fadein);
            do_fade = 1;
        } else if (mfd->end - ptr->id < mfd->fadeout) {
            // fading-out
            fade_coeff = (float)(ptr->id - mfd->end + mfd->fadeout) / (float)(mfd->fadeout);
            do_fade = 1;
        }

        mfd->cur_delay--;

        if (mfd->cur_delay < 0 || mfd->ignoredelay) {
            int seq;

            mfd->cur_seq = (mfd->cur_seq + 1) % mfd->nr_of_images;

            mfd->images = mfd->image;
            for (seq=0; seq<mfd->cur_seq; seq++)
                mfd->images = mfd->images->next;

            mfd->cur_delay = mfd->images->delay * vob->fps/100;
        }

        pixel_packet = GetImagePixels(mfd->images, 0, 0,
                                      mfd->images->columns,
                                      mfd->images->rows);

        if (vob->im_v_codec == TC_CODEC_RGB24) {
            unsigned long r_off, g_off, b_off;

            if (!(rgbswap || mfd->rgbswap)) {
                r_off = 0;
                b_off = 2;
            } else {
                r_off = 2;
                b_off = 0;
            }
            g_off = 1;

            for (row = 0; row < mfd->image->rows; row++) {
                video_buf = ptr->video_buf + 3 * ((row + mfd->posy) * vob->ex_v_width + mfd->posx);

                for (col = 0; col < mfd->image->columns; col++) {
                    opacity = pixel_packet->opacity;

                    if (do_fade)
                        opacity += (Quantum)((MaxRGB - opacity) * fade_coeff);

                    if (opacity == 0) {
                        *(video_buf + r_off) = ScaleQuantumToChar(pixel_packet->red);
                        *(video_buf + g_off) = ScaleQuantumToChar(pixel_packet->green);
                        *(video_buf + b_off) = ScaleQuantumToChar(pixel_packet->blue);
                    } else if (opacity < MaxRGB) {
                        unsigned char opacity_uchar = ScaleQuantumToChar(opacity);
                        img_coeff = img_coeff_lookup[opacity_uchar];
                        vid_coeff = vid_coeff_lookup[opacity_uchar];

                        *(video_buf + r_off) = (uint8_t)((*(video_buf + r_off)) * vid_coeff)
                                                + (uint8_t)(ScaleQuantumToChar(pixel_packet->red)   * img_coeff);
                        *(video_buf + g_off) = (uint8_t)((*(video_buf + g_off)) * vid_coeff)
                                                + (uint8_t)(ScaleQuantumToChar(pixel_packet->green) * img_coeff);
                        *(video_buf + b_off) = (uint8_t)((*(video_buf + b_off)) * vid_coeff)
                                                + (uint8_t)(ScaleQuantumToChar(pixel_packet->blue)  * img_coeff);
                    }

                    video_buf += 3;
                    pixel_packet++;
                }
            }
        } else { /* !RGB */
            unsigned long vid_size = vob->ex_v_width * vob->ex_v_height;
            unsigned long img_size = mfd->images->columns * mfd->images->rows;

            uint8_t *img_pixel_Y, *img_pixel_U, *img_pixel_V;
            uint8_t *vid_pixel_Y, *vid_pixel_U, *vid_pixel_V;

            img_pixel_Y = mfd->yuv[mfd->cur_seq];
            img_pixel_U = img_pixel_Y + img_size;
            img_pixel_V = img_pixel_U + img_size/4;

            for (row = 0; row < mfd->images->rows; row++) {
                vid_pixel_Y = ptr->video_buf + (row + mfd->posy)*mfd->vob->ex_v_width + mfd->posx;
                vid_pixel_U = ptr->video_buf + vid_size + (row/2 + mfd->posy/2)*(mfd->vob->ex_v_width/2) + mfd->posx/2;
                vid_pixel_V = vid_pixel_U + vid_size/4;
                for (col = 0; col < mfd->images->columns; col++) {
                    int do_UV_pixels = (mfd->grayout == 0 && !(row % 2) && !(col % 2)) ? 1 : 0;
                    opacity = pixel_packet->opacity;

                    if (do_fade)
                        opacity += (Quantum)((MaxRGB - opacity) * fade_coeff);

                    if (opacity == 0) {
                        *vid_pixel_Y = *img_pixel_Y;
                        if (do_UV_pixels) {
                                *vid_pixel_U = *img_pixel_U;
                                *vid_pixel_V = *img_pixel_V;
                        }
                    } else if (opacity < MaxRGB) {
                        unsigned char opacity_uchar = ScaleQuantumToChar(opacity);
                        img_coeff = img_coeff_lookup[opacity_uchar];
                        vid_coeff = vid_coeff_lookup[opacity_uchar];

                        *vid_pixel_Y = (uint8_t)(*vid_pixel_Y * vid_coeff) + (uint8_t)(*img_pixel_Y * img_coeff);

                        if (do_UV_pixels) {
                            *vid_pixel_U = (uint8_t)(*vid_pixel_U * vid_coeff) + (uint8_t)(*img_pixel_U * img_coeff);
                            *vid_pixel_V = (uint8_t)(*vid_pixel_V * vid_coeff) + (uint8_t)(*img_pixel_V * img_coeff);
                        }
                    }

                    vid_pixel_Y++;
                    img_pixel_Y++;
                    if (do_UV_pixels) {
                        vid_pixel_U++;
                        img_pixel_U++;
                        vid_pixel_V++;
                        img_pixel_V++;
                    }
                    pixel_packet++;
                }
            }
        }
    }

    return 0;
}