Skip to content

Commit 99a1601

Browse files
committed
Add Lanczos antialiasing
1 parent b0d6af2 commit 99a1601

File tree

6 files changed

+129
-47
lines changed

6 files changed

+129
-47
lines changed

InvEqui.cpp

Lines changed: 100 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ static PF_Err ParamsSetup (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef
7676
KEEPLAYER_PARAM_ID
7777
);
7878

79+
AEFX_CLR_STRUCT(def);
80+
81+
PF_ADD_CHECKBOX(
82+
STR(StrID_Antialias_Param_Name),
83+
STR(StrID_Antialias_Param_Desc),
84+
TRUE,
85+
0,
86+
ANTIALIAS_PARAM_ID
87+
);
88+
7989
out_data->num_params = INVEQUI_NUM_PARAMS;
8090

8191
return PF_Err_NONE;
@@ -87,10 +97,64 @@ struct RenderArgs {
8797
PF_ParamDef *scanLayer;
8898
};
8999

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

104+
inline PF_Pixel8 boundedIntegral(PF_EffectWorld &def, int x, int y) {
105+
if (x < 0 || y < 0)
106+
return {0, 0, 0, 0};
107+
if (x > def.width || y > def.height)
108+
return {0, 0, 0, 0};
109+
110+
PF_Pixel8 *ptr = sampleIntegral8(def, x, y);
111+
if (ptr == nullptr)
112+
return {0, 0, 0, 0};
113+
114+
return *ptr;
115+
}
116+
117+
inline PF_Pixel8 lanczosSample(PF_EffectWorld &def, float x, float y) {
118+
int xi = static_cast<int>(x);
119+
int yi = static_cast<int>(y);
120+
float xo = x - static_cast<float>(xi);
121+
float yo = y - static_cast<float>(yi);
122+
123+
float lx, ly;
124+
float a, r, g, b;
125+
float y_a, y_r, y_g, y_b;
126+
127+
a = r = g = b = 0.0f;
128+
129+
for (int iy = -3; iy <= 3; iy++) {
130+
y_a = y_r = y_g = y_b = 0.0f;
131+
132+
for (int ix = -3; ix <= 3; ix++) {
133+
lx = Math3D::lanczos(xo - ix);
134+
PF_Pixel px = boundedIntegral(def, xi + ix, yi + iy);
135+
136+
y_a += lx * px.alpha;
137+
y_r += lx * px.red;
138+
y_g += lx * px.green;
139+
y_b += lx * px.blue;
140+
}
141+
142+
ly = Math3D::lanczos(yo - iy);
143+
144+
a += ly * y_a;
145+
r += ly * y_r;
146+
g += ly * y_g;
147+
b += ly * y_b;
148+
}
149+
150+
return {
151+
static_cast<A_u_char>(fmaxf(fminf(255.0f, a), 0.0f)),
152+
static_cast<A_u_char>(fmaxf(fminf(255.0f, r), 0.0f)),
153+
static_cast<A_u_char>(fmaxf(fminf(255.0f, g), 0.0f)),
154+
static_cast<A_u_char>(fmaxf(fminf(255.0f, b), 0.0f))
155+
};
156+
}
157+
94158
static PF_Err SubSample_Pixel8(void *refcon, A_long x, A_long y, PF_Pixel8 *inP, PF_Pixel8 *outP) {
95159
PF_Err err = PF_Err_NONE;
96160
RenderArgs* rArgs = reinterpret_cast<RenderArgs*>(refcon);
@@ -107,79 +171,67 @@ static PF_Err SubSample_Pixel8(void *refcon, A_long x, A_long y, PF_Pixel8 *inP,
107171
fov = fminf(fmaxf(fov, 0.1f), 179.9f);
108172

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

111-
Math3D::Vector3D<float> model =
176+
Math3D::Vector3D<> model =
112177
Math3D::rotate(
113178
Math3D::rotate(
114-
Math3D::Vector3D<float>(0.0f, 0.0f, -1.0f),
179+
Math3D::Vector3D<>(0.0f, 0.0f, -1.0f),
115180
Math3D::radians(pitchDeg),
116-
Math3D::Vector3D<float>(1.0f, 0.0f, 0.0f)
181+
Math3D::Vector3D<>(1.0f, 0.0f, 0.0f)
117182
),
118183
Math3D::radians(yawDeg),
119-
Math3D::Vector3D<float>(0.0f, 1.0f, 0.0f)
184+
Math3D::Vector3D<>(0.0f, 1.0f, 0.0f)
120185
);
121186

122-
Math3D::Vector3D<float> view =
187+
Math3D::Vector3D<> view =
123188
Math3D::rotate(
124189
Math3D::rotate(
125190
model,
126191
Math3D::radians(-yaw),
127-
Math3D::Vector3D<float>(0.0f, 1.0f, 0.0f)
192+
Math3D::Vector3D<>(0.0f, 1.0f, 0.0f)
128193
),
129194
Math3D::radians(-pitch),
130-
Math3D::Vector3D<float>(1.0f, 0.0f, 0.0f)
195+
Math3D::Vector3D<>(1.0f, 0.0f, 0.0f)
131196
);
132197

133-
Math3D::Vector3D<float> screen =
198+
Math3D::Vector3D<> screen =
134199
Math3D::perspective(
135200
view,
136201
Math3D::radians(fov),
137202
static_cast<float>(sample.width) / static_cast<float>(sample.height)
138203
);
139204

140-
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) {
141-
if (keepLayer) {
142-
outP->red = inP->red;
143-
outP->green = inP->green;
144-
outP->blue = inP->blue;
145-
outP->alpha = inP->alpha;
146-
}
147-
else {
148-
outP->red = 0;
149-
outP->green = 0;
150-
outP->blue = 0;
151-
outP->alpha = 0;
152-
}
153-
}
154-
else {
155-
float samplePosX = (screen.x + 1.0f) * 0.5f * static_cast<float>(sample.width);
156-
float samplePosY = (1.0f - ((screen.y + 1.0f) * 0.5f)) * static_cast<float>(sample.height);
157-
158-
int sX = static_cast<int>(samplePosX);
159-
int sY = static_cast<int>(samplePosY);
205+
float width = static_cast<float>(sample.width);
206+
float height = static_cast<float>(sample.height);
160207

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

163-
if (sampleP != nullptr) {
164-
outP->red = sampleP->red;
165-
outP->green = sampleP->green;
166-
outP->blue = sampleP->blue;
167-
outP->alpha = sampleP->alpha;
211+
if (screen.z < -1.0f || screen.z > 1.0f || samplePosX < -2.0f || samplePosY < -2.0f || samplePosX + 1.0f > width || samplePosY + 1.0f > height) {
212+
if (keepLayer)
213+
*outP = *inP;
214+
else
215+
*outP = { 0, 0, 0, 0 };
216+
} else {
217+
if (antialias) {
218+
*outP = lanczosSample(sample, samplePosX, samplePosY);
168219
}
169220
else {
170-
outP->red = 255;
171-
outP->green = 255;
172-
outP->blue = 0;
173-
outP->alpha = 255;
221+
int sX = static_cast<int>(samplePosX);
222+
int sY = static_cast<int>(samplePosY);
223+
224+
*outP = boundedIntegral(sample, sX, sY);
174225
}
175226
}
176227

177228
return err;
178229
}
179230

180231
static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *params[], PF_LayerDef *output) {
181-
PF_Err err = PF_Err_NONE;
182-
AEGP_SuiteHandler suites(in_data->pica_basicP);
232+
PF_Err err = PF_Err_NONE,
233+
err2 = PF_Err_NONE;
234+
AEGP_SuiteHandler suites(in_data->pica_basicP);
183235

184236
PF_ParamDef scanLayer;
185237

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

192-
A_long progress_baseL = 0, progress_finalL = 1;
244+
A_long progress_baseL = 0, progress_finalL = 3;
193245

194246
ERR(PF_CHECKOUT_PARAM(
195247
in_data,
@@ -200,6 +252,8 @@ static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *par
200252
&scanLayer
201253
));
202254

255+
progress_baseL++;
256+
203257
ERR(suites.Iterate8Suite1()->iterate(
204258
in_data,
205259
progress_baseL,
@@ -213,6 +267,10 @@ static PF_Err Render (PF_InData *in_data, PF_OutData *out_data, PF_ParamDef *par
213267

214268
progress_baseL++;
215269

270+
ERR2(PF_CHECKIN_PARAM(in_data, &scanLayer));
271+
272+
progress_baseL++;
273+
216274
return err;
217275
}
218276

InvEqui.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
/* Versioning information */
2828

2929
#define MAJOR_VERSION 1
30-
#define MINOR_VERSION 0
30+
#define MINOR_VERSION 1
3131
#define BUG_VERSION 0
3232
#define STAGE_VERSION PF_Stage_DEVELOP
3333
#define BUILD_VERSION 1
@@ -39,6 +39,7 @@ enum {
3939
INVEQUI_YAW,
4040
INVEQUI_PITCH,
4141
INVEQUI_KEEPLAYER,
42+
INVEQUI_ANTIALIAS,
4243
INVEQUI_NUM_PARAMS
4344
};
4445

@@ -48,6 +49,7 @@ enum {
4849
YAW_PARAM_ID,
4950
PITCH_PARAM_ID,
5051
KEEPLAYER_PARAM_ID,
52+
ANTIALIAS_PARAM_ID,
5153
};
5254

5355

InvEqui_Strings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ TableString g_strs[StrID_NUMTYPES] = {
1616
StrID_Pitch_Param_Name, "Pitch",
1717
StrID_KeepLayer_Param_Name, "Preserve layer",
1818
StrID_KeepLayer_Param_Desc, "Keep",
19+
StrID_Antialias_Param_Name, "Antialias",
20+
StrID_Antialias_Param_Desc, "Use",
1921
};
2022

2123

InvEqui_Strings.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@ typedef enum {
1010
StrID_Pitch_Param_Name,
1111
StrID_KeepLayer_Param_Name,
1212
StrID_KeepLayer_Param_Desc,
13+
StrID_Antialias_Param_Name,
14+
StrID_Antialias_Param_Desc,
1315
StrID_NUMTYPES
1416
} StrIDType;

Math3D.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,22 @@ namespace Math3D {
8787
return Vector3D<T>(x / w, y / w, z / w);
8888
}
8989

90+
template <typename T = float>
91+
T sinc(T x) {
92+
if (x == static_cast<T>(0))
93+
return static_cast<T>(1);
94+
95+
T xi = radians(x * static_cast<T>(180));
96+
97+
return sin(xi) / xi;
98+
}
99+
100+
template <typename T = float>
101+
T lanczos(T x, T a = static_cast<T>(3)) {
102+
if (-a <= x || x < a)
103+
return sinc(x) * sinc(x / a);
104+
105+
return 0;
106+
}
107+
90108
}

Win/InvEqui.vcxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,14 @@
6666
<PropertyGroup Label="UserMacros" />
6767
<PropertyGroup>
6868
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
69-
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
70-
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
69+
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
70+
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
7171
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
7272
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
7373
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
7474
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</IgnoreImportLibrary>
75-
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
76-
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build</OutDir>
75+
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
76+
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">C:\Program Files\Adobe\Adobe After Effects CC 2018\Support Files\Plug-ins\Build\</OutDir>
7777
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
7878
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
7979
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</IgnoreImportLibrary>

0 commit comments

Comments
 (0)