Skip to content

Commit

Permalink
Issue #337: Add resamplers kernels, backport from https://github.com/…
Browse files Browse the repository at this point in the history
  • Loading branch information
pinterf committed Feb 17, 2023
1 parent 71b035d commit 8e40c88
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 4 deletions.
6 changes: 6 additions & 0 deletions avs_core/convert/convert_planar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1613,6 +1613,12 @@ static ResamplingFunction* getResampler( const char* resampler, IScriptEnvironme
return new GaussianFilter(30.0); // Parse out optional P= from string
else if (!lstrcmpi(resampler, "sinc"))
return new SincFilter(4); // Parse out optional Taps= from string
else if (!lstrcmpi(resampler, "sinpow"))
return new SinPowerFilter(2.5); // Parse out optional P= from string.
else if (!lstrcmpi(resampler, "sinclin2"))
return new SincLin2Filter(15); // Parse out optional Taps= from string
else if (!lstrcmpi(resampler, "userdefined2"))
return new UserDefined2Filter(121.0, 19.0); // Parse out optional B= and C= from string
else
env->ThrowError("Convert: Unknown chroma resampler, '%s'", resampler);
}
Expand Down
24 changes: 24 additions & 0 deletions avs_core/filters/resample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ extern const AVSFunction Resample_filters[] = {
{ "Spline64Resize", BUILTIN_FUNC_PREFIX, "cii[src_left]f[src_top]f[src_width]f[src_height]f", FilteredResize::Create_Spline64Resize},
{ "GaussResize", BUILTIN_FUNC_PREFIX, "cii[src_left]f[src_top]f[src_width]f[src_height]f[p]f", FilteredResize::Create_GaussianResize},
{ "SincResize", BUILTIN_FUNC_PREFIX, "cii[src_left]f[src_top]f[src_width]f[src_height]f[taps]i", FilteredResize::Create_SincResize},
{ "SinPowerResize", BUILTIN_FUNC_PREFIX, "cii[src_left]f[src_top]f[src_width]f[src_height]f[p]f", FilteredResize::Create_SinPowerResize},
{ "SincLin2Resize", BUILTIN_FUNC_PREFIX, "cii[src_left]f[src_top]f[src_width]f[src_height]f[taps]i", FilteredResize::Create_SincLin2Resize},
{ "UserDefined2Resize", BUILTIN_FUNC_PREFIX, "cii[b]f[c]f[src_left]f[src_top]f[src_width]f[src_height]f", FilteredResize::Create_UserDefined2Resize},
/**
* Resize(PClip clip, dst_width, dst_height [src_left, src_top, src_width, int src_height,] )
*
Expand Down Expand Up @@ -1092,3 +1095,24 @@ AVSValue __cdecl FilteredResize::Create_SincResize(AVSValue args, void*, IScript
return CreateResize(args[0].AsClip(), args[1].AsInt(), args[2].AsInt(), &args[3], &f, env);
}

// like GaussianFilter(); optional P
AVSValue __cdecl FilteredResize::Create_SinPowerResize(AVSValue args, void*, IScriptEnvironment* env)
{
auto f = SinPowerFilter(args[7].AsFloat(2.5f));
return CreateResize(args[0].AsClip(), args[1].AsInt(), args[2].AsInt(), &args[3], &f, env);
}

// like SincFilter or LanczosFilter: optional Taps
AVSValue __cdecl FilteredResize::Create_SincLin2Resize(AVSValue args, void*, IScriptEnvironment* env)
{
auto f = SincLin2Filter(args[7].AsInt(15));
return CreateResize(args[0].AsClip(), args[1].AsInt(), args[2].AsInt(), &args[3], &f, env);
}

// like bicubic: optional B and C
AVSValue __cdecl FilteredResize::Create_UserDefined2Resize(AVSValue args, void*, IScriptEnvironment* env)
{
auto f = UserDefined2Filter(args[3].AsFloat(121.0), args[4].AsFloat(19.0));
return CreateResize(args[0].AsClip(), args[1].AsInt(), args[2].AsInt(), &args[5], &f, env);
}

6 changes: 6 additions & 0 deletions avs_core/filters/resample.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,12 @@ class FilteredResize
static AVSValue __cdecl Create_GaussianResize(AVSValue args, void*, IScriptEnvironment* env);

static AVSValue __cdecl Create_SincResize(AVSValue args, void*, IScriptEnvironment* env);

static AVSValue __cdecl Create_SinPowerResize(AVSValue args, void*, IScriptEnvironment* env);

static AVSValue __cdecl Create_SincLin2Resize(AVSValue args, void*, IScriptEnvironment* env);

static AVSValue __cdecl Create_UserDefined2Resize(AVSValue args, void*, IScriptEnvironment* env);
};


Expand Down
93 changes: 90 additions & 3 deletions avs_core/filters/resample_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,11 @@ double GaussianFilter::f(double value) {
*** Sinc filter ***
***********************/
SincFilter::SincFilter(int _taps) {
taps = (double)clamp(_taps, 1, 20);
taps = (double)clamp(_taps, 1, 150);
}

double SincFilter::f(double value) {
value = fabs(value);
value = fabs(value);

if (value > 0.000001) {
value *= M_PI;
Expand All @@ -228,6 +228,92 @@ double SincFilter::f(double value) {
}


/**********************
*** SinPower filter ***
***********************/

SinPowerFilter::SinPowerFilter(double p) {
param = clamp(p, 1.0, 10.0);
}

double SinPowerFilter::f(double value) {
value = fabs(value);
value *= M_PI / param;

if (value < (M_PI / 2)) return pow(cos(value), 1.8);
else
{
if (value < M_PI) return -(cos(value) * cos(value)) / (0.9 * value);
else return 0;
}
}

/***********************
*** SincLin2 filter ***
***********************/

SincLin2Filter::SincLin2Filter(int _taps)
{
taps = (double)clamp(_taps, 1, 30);
}

double SincLin2Filter::sinc(double value)
{
if (value > 0.000001)
{
value *= M_PI;
return sin(value) / value;
}
else return 1.0;
}

double SincLin2Filter::f(double value)
{
value = fabs(value);

if (value < (taps / 2.0)) return sinc(value);
else return sinc(value) * ((2.0 - (2.0 * value / taps)));

}


/*********************************
*** UserDefined2 filter ***
*********************************/

UserDefined2Filter::UserDefined2Filter(double _b, double _c)
{
a = 1.0; // 0 sample = 1
b = (double)clamp(_b, -50.0, 250.0); // 1 and -1 sample
c = (double)clamp(_c, -50.0, 250.0); // 2 and -2 sample
b = (b - 16.0) / 219.0;
c = (c - 16.0) / 219.0;
}

double UserDefined2Filter::sinc(double value)
{

if (fabs(value) > 0.000001)
{
value *= M_PI;
return sin(value) / value;
}
else return 1.0;
}

double UserDefined2Filter::f(double x)
{
x = fabs(x);

if (x <= 3) // ?
{
return c * sinc(x + 2) + b * sinc(x + 1) + a * sinc(x) + b * sinc(x - 1) + c * sinc(x - 2);
}
else return 0;

}


/******************************
**** Resampling Patterns ****
*****************************/
Expand Down Expand Up @@ -313,7 +399,8 @@ ResamplingProgram* ResamplingFunction::GetResamplingProgram(int source_size, dou
for (int k = 0; k < fir_filter_size; ++k) {
double new_value = value + f((start_pos + k - ok_pos) * filter_step) / total;
// FIXME: is it correct to round negative values upwards?
program->pixel_coefficient[i*fir_filter_size + k] = short(int(new_value*current_FPScale + 0.5) - int(value*current_FPScale + 0.5)); // to make it round across pixels
// Answer : No with int cast, yes with floor() instead.
program->pixel_coefficient[i*fir_filter_size + k] = (short)((int)(new_value*current_FPScale + 0.5) - int(value*current_FPScale + 0.5)); // to make it round across pixels
value = new_value;
}
}
Expand Down
44 changes: 43 additions & 1 deletion avs_core/filters/resample_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ struct ResamplingProgram {
else
pixel_coefficient_float = (float*)Env->Allocate(sizeof(float) * target_size * filter_size, 64, AVS_NORMAL_ALLOC);

if (!pixel_offset || (!pixel_coefficient && bits_per_pixel < 32) || (!pixel_coefficient_float && bits_per_pixel == 32)) {
if ((pixel_offset == nullptr) || (pixel_coefficient == nullptr && bits_per_pixel < 32) ||
(pixel_coefficient_float == nullptr && bits_per_pixel == 32)) {
Env->Free(pixel_offset);
Env->Free(pixel_coefficient);
Env->Free(pixel_coefficient_float);
Expand Down Expand Up @@ -263,5 +264,46 @@ class SincFilter : public ResamplingFunction
double taps;
};

class SinPowerFilter : public ResamplingFunction
// SinPow kernel, used in SinPowResize
{
public:
SinPowerFilter(double p = 2.5);
double f(double x);
double support() { return 2.0; }; // 2 very important, 4 cause bugs

private:
double param;
};

class SincLin2Filter : public ResamplingFunction
/**
* SincLin2 filter, used in SincLin2Resize
**/
{
public:
SincLin2Filter(int _taps = 15);
double f(double x);
double support() { return taps; };

private:
double sinc(double value);
double taps;
};

class UserDefined2Filter : public ResamplingFunction
/**
* User-defined by 2 samples filter, used in UDef2Resize
**/
{
public:
UserDefined2Filter(double _b = 121.0, double _c = 19.0);
double f(double x);
double support() { return 2.0; }

private:
double sinc(double value);
double a, b, c;
};

#endif // __Reample_Functions_H__

0 comments on commit 8e40c88

Please sign in to comment.