Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include "VapourSynth.h"
- #include "VSHelper.h"
- #include <stdint.h>
- typedef uint8_t pixel_t;
- typedef struct least_squares_data
- {
- int integral_x;
- int integral_y;
- int integral_xy;
- int integral_xsqr;
- } least_squares_data;
- typedef struct
- {
- VSNodeRef *node;
- const VSVideoInfo *vi;
- int left;
- int right;
- int top;
- int bottom;
- int radius;
- } ContinuityData;
- void least_squares(int n, least_squares_data *d, float *a, float *b)
- {
- float interval_x = (float) (d[n - 1].integral_x - d[0].integral_x);
- float interval_y = (float) (d[n - 1].integral_y - d[0].integral_y);
- float interval_xy = (float) (d[n - 1].integral_xy - d[0].integral_xy);
- float interval_xsqr = (float) (d[n - 1].integral_xsqr - d[0].integral_xsqr);
- // add 0.001f to denominator to prevent division by zero
- *a = ((float) n * interval_xy - interval_x * interval_y) / ((interval_xsqr * (float) n - interval_x * interval_x) + 0.001f);
- *b = (interval_y - *a * interval_x) / (float) n;
- }
- size_t required_buffer(int n)
- {
- return n * sizeof(least_squares_data);
- }
- 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)
- {
- int i;
- float a, b;
- buf[0].integral_x = x[0];
- buf[0].integral_y = y[0];
- buf[0].integral_xy = x[0] * y[0];
- buf[0].integral_xsqr = x[0] * x[0];
- for (i = 1; i < n; ++i)
- {
- int _x = x[i * x_dist_to_next];
- int _y = y[i * y_dist_to_next];
- buf[i].integral_x = buf[i - 1].integral_x + _x;
- buf[i].integral_y = buf[i - 1].integral_y + _y;
- buf[i].integral_xy = buf[i - 1].integral_xy + _x * _y;
- buf[i].integral_xsqr = buf[i - 1].integral_xsqr + _x * _x;
- }
- if (radius)
- {
- for (i = 0; i < n; ++i)
- {
- int left = i - radius;
- int right = i + radius;
- if (left < 0)
- left = 0;
- if (right > n - 1)
- right = n - 1;
- least_squares(right - left + 1, buf + left, &a, &b);
- x[i * x_dist_to_next] = (pixel_t) (x[i * x_dist_to_next] * a + b);
- }
- }
- else
- {
- least_squares(n, buf, &a, &b);
- for (i = 0; i < n; ++i)
- x[i * x_dist_to_next] = (pixel_t) (x[i * x_dist_to_next] * a + b);
- }
- }
- static void VS_CC continuityInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi)
- {
- ContinuityData *d = (ContinuityData *) * instanceData;
- vsapi->setVideoInfo(d->vi, 1, node);
- }
- static const VSFrameRef *VS_CC continuityGetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi)
- {
- ContinuityData *d = (ContinuityData *) * instanceData;
- if (activationReason == arInitial)
- {
- vsapi->requestFrameFilter(n, d->node, frameCtx);
- }
- else if (activationReason == arAllFramesReady)
- {
- const VSFrameRef *src = vsapi->getFrameFilter(n, d->node, frameCtx);
- int height = vsapi->getFrameHeight(src, 0);
- int width = vsapi->getFrameWidth(src, 0);
- int stride = vsapi->getStride(src, 0);
- least_squares_data *buf = (least_squares_data*) malloc(required_buffer(width > height ? width : height));
- VSFrameRef *dst = vsapi->copyFrame(src, core);
- pixel_t *dest = (pixel_t*)vsapi->getWritePtr(dst, 0);
- int i;
- // top
- for (i = 0; i < d->top; ++i)
- {
- int ref_row = d->top - i;
- process_edge(dest + stride * (ref_row - 1), dest + stride * ref_row, 1, 1, width, d->radius, buf);
- }
- // bottom
- for (i = 0; i < d->bottom; ++i)
- {
- int ref_row = height - d->bottom - 1 + i;
- process_edge(dest + stride * (ref_row + 1), dest + stride * ref_row, 1, 1, width, d->radius, buf);
- }
- // left
- for (i = 0; i < d->left; ++i)
- {
- int ref_col = d->left - i;
- process_edge(dest + ref_col - 1, dest + ref_col, stride, stride, height, d->radius, buf);
- }
- // right
- for (i = 0; i < d->right; ++i)
- {
- int ref_col = width - d->right - 1 + i;
- process_edge(dest + ref_col + 1, dest + ref_col, stride, stride, height, d->radius, buf);
- }
- free(buf);
- vsapi->freeFrame(src);
- return dst;
- }
- return 0;
- }
- static void VS_CC continuityFree(void *instanceData, VSCore *core, const VSAPI *vsapi)
- {
- ContinuityData *d = (ContinuityData *)instanceData;
- vsapi->freeNode(d->node);
- free(d);
- }
- static void VS_CC continuityCreate(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi)
- {
- ContinuityData d;
- ContinuityData *data;
- int err;
- d.node = vsapi->propGetNode(in, "clip", 0, 0);
- d.vi = vsapi->getVideoInfo(d.node);
- if (!isConstantFormat(d.vi) || d.vi->format->sampleType != stInteger || d.vi->format->bitsPerSample != 8)
- {
- vsapi->setError(out, "ContinuityFixer: only constant format 8bit integer input supported");
- vsapi->freeNode(d.node);
- return;
- }
- d.bottom = vsapi->propGetInt(in, "bottom", 0, &err);
- d.top = vsapi->propGetInt(in, "top", 0, &err);
- d.right = vsapi->propGetInt(in, "right", 0, &err);
- d.left = vsapi->propGetInt(in, "left", 0, &err);
- d.radius = vsapi->propGetInt(in, "radius", 0, &err);
- if (err)
- {
- d.radius = d.vi->height < d.vi->width ? d.vi->height : d.vi->width;
- }
- data = (ContinuityData*) malloc(sizeof(d));
- *data = d;
- vsapi->createFilter(in, out, "ContinuityFixer", continuityInit, continuityGetFrame, continuityFree, fmParallel, 0, data, core);
- }
- VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc, VSRegisterFunction registerFunc, VSPlugin *plugin)
- {
- configFunc("com.monos.edgefixer", "edgefixer", "VapourSynth edgefixer port", VAPOURSYNTH_API_VERSION, 1, plugin);
- registerFunc("ContinuityFixer", "clip:clip;"
- "left:int;"
- "top:int;"
- "right:int;"
- "bottom:int;"
- "radius:int:opt;",
- continuityCreate, 0, plugin);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement