Skip to content

Commit

Permalink
Add Lanczos antialiasing
Browse files Browse the repository at this point in the history
  • Loading branch information
scarletcafe committed Mar 31, 2019
1 parent b0d6af2 commit 99a1601
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 47 deletions.
142 changes: 100 additions & 42 deletions InvEqui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ static PF_Err ParamsSetup (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef
KEEPLAYER_PARAM_ID
);

AEFX_CLR_STRUCT(def);

PF_ADD_CHECKBOX(
STR(StrID_Antialias_Param_Name),
STR(StrID_Antialias_Param_Desc),
TRUE,
0,
ANTIALIAS_PARAM_ID
);

out_data->num_params = INVEQUI_NUM_PARAMS;

return PF_Err_NONE;
Expand All @@ -87,10 +97,64 @@ struct RenderArgs {
PF_ParamDef *scanLayer;
};

inline PF_Pixel *sampleIntegral8(PF_EffectWorld &def, int x, int y) {
inline PF_Pixel8 *sampleIntegral8(PF_EffectWorld &def, int x, int y) {
return (PF_Pixel8*)((char*)def.data + (y * def.rowbytes) + (x * sizeof(PF_Pixel8)));
}

inline PF_Pixel8 boundedIntegral(PF_EffectWorld &def, int x, int y) {
if (x < 0 || y < 0)
return {0, 0, 0, 0};
if (x > def.width || y > def.height)
return {0, 0, 0, 0};

PF_Pixel8 *ptr = sampleIntegral8(def, x, y);
if (ptr == nullptr)
return {0, 0, 0, 0};

return *ptr;
}

inline PF_Pixel8 lanczosSample(PF_EffectWorld &def, float x, float y) {
int xi = static_cast<int>(x);
int yi = static_cast<int>(y);
float xo = x - static_cast<float>(xi);
float yo = y - static_cast<float>(yi);

float lx, ly;
float a, r, g, b;
float y_a, y_r, y_g, y_b;

a = r = g = b = 0.0f;

for (int iy = -3; iy <= 3; iy++) {
y_a = y_r = y_g = y_b = 0.0f;

for (int ix = -3; ix <= 3; ix++) {
lx = Math3D::lanczos(xo - ix);
PF_Pixel px = boundedIntegral(def, xi + ix, yi + iy);

y_a += lx * px.alpha;
y_r += lx * px.red;
y_g += lx * px.green;
y_b += lx * px.blue;
}

ly = Math3D::lanczos(yo - iy);

a += ly * y_a;
r += ly * y_r;
g += ly * y_g;
b += ly * y_b;
}

return {
static_cast<A_u_char>(fmaxf(fminf(255.0f, a), 0.0f)),
static_cast<A_u_char>(fmaxf(fminf(255.0f, r), 0.0f)),
static_cast<A_u_char>(fmaxf(fminf(255.0f, g), 0.0f)),
static_cast<A_u_char>(fmaxf(fminf(255.0f, b), 0.0f))
};
}

static PF_Err SubSample_Pixel8(void *refcon, A_long x, A_long y, PF_Pixel8 *inP, PF_Pixel8 *outP) {
PF_Err err = PF_Err_NONE;
RenderArgs* rArgs = reinterpret_cast<RenderArgs*>(refcon);
Expand All @@ -107,79 +171,67 @@ static PF_Err SubSample_Pixel8(void *refcon, A_long x, A_long y, PF_Pixel8 *inP,
fov = fminf(fmaxf(fov, 0.1f), 179.9f);

bool keepLayer = static_cast<bool>(rArgs->params[INVEQUI_KEEPLAYER]->u.bd.value);
bool antialias = static_cast<bool>(rArgs->params[INVEQUI_ANTIALIAS]->u.bd.value);

Math3D::Vector3D<float> model =
Math3D::Vector3D<> model =
Math3D::rotate(
Math3D::rotate(
Math3D::Vector3D<float>(0.0f, 0.0f, -1.0f),
Math3D::Vector3D<>(0.0f, 0.0f, -1.0f),
Math3D::radians(pitchDeg),
Math3D::Vector3D<float>(1.0f, 0.0f, 0.0f)
Math3D::Vector3D<>(1.0f, 0.0f, 0.0f)
),
Math3D::radians(yawDeg),
Math3D::Vector3D<float>(0.0f, 1.0f, 0.0f)
Math3D::Vector3D<>(0.0f, 1.0f, 0.0f)
);

Math3D::Vector3D<float> view =
Math3D::Vector3D<> view =
Math3D::rotate(
Math3D::rotate(
model,
Math3D::radians(-yaw),
Math3D::Vector3D<float>(0.0f, 1.0f, 0.0f)
Math3D::Vector3D<>(0.0f, 1.0f, 0.0f)
),
Math3D::radians(-pitch),
Math3D::Vector3D<float>(1.0f, 0.0f, 0.0f)
Math3D::Vector3D<>(1.0f, 0.0f, 0.0f)
);

Math3D::Vector3D<float> screen =
Math3D::Vector3D<> screen =
Math3D::perspective(
view,
Math3D::radians(fov),
static_cast<float>(sample.width) / static_cast<float>(sample.height)
);

if (screen.z < -1.0f || screen.z > 1.0f || screen.x < -1.0f || screen.x > 1.0f || screen.y < -1.0f || screen.y > 1.0f) {
if (keepLayer) {
outP->red = inP->red;
outP->green = inP->green;
outP->blue = inP->blue;
outP->alpha = inP->alpha;
}
else {
outP->red = 0;
outP->green = 0;
outP->blue = 0;
outP->alpha = 0;
}
}
else {
float samplePosX = (screen.x + 1.0f) * 0.5f * static_cast<float>(sample.width);
float samplePosY = (1.0f - ((screen.y + 1.0f) * 0.5f)) * static_cast<float>(sample.height);

int sX = static_cast<int>(samplePosX);
int sY = static_cast<int>(samplePosY);
float width = static_cast<float>(sample.width);
float height = static_cast<float>(sample.height);

PF_Pixel* sampleP = sampleIntegral8(sample, sX, sY);
float samplePosX = (screen.x + 1.0f) * 0.5f * width;
float samplePosY = (1.0f - ((screen.y + 1.0f) * 0.5f)) * height;

if (sampleP != nullptr) {
outP->red = sampleP->red;
outP->green = sampleP->green;
outP->blue = sampleP->blue;
outP->alpha = sampleP->alpha;
if (screen.z < -1.0f || screen.z > 1.0f || samplePosX < -2.0f || samplePosY < -2.0f || samplePosX + 1.0f > width || samplePosY + 1.0f > height) {
if (keepLayer)
*outP = *inP;
else
*outP = { 0, 0, 0, 0 };
} else {
if (antialias) {
*outP = lanczosSample(sample, samplePosX, samplePosY);
}
else {
outP->red = 255;
outP->green = 255;
outP->blue = 0;
outP->alpha = 255;
int sX = static_cast<int>(samplePosX);
int sY = static_cast<int>(samplePosY);

*outP = boundedIntegral(sample, sX, sY);
}
}

return err;
}

static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *params[], PF_LayerDef *output) {
PF_Err err = PF_Err_NONE;
AEGP_SuiteHandler suites(in_data->pica_basicP);
PF_Err err = PF_Err_NONE,
err2 = PF_Err_NONE;
AEGP_SuiteHandler suites(in_data->pica_basicP);

PF_ParamDef scanLayer;

Expand All @@ -189,7 +241,7 @@ static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *par
&scanLayer
};

A_long progress_baseL = 0, progress_finalL = 1;
A_long progress_baseL = 0, progress_finalL = 3;

ERR(PF_CHECKOUT_PARAM(
in_data,
Expand All @@ -200,6 +252,8 @@ static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *par
&scanLayer
));

progress_baseL++;

ERR(suites.Iterate8Suite1()->iterate(
in_data,
progress_baseL,
Expand All @@ -213,6 +267,10 @@ static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *par

progress_baseL++;

ERR2(PF_CHECKIN_PARAM(in_data, &scanLayer));

progress_baseL++;

return err;
}

Expand Down
4 changes: 3 additions & 1 deletion InvEqui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/* Versioning information */

#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define MINOR_VERSION 1
#define BUG_VERSION 0
#define STAGE_VERSION PF_Stage_DEVELOP
#define BUILD_VERSION 1
Expand All @@ -39,6 +39,7 @@ enum {
INVEQUI_YAW,
INVEQUI_PITCH,
INVEQUI_KEEPLAYER,
INVEQUI_ANTIALIAS,
INVEQUI_NUM_PARAMS
};

Expand All @@ -48,6 +49,7 @@ enum {
YAW_PARAM_ID,
PITCH_PARAM_ID,
KEEPLAYER_PARAM_ID,
ANTIALIAS_PARAM_ID,
};


Expand Down
2 changes: 2 additions & 0 deletions InvEqui_Strings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ TableString g_strs[StrID_NUMTYPES] = {
StrID_Pitch_Param_Name, "Pitch",
StrID_KeepLayer_Param_Name, "Preserve layer",
StrID_KeepLayer_Param_Desc, "Keep",
StrID_Antialias_Param_Name, "Antialias",
StrID_Antialias_Param_Desc, "Use",
};


Expand Down
2 changes: 2 additions & 0 deletions InvEqui_Strings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ typedef enum {
StrID_Pitch_Param_Name,
StrID_KeepLayer_Param_Name,
StrID_KeepLayer_Param_Desc,
StrID_Antialias_Param_Name,
StrID_Antialias_Param_Desc,
StrID_NUMTYPES
} StrIDType;
18 changes: 18 additions & 0 deletions Math3D.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,22 @@ namespace Math3D {
return Vector3D<T>(x / w, y / w, z / w);
}

template <typename T = float>
T sinc(T x) {
if (x == static_cast<T>(0))
return static_cast<T>(1);

T xi = radians(x * static_cast<T>(180));

return sin(xi) / xi;
}

template <typename T = float>
T lanczos(T x, T a = static_cast<T>(3)) {
if (-a <= x || x < a)
return sinc(x) * sinc(x / a);

return 0;
}

}
8 changes: 4 additions & 4 deletions Win/InvEqui.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>
Expand Down

0 comments on commit 99a1601

Please sign in to comment.