📄 effects.cpp
字号:
// Avisynth v0.3. Copyright 2000 Ben Rudiak-Gould. For distribution
// conditions, please see http://www.math.berkeley.edu/~benrg/avisynth.html .
#include "avisynth.h"
#include "internal-filters.h"
class VerticalReduceBy2 : public GenericVideoFilter {
unsigned char *mybuffer;
public:
VerticalReduceBy2(PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
void GetVideoInfo(VideoInfo* pvi);
~VerticalReduceBy2();
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) { return new VerticalReduceBy2(args[0].clip); }
};
class HorizontalReduceBy2 : public GenericVideoFilter {
unsigned char *mybuffer;
public:
HorizontalReduceBy2(PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
void GetVideoInfo(VideoInfo* pvi);
~HorizontalReduceBy2();
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) { return new HorizontalReduceBy2(args[0].clip); }
};
static PVideoFilter __cdecl Create_ReduceBy2(const FilterInfo*, const Arg* args, const char*) {
return new VerticalReduceBy2(new HorizontalReduceBy2(args[0].clip));
}
class Crop : public GenericVideoFilter {
/*const*/ int left, top, width, height;
unsigned char* mybuffer;
public:
Crop(int _left, int _top, int _width, int _height, PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
void GetVideoInfo(VideoInfo* pvi);
~Crop();
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
return new Crop(args[0].integer, args[1].integer, args[2].integer, args[3].integer, args[4].clip);
}
};
class AddBorders : public GenericVideoFilter {
/*const*/ int left, top, right, bot;
unsigned char* mybuffer;
public:
AddBorders(int _left, int _top, int _right, int _bot, PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
void GetVideoInfo(VideoInfo* pvi);
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
return new AddBorders(args[0].integer, args[1].integer, args[2].integer, args[3].integer, args[4].clip);
}
};
class Letterbox : public GenericVideoFilter {
const int top, bot;
public:
Letterbox(int _top, int _bot, PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
return new Letterbox(args[0].integer, args[1].integer, args[2].clip);
}
};
class FixLuminance : public GenericVideoFilter {
const int vertex, slope;
public:
FixLuminance(int _vertex, int _slope, PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
return new FixLuminance(args[0].integer, int(args[1].floating_pt*16), args[2].clip);
}
};
class PeculiarBlend : public GenericVideoFilter {
const int cutoff;
unsigned char *frame;
int frame_num;
public:
PeculiarBlend(int _cutoff, PVideoFilter _child);
void GetFrame(int n, unsigned char* buf);
~PeculiarBlend();
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
return new PeculiarBlend(args[0].integer, args[1].clip);
}
};
/********************************************************************
********************************************************************/
#include <math.h>
class ResamplingFunction {
public:
virtual double f(double x) = 0;
virtual double support() = 0;
};
class TriangleFilter : public ResamplingFunction {
public:
double f(double x) {
x = fabs(x);
return (x<1.0) ? 1.0-x : 0.0;
}
double support() { return 1.0; }
};
class MitchellNetravaliFilter : public ResamplingFunction {
double p0,p2,p3,q0,q1,q2,q3;
public:
MitchellNetravaliFilter(double b=1./3., double c=1./3.) {
p0 = ( 6. - 2.*b ) / 6.;
p2 = (-18. + 12.*b + 6.*c) / 6.;
p3 = ( 12. - 9.*b - 6.*c) / 6.;
q0 = ( 8.*b + 24.*c) / 6.;
q1 = ( - 12.*b - 48.*c) / 6.;
q2 = ( 6.*b + 30.*c) / 6.;
q3 = ( - b - 6.*c) / 6.;
}
double f(double x) {
x = fabs(x);
return (x<1) ? (p0+x*x*(p2+x*p3)) : (x<2) ? (q0+x*(q1+x*(q2+x*q3))) : 0.0;
}
double support() { return 2.0; }
};
// This function returns a resampling "program" which is interpreted by the
// FilteredResize filters. It handles edge conditions so FilteredResize
// doesn't have to.
static int* GetResamplingPattern(int original_width, double subrange_start, double subrange_width, int target_width, ResamplingFunction* func) {
double scale = double(target_width) / subrange_width;
double filter_step = min(scale, 1.0);
double filter_support = func->support() / filter_step;
int fir_filter_size = int(ceil(filter_support*2));
int* result = new int[1 + target_width*(1+fir_filter_size)];
int* cur = result;
*cur++ = fir_filter_size;
double pos_step = subrange_width / target_width;
// the following translates such that the image center remains fixed
double pos = subrange_start + ((subrange_width - target_width) / (target_width*2));
for (int i=0; i<target_width; ++i) {
int end_pos = int(pos + filter_support);
if (end_pos > original_width-1)
end_pos = original_width-1;
int start_pos = end_pos - fir_filter_size + 1;
if (start_pos < 0)
start_pos = 0;
*cur++ = start_pos;
// the following code ensures that the coefficients add to exactly 65536
double total = 0.0;
for (int j=0; j<fir_filter_size; ++j)
total += func->f((start_pos+j - pos) * filter_step);
double total2 = 0.0;
for (int k=0; k<fir_filter_size; ++k) {
double total3 = total2 + func->f((start_pos+k - pos) * filter_step) / total;
*cur++ = int(total3*65536+0.5) - int(total2*65536+0.5);
total2 = total3;
}
pos += pos_step;
}
return result;
}
class FilteredResizeH : public GenericVideoFilter {
const int target_width;
int* /*const*/ pattern_luma;
int* /*const*/ pattern_chroma;
unsigned char* srcbuffer;
public:
FilteredResizeH(double subrange_left, double subrange_width, int _target_width, ResamplingFunction* func, PVideoFilter _child)
: GenericVideoFilter(_child), target_width(_target_width)
{
pattern_chroma = 0;
if (vi.IsYUY2()) {
if (target_width&1)
throw FilterChainError("Resize: YUY2 width must be even");
pattern_chroma = GetResamplingPattern(vi.width>>1, subrange_left/2, subrange_width/2, target_width>>1, func);
}
pattern_luma = GetResamplingPattern(vi.width, subrange_left, subrange_width, target_width, func);
srcbuffer = new unsigned char[vi.ImageSize()];
}
void GetFrame(int n, unsigned char* buf) {
child->GetFrame(n, srcbuffer);
unsigned char* base = srcbuffer;
unsigned char* out = buf;
int src_row_size = vi.RowSize();
if (vi.IsYUY2()) {
int dst_row_size = target_width*2;
for (int y=0; y<vi.height; ++y) {
int* cur = pattern_luma+1;
for (int x=0; x<target_width; ++x) {
int total = 0;
int ofs = *cur++;
for (int a=0; a<pattern_luma[0]; ++a)
total += base[(ofs+a)*2] * (*cur++);
out[x*2] = ScaledPixelClip(total);
}
cur = pattern_chroma+1;
for (int xx=0; xx<target_width; xx+=2) {
int utotal = 0, vtotal = 0;
int ofs = *cur++;
for (int a=0; a<pattern_chroma[0]; ++a) {
utotal += base[(ofs+a)*4+1] * (*cur);
vtotal += base[(ofs+a)*4+3] * (*cur);
++cur;
}
out[xx*2+1] = ScaledPixelClip(utotal);
out[xx*2+3] = ScaledPixelClip(vtotal);
}
base += src_row_size;
out += dst_row_size;
}
} else {
int dst_row_size = target_width*3;
for (int y=0; y<vi.height; ++y) {
int* cur = pattern_luma+1;
for (int x=0; x<target_width; ++x) {
int btotal = 0, gtotal = 0, rtotal = 0;
int ofs = *cur++;
for (int a=0; a<pattern_luma[0]; ++a) {
btotal += base[(ofs+a)*3] * (*cur);
gtotal += base[(ofs+a)*3+1] * (*cur);
rtotal += base[(ofs+a)*3+2] * (*cur);
++cur;
}
out[x*3] = ScaledPixelClip(btotal);
out[x*3+1] = ScaledPixelClip(gtotal);
out[x*3+2] = ScaledPixelClip(rtotal);
}
base += src_row_size;
out += dst_row_size;
}
}
}
void GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->width = target_width;
}
~FilteredResizeH() {
if (pattern_luma) delete[] pattern_luma;
if (pattern_chroma) delete[] pattern_chroma;
if (srcbuffer) delete[] srcbuffer;
}
};
class FilteredResizeV : public GenericVideoFilter {
const int target_height;
int* /*const*/ resampling_pattern;
unsigned char* srcbuffer;
public:
FilteredResizeV(double subrange_top, double subrange_height, int _target_height, ResamplingFunction* func, PVideoFilter _child)
: GenericVideoFilter(_child), target_height(_target_height)
{
if (vi.IsRGB())
subrange_top = vi.height - subrange_top - subrange_height;
resampling_pattern = GetResamplingPattern(vi.height, subrange_top, subrange_height, target_height, func);
srcbuffer = new unsigned char[vi.ImageSize()];
}
void GetFrame(int n, unsigned char* buf) {
child->GetFrame(n, srcbuffer);
int* cur = resampling_pattern;
int fir_filter_width = *cur++;
int row_size = vi.RowSize();
unsigned char* out = buf;
for (int y=0; y<target_height; ++y) {
unsigned char* base = srcbuffer + row_size * (*cur++);
for (int x=0; x<row_size; ++x) {
int total = 0;
unsigned char* base2 = base+x;
for (int b=0; b<fir_filter_width; ++b) {
total += *base2 * cur[b];
base2 += row_size;
}
*out++ = ScaledPixelClip(total);
}
cur += fir_filter_width;
}
}
void GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->height = target_height;
}
~FilteredResizeV() {
if (resampling_pattern) delete[] resampling_pattern;
if (srcbuffer) delete[] srcbuffer;
}
};
static PVideoFilter CreateResizeH(double subrange_left, double subrange_width, int target_width, ResamplingFunction* func, PVideoFilter clip) {
if (subrange_width == target_width) {
VideoInfo vi;
clip->GetVideoInfo(&vi);
if (subrange_left == 0 && subrange_width == vi.width)
return clip;
else
return new Crop(int(subrange_left), 0, int(subrange_width), vi.height, clip);
} else {
return new FilteredResizeH(subrange_left, subrange_width, target_width, func, clip);
}
}
static PVideoFilter CreateResizeV(double subrange_top, double subrange_height, int target_height, ResamplingFunction* func, PVideoFilter clip) {
if (subrange_height == target_height) {
VideoInfo vi;
clip->GetVideoInfo(&vi);
if (subrange_top == 0 && subrange_height == vi.height)
return clip;
else
return new Crop(0, int(subrange_top), vi.width, int(subrange_height), clip);
} else {
return new FilteredResizeV(subrange_top, subrange_height, target_height, func, clip);
}
}
static PVideoFilter CreateResize(const Arg* args, const char* arg_types, ResamplingFunction* f) {
if (strlen(arg_types) == 3) {
VideoInfo vi;
args[2].clip->GetVideoInfo(&vi);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -