Advertisement
MonoS

continuityfixer for vs 8bit

Feb 18th, 2015
212
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.33 KB | None | 0 0
  1. #include <stdlib.h>
  2. #include "VapourSynth.h"
  3. #include "VSHelper.h"
  4. #include <stdint.h>
  5.  
  6. typedef uint8_t pixel_t;
  7.  
  8. typedef struct least_squares_data
  9. {
  10.     int integral_x;
  11.     int integral_y;
  12.     int integral_xy;
  13.     int integral_xsqr;
  14. } least_squares_data;
  15.  
  16. typedef struct
  17. {
  18.     VSNodeRef *node;
  19.     const VSVideoInfo *vi;
  20.  
  21.     int left;
  22.     int right;
  23.     int top;
  24.     int bottom;
  25.  
  26.     int radius;
  27. } ContinuityData;
  28.  
  29. void least_squares(int n, least_squares_data *d, float *a, float *b)
  30. {
  31.     float interval_x = (float) (d[n - 1].integral_x - d[0].integral_x);
  32.     float interval_y = (float) (d[n - 1].integral_y - d[0].integral_y);
  33.     float interval_xy = (float) (d[n - 1].integral_xy - d[0].integral_xy);
  34.     float interval_xsqr = (float) (d[n - 1].integral_xsqr - d[0].integral_xsqr);
  35.  
  36.  
  37.     // add 0.001f to denominator to prevent division by zero
  38.     *a = ((float) n * interval_xy - interval_x * interval_y) / ((interval_xsqr * (float) n - interval_x * interval_x) + 0.001f);
  39.     *b = (interval_y - *a * interval_x) / (float) n;
  40. }
  41.  
  42. size_t required_buffer(int n)
  43. {
  44.     return n * sizeof(least_squares_data);
  45. }
  46.  
  47. void process_edge(pixel_t * x, const pixel_t *y, int x_dist_to_next, int y_dist_to_next, int n, int radius, least_squares_data *buf)
  48. {
  49.     int i;
  50.     float a, b;
  51.  
  52.     buf[0].integral_x = x[0];
  53.     buf[0].integral_y = y[0];
  54.     buf[0].integral_xy = x[0] * y[0];
  55.     buf[0].integral_xsqr = x[0] * x[0];
  56.  
  57.     for (i = 1; i < n; ++i)
  58.     {
  59.         int _x = x[i * x_dist_to_next];
  60.         int _y = y[i * y_dist_to_next];
  61.         buf[i].integral_x = buf[i - 1].integral_x + _x;
  62.         buf[i].integral_y = buf[i - 1].integral_y + _y;
  63.         buf[i].integral_xy = buf[i - 1].integral_xy + _x * _y;
  64.         buf[i].integral_xsqr = buf[i - 1].integral_xsqr + _x * _x;
  65.     }
  66.     if (radius)
  67.     {
  68.         for (i = 0; i < n; ++i)
  69.         {
  70.             int left = i - radius;
  71.             int right = i + radius;
  72.             if (left < 0)
  73.                 left = 0;
  74.             if (right > n - 1)
  75.                 right = n - 1;
  76.             least_squares(right - left + 1, buf + left, &a, &b);
  77.             x[i * x_dist_to_next] = (pixel_t) (x[i * x_dist_to_next] * a + b);
  78.         }
  79.     }
  80.     else
  81.     {
  82.         least_squares(n, buf, &a, &b);
  83.         for (i = 0; i < n; ++i)
  84.             x[i * x_dist_to_next] = (pixel_t) (x[i * x_dist_to_next] * a + b);
  85.     }
  86. }
  87.  
  88. static void VS_CC continuityInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi)
  89. {
  90.     ContinuityData *d = (ContinuityData *) * instanceData;
  91.     vsapi->setVideoInfo(d->vi, 1, node);
  92. }
  93.  
  94. static const VSFrameRef  *VS_CC continuityGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi)
  95. {
  96.     ContinuityData *d = (ContinuityData *) * instanceData;
  97.  
  98.     if (activationReason == arInitial)
  99.     {
  100.         vsapi->requestFrameFilter(n, d->node, frameCtx);
  101.     }
  102.     else if (activationReason == arAllFramesReady)
  103.     {
  104.         const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx);
  105.  
  106.         int height = vsapi->getFrameHeight(src, 0);
  107.         int width = vsapi->getFrameWidth(src, 0);
  108.         int stride = vsapi->getStride(src, 0);
  109.  
  110.         least_squares_data *buf = (least_squares_data*) malloc(required_buffer(width > height ? width : height));
  111.        
  112.         VSFrameRef *dst = vsapi->copyFrame(src, core);
  113.        
  114.         pixel_t *dest = (pixel_t*)vsapi->getWritePtr(dst, 0);
  115.  
  116.         int i;
  117.         // top
  118.         for (i = 0; i < d->top; ++i)
  119.         {
  120.             int ref_row = d->top - i;
  121.             process_edge(dest + stride * (ref_row - 1), dest + stride * ref_row, 1, 1, width, d->radius, buf);
  122.         }
  123.  
  124.         // bottom
  125.         for (i = 0; i < d->bottom; ++i)
  126.         {
  127.             int ref_row = height - d->bottom - 1 + i;
  128.             process_edge(dest + stride * (ref_row + 1), dest + stride * ref_row, 1, 1, width, d->radius, buf);
  129.         }
  130.  
  131.         // left
  132.         for (i = 0; i < d->left; ++i)
  133.         {
  134.             int ref_col = d->left - i;
  135.             process_edge(dest + ref_col - 1, dest + ref_col, stride, stride, height, d->radius, buf);
  136.         }
  137.  
  138.         // right
  139.         for (i = 0; i < d->right; ++i)
  140.         {
  141.             int ref_col = width - d->right - 1 + i;
  142.             process_edge(dest + ref_col + 1, dest + ref_col, stride, stride, height, d->radius, buf);
  143.         }
  144.        
  145.         free(buf);
  146.         vsapi->freeFrame(src);
  147.  
  148.         return dst;
  149.     }
  150.  
  151.     return 0;
  152. }
  153.  
  154. static void VS_CC continuityFree(void *instanceData, VSCore *core, const VSAPI *vsapi)
  155. {
  156.     ContinuityData *d = (ContinuityData *)instanceData;
  157.     vsapi->freeNode(d->node);
  158.     free(d);
  159. }
  160.  
  161. static void VS_CC  continuityCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi)
  162. {
  163.     ContinuityData d;
  164.     ContinuityData *data;
  165.     int err;
  166.  
  167.     d.node = vsapi->propGetNode(in, "clip", 0, 0);
  168.     d.vi = vsapi->getVideoInfo(d.node);
  169.  
  170.     if (!isConstantFormat(d.vi) || d.vi->format->sampleType != stInteger || d.vi->format->bitsPerSample != 8)
  171.     {
  172.         vsapi->setError(out, "ContinuityFixer: only constant format 8bit integer input supported");
  173.         vsapi->freeNode(d.node);
  174.         return;
  175.     }
  176.  
  177.     d.bottom = vsapi->propGetInt(in, "bottom", 0, &err);
  178.     d.top =    vsapi->propGetInt(in, "top", 0, &err);
  179.     d.right =  vsapi->propGetInt(in, "right", 0, &err);
  180.     d.left =   vsapi->propGetInt(in, "left", 0, &err);
  181.  
  182.     d.radius = vsapi->propGetInt(in, "radius", 0, &err);
  183.     if (err)
  184.     {
  185.         d.radius = d.vi->height < d.vi->width ? d.vi->height : d.vi->width;
  186.     }
  187.    
  188.     data = (ContinuityData*) malloc(sizeof(d));
  189.     *data = d;
  190.  
  191.     vsapi->createFilter(in, out, "ContinuityFixer", continuityInit, continuityGetFrame, continuityFree, fmParallel, 0, data, core);
  192. }
  193.  
  194. VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc, VSRegisterFunction registerFunc, VSPlugin *plugin)
  195. {
  196.     configFunc("com.monos.edgefixer", "edgefixer", "VapourSynth edgefixer port", VAPOURSYNTH_API_VERSION, 1, plugin);
  197.     registerFunc("ContinuityFixer", "clip:clip;"
  198.                                     "left:int;"
  199.                                     "top:int;"
  200.                                     "right:int;"
  201.                                     "bottom:int;"
  202.                                     "radius:int:opt;",
  203.                                     continuityCreate, 0, plugin);
  204. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement