Advertisement
MonoS

continuityfixer for vs

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