📄 effects.cpp
字号:
return CreateResizeV(0, vi.height, args[1].integer, f, CreateResizeH(0, vi.width, args[0].integer, f, args[2].clip));
} else {
const double subrange_left = args[0].floating_pt, subrange_top = args[1].floating_pt;
const double subrange_width = args[2].floating_pt, subrange_height = args[3].floating_pt;
const int target_width = args[4].integer, target_height = args[5].integer;
if (target_width == subrange_width && target_height == subrange_height)
return new Crop(int(subrange_left), int(subrange_top), int(subrange_width), int(subrange_height), args[6].clip);
else
return CreateResizeV(subrange_top, subrange_height, target_height, f, CreateResizeH(subrange_left, subrange_width, target_width, f, args[6].clip));
}
}
static PVideoFilter __cdecl Create_BilinearResize(const FilterInfo*, const Arg* args, const char* arg_types) {
return CreateResize(args, arg_types, &TriangleFilter());
}
static PVideoFilter __cdecl Create_BicubicResize(const FilterInfo*, const Arg* args, const char* arg_types) {
return CreateResize(args, arg_types, &MitchellNetravaliFilter(1./3.,1./3.));
}
static PVideoFilter __cdecl Create_BicubicResizeBC(const FilterInfo*, const Arg* args, const char* arg_types) {
return CreateResize(args+2, arg_types+2, &MitchellNetravaliFilter(args[0].floating_pt,args[1].floating_pt));
}
/********************************************************************
********************************************************************/
class Fieldwise : public GenericVideoFilter {
PVideoFilter child2;
public:
Fieldwise(PVideoFilter _child1, PVideoFilter _child2) : GenericVideoFilter(_child1), child2(_child2) {}
void GetFrame(int n, unsigned char* buf) {
(child->GetParity(n) ? child2 : child)->GetFrame(n, buf);
}
};
static PVideoFilter __cdecl Create_Bob(const FilterInfo*, const Arg* args, const char* arg_types) {
double b=1./3., c=1./3.;
if (arg_types[0] == 'f') {
b = args[0].floating_pt;
c = args[1].floating_pt;
args += 2;
arg_types += 2;
}
PVideoFilter clip = args[0].clip;
VideoInfo vi;
clip->GetVideoInfo(&vi);
if (!vi.field_based) {
clip = new_SeparateFields(clip);
clip->GetVideoInfo(&vi);
}
MitchellNetravaliFilter filter(b, c);
return new Fieldwise(new FilteredResizeV(-0.25, vi.height, vi.height*2, &filter, clip), new FilteredResizeV(+0.25, vi.height, vi.height*2, &filter, clip));
}
/********************************************************************
********************************************************************/
VerticalReduceBy2::VerticalReduceBy2(PVideoFilter _child)
: GenericVideoFilter(_child), mybuffer(0) {}
void VerticalReduceBy2::GetFrame(int n, unsigned char* buf) {
if (!mybuffer)
mybuffer = new unsigned char[vi.ImageSize()];
child->GetFrame(n, mybuffer);
int row_size = vi.RowSize();
for (int y=0; y<(vi.height>>1); ++y) {
unsigned char* line0 = mybuffer + (y*2)*row_size;
unsigned char* line1 = line0 + row_size;
unsigned char* line2 = (y*2 < vi.height-2) ? (line1 + row_size) : line0;
unsigned char* out = buf + y*row_size;
for (int x=0; x<row_size; ++x)
out[x] = (line0[x] + 2*line1[x] + line2[x] + 2) >> 2;
}
}
void VerticalReduceBy2::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->height >>= 1;
}
VerticalReduceBy2::~VerticalReduceBy2() { if (mybuffer) delete[] mybuffer; }
HorizontalReduceBy2::HorizontalReduceBy2(PVideoFilter _child)
: GenericVideoFilter(_child), mybuffer(0)
{
if (vi.IsYUY2() && (vi.width & 3))
throw FilterChainError("HorizontalReduceBy2: YUY2 image width must be even");
}
void HorizontalReduceBy2::GetFrame(int n, unsigned char* buf) {
if (!mybuffer)
mybuffer = new unsigned char[vi.ImageSize()];
child->GetFrame(n, mybuffer);
unsigned char* src = mybuffer;
unsigned char* dst = buf;
if (vi.IsYUY2()) {
for (int y = vi.height; y; --y) {
for (int x = (vi.width>>2)-1; x; --x) {
dst[0] = (src[0] + 2*src[2] + src[4] + 2) >> 2;
dst[1] = (src[1] + 2*src[5] + src[9] + 2) >> 2;
dst[2] = (src[4] + 2*src[6] + src[8] + 2) >> 2;
dst[3] = (src[3] + 2*src[7] + src[11] + 2) >> 2;
dst += 4;
src += 8;
}
dst[0] = (src[0] + 2*src[2] + src[4] + 2) >> 2;
dst[1] = (src[1] + src[5] + 1) >> 1;
dst[2] = (src[4] + src[6] + 1) >> 1;
dst[3] = (src[3] + src[7] + 1) >> 1;
dst += 4;
src += 8;
}
} else {
for (int y = vi.height; y; --y) {
for (int x = (vi.width-1)>>1; x; --x) {
dst[0] = (src[0] + 2*src[3] + src[6] + 2) >> 2;
dst[1] = (src[1] + 2*src[4] + src[7] + 2) >> 2;
dst[2] = (src[2] + 2*src[5] + src[8] + 2) >> 2;
dst += 3;
src += 6;
}
if (vi.width&1) {
src += 3;
} else {
dst[0] = (src[0] + src[3] + 1) >> 1;
dst[1] = (src[1] + src[4] + 1) >> 1;
dst[2] = (src[2] + src[5] + 1) >> 1;
dst += 3;
src += 6;
}
}
}
}
void HorizontalReduceBy2::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->width >>= 1;
}
HorizontalReduceBy2::~HorizontalReduceBy2() { if (mybuffer) delete[] mybuffer; }
/********************************************************************
********************************************************************/
Crop::Crop(int _left, int _top, int _width, int _height, PVideoFilter _child)
: GenericVideoFilter(_child), left(_left), top(_top), width(_width), height(_height), mybuffer(0)
{
if (vi.IsYUY2()) {
// YUY2 can only crop to even pixel boundaries horizontally
left = left & -2;
width = (width+1) & -2;
} else {
// RGB is upside-down
top = vi.height - height - top;
}
}
void Crop::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->width = width;
pvi->height = height;
}
void Crop::GetFrame(int n, unsigned char* buf) {
if (!mybuffer)
mybuffer = new unsigned char[vi.ImageSize()];
child->GetFrame(n, mybuffer);
int row_size = vi.RowSize();
int cropped_row_size = width * vi.pixel_type;
int offset = (top*vi.width+left) * vi.pixel_type;
for (int y=0; y<height; ++y)
memcpy(buf+cropped_row_size*y, mybuffer+row_size*y+offset, cropped_row_size);
}
Crop::~Crop() {
if (mybuffer)
delete[] mybuffer;
}
class CropBottom : public GenericVideoFilter {
unsigned char* mybuffer;
const int bottom;
public:
CropBottom(int _bottom, PVideoFilter _child) : GenericVideoFilter(_child), bottom(_bottom), mybuffer(0) {}
void GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->height -= bottom;
}
void GetFrame(int n, unsigned char* buf) {
if (!mybuffer)
mybuffer = new unsigned char[vi.ImageSize()];
child->GetFrame(n, mybuffer);
if (vi.IsYUY2())
memcpy(buf, mybuffer, (vi.height-bottom) * vi.RowSize());
else
memcpy(buf, mybuffer + bottom * vi.RowSize(), (vi.height-bottom) * vi.RowSize());
}
~CropBottom() {
if (mybuffer)
delete[] mybuffer;
}
static PVideoFilter __cdecl Create(const FilterInfo*, const Arg* args, const char*) {
return new CropBottom(args[0].integer, args[1].clip);
}
};
AddBorders::AddBorders(int _left, int _top, int _right, int _bot, PVideoFilter _child)
: GenericVideoFilter(_child), left(_left), top(_top), right(_right), bot(_bot), mybuffer(0)
{
if (vi.IsYUY2()) {
// YUY2 can only crop to even pixel boundaries horizontally
left = left & -2;
right = (right+1) & -2;
} else {
// RGB is upside-down
swap(top, bot);
}
}
void AddBorders::GetVideoInfo(VideoInfo* pvi) {
*pvi = vi;
pvi->width += left+right;
pvi->height += top+bot;
}
void AddBorders::GetFrame(int n, unsigned char* buf) {
if (!mybuffer)
mybuffer = new unsigned char[vi.ImageSize()];
child->GetFrame(n, mybuffer);
int row_size = vi.RowSize();
int expanded_row_size = row_size + (left+right) * vi.pixel_type;
int offset = top * expanded_row_size + left * vi.pixel_type;
unsigned* last_blacken = (unsigned*)buf;
unsigned black = (vi.IsYUY2()) ? 0x80108010 : 0;
for (int y=0; y<vi.height; ++y) {
unsigned* dst = (unsigned*)(buf + offset + y*expanded_row_size);
while (last_blacken < dst)
*last_blacken++ = black;
memcpy(dst, mybuffer+row_size*y, row_size);
last_blacken += row_size>>2;
}
while (last_blacken < (unsigned*)(buf+expanded_row_size*(vi.height+top+bot)))
*last_blacken++ = black;
}
/********************************************************************
********************************************************************/
Letterbox::Letterbox(int _top, int _bot, PVideoFilter _child) : GenericVideoFilter(_child), top(_top), bot(_bot) {}
void Letterbox::GetFrame(int n, unsigned char* buf) {
child->GetFrame(n, buf);
if (vi.IsYUY2()) {
unsigned* p = (unsigned*)buf;
for (int i=top*vi.width/2; i>0; --i)
*p++ = 0x80108010; // black
unsigned *q = (unsigned*)(buf + (vi.height-bot)*vi.width*2);
for (int j=bot*vi.width/2; j>0; --j)
*q++ = 0x80108010; // black
} else {
memset(buf, 0, bot*vi.RowSize());
memset(buf+(vi.height-top)*vi.RowSize(), 0, top*vi.RowSize());
}
}
/********************************************************************
********************************************************************/
static void BlendIn(unsigned char* main, unsigned char* other, int pitch, int height, int cutoff) {
if (cutoff-31 > 0)
memcpy(main, other, min(cutoff-31, height)*pitch);
for (int y = max(0, cutoff-31); y < min(cutoff, height-1); ++y) {
int offset = y * pitch;
int scale = cutoff - y;
for (int x = 0; x < pitch; ++x)
main[offset+x] += ((other[offset+x] - main[offset+x]) * scale + 16) >> 5;
}
}
PeculiarBlend::PeculiarBlend(int _cutoff, PVideoFilter _child)
: GenericVideoFilter(_child), cutoff(_cutoff), frame(0)
{
if (!vi.IsYUY2())
throw FilterChainError("PeculiarBlend: requires YUY2 input");
}
void PeculiarBlend::GetFrame(int n, unsigned char* buf) {
if (frame && n == frame_num)
memcpy(buf, frame, vi.ImageSize());
else
child->GetFrame(n, buf);
if (!frame || frame_num != n+1) {
if (!frame)
frame = new unsigned char[vi.ImageSize()];
child->GetFrame(frame_num = n+1, frame);
}
BlendIn(buf, frame, vi.RowSize(), vi.height, cutoff);
}
PeculiarBlend::~PeculiarBlend() { if (frame) delete[] frame; }
/********************************************************************
********************************************************************/
FixLuminance::FixLuminance(int _vertex, int _slope, PVideoFilter _child)
: GenericVideoFilter(_child), vertex(_vertex), slope(_slope)
{
if (!vi.IsYUY2())
throw FilterChainError("FixLuminance: requires YUY2 input");
}
void FixLuminance::GetFrame(int n, unsigned char* buf) {
child->GetFrame(n, buf);
unsigned char* p = buf;
for (int y=0; y<=vertex-slope/16; ++y) {
int subtract = (vertex-y)*16/slope;
for (int x=0; x<vi.width; ++x) {
*p = max(0, *p-subtract);
p += 2;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -