Filter SDK/CMerge

From Avisynth wiki
Revision as of 00:00, 29 December 2016 by Admin (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


#include "avisynth_c.h"
#include <stdlib.h> // free, malloc

typedef struct Merge {
   AVS_Clip* clip2;
   double weight;
} Merge;

AVS_VideoFrame* AVSC_CC Merge_get_frame(AVS_FilterInfo* fi, int n)
{
   Merge* params = (Merge*) fi->user_data;

   AVS_VideoFrame* src = avs_get_frame(fi->child, n);
   const BYTE*     srcp = avs_get_read_ptr(src);
   int             src_pitch = avs_get_pitch(src);

   AVS_VideoFrame* src2 = avs_get_frame(params->clip2, n);
   const BYTE*     srcp2 = avs_get_read_ptr(src2);
   int             src2_pitch = avs_get_pitch(src2);

   AVS_VideoFrame* dst = avs_new_video_frame(fi->env, &fi->vi);
   BYTE*           dstp = avs_get_write_ptr(dst);
   int             dst_pitch = avs_get_pitch(dst);
   int             dst_rowsize = avs_get_row_size(dst); // in bytes!
   int             dst_height = avs_get_height(dst);

   int x, y, ch_tot;
   double w;

   if (avs_is_rgb32(&fi->vi))
      ch_tot = 4;
   else // rgb24
      ch_tot = 3;

   w = params->weight;

   for (y=0; y<dst_height; ++y) {
      for (x=0; x<dst_rowsize; x+=ch_tot) {
         dstp[x]   = (int)((1-w)*srcp[x] + w*srcp2[x]+0.5);     // B
         dstp[x+1] = (int)((1-w)*srcp[x+1] + w*srcp2[x+1]+0.5); // G
         dstp[x+2] = (int)((1-w)*srcp[x+2] + w*srcp2[x+2]+0.5); // R
      }
      srcp += src_pitch;
      srcp2 += src2_pitch;
      dstp += dst_pitch;
   }
	
   avs_release_frame(src);
   avs_release_frame(src2);

   return dst;
}

void AVSC_CC free_Merge(AVS_FilterInfo* fi)
{
   Merge* params = (Merge*) fi->user_data;
   avs_release_clip(params->clip2);
   free(params);
}

AVS_Value AVSC_CC create_Merge(AVS_ScriptEnvironment* env, AVS_Value args, void* user_data)
{
   AVS_Value v;
   AVS_Value tmp;
   AVS_FilterInfo* fi;
   const AVS_VideoInfo* vi2;

   AVS_Clip* new_clip = avs_new_c_filter(env, &fi, avs_array_elt(args, 0), 1);

   Merge *params = (Merge*)malloc(sizeof(Merge));
   if (!params)
      return avs_void;

      if (!avs_is_rgb(&fi->vi)) {
         return avs_new_value_error("Input video must be in RGB format!");
      }

   tmp = avs_array_elt(args, 1);
   if (avs_defined(tmp)) {
      params->clip2 = avs_take_clip(tmp, env);
      vi2 = avs_get_video_info(params->clip2);
      if (!avs_has_video(vi2)) {
         return avs_new_value_error("Second clip must be a video clip!");
      } 
      else if (!avs_is_color_space(vi2, fi->vi.pixel_type))
      {
         return avs_new_value_error("Second video must have the same pixel-type as the first clip!");
      } 
      else if (vi2->width != fi->vi.width || vi2->height != fi->vi.height)
      {
         return avs_new_value_error("Input and second clip sizes must match!");
      }
   } else {
      return avs_new_value_error("Second clip is missing!");
   }

   tmp = avs_array_elt(args, 2);
   if (avs_defined(tmp)) {
      params->weight = avs_as_float(tmp);
      if ((params->weight<0.0f) || (params->weight>1.0f)) {
         return avs_new_value_error("Make sure that '0.0 <= weight <= 1.0'!");
      }
   } else {
      params->weight = 0.5; // default value
   }

   fi->user_data = (void*) params;
   fi->get_frame = Merge_get_frame;
   fi->free_filter = free_Merge;

   v = avs_new_value_clip(new_clip);

   avs_release_clip(new_clip);
   return v;

}


const char* AVSC_CC avisynth_c_plugin_init(AVS_ScriptEnvironment* env)
{
   avs_add_function(env, "Merge", "cc[weight]f", create_Merge, 0);
   return "Merge sample C plugin";
}
Personal tools