VSE: add Cubic Mitchell filtering, rename previous cubic to Cubic BSpline #117517
|
@ -203,6 +203,27 @@ void interpolate_bilinear_wrap_fl(const float *buffer,
|
|||
void interpolate_cubic_bspline_fl(
|
||||
const float *buffer, float *output, int width, int height, int components, float u, float v);
|
||||
|
||||
/**
|
||||
* Cubic Mitchell sampling.
|
||||
*
|
||||
* Takes 4x4 image samples at floor(u,v)-1 .. floor(u,v)+2, and blends them
|
||||
* based on fractional parts of u,v. Uses Mitchell-Netravali filter (B=C=1/3),
|
||||
* which has a good compromise between blur and ringing.
|
||||
* Samples outside the image are clamped to texels at image edge.
|
||||
*
|
||||
* Note that you probably want to subtract 0.5 from u,v before this function,
|
||||
* to get proper filtering.
|
||||
*/
|
||||
|
||||
[[nodiscard]] uchar4 interpolate_cubic_mitchell_byte(
|
||||
const uchar *buffer, int width, int height, float u, float v);
|
||||
|
||||
[[nodiscard]] float4 interpolate_cubic_mitchell_fl(
|
||||
const float *buffer, int width, int height, float u, float v);
|
||||
|
||||
void interpolate_cubic_mitchell_fl(
|
||||
const float *buffer, float *output, int width, int height, int components, float u, float v);
|
||||
|
||||
} // namespace blender::math
|
||||
|
||||
#define EWA_MAXIDX 255
|
||||
|
|
|
@ -10,24 +10,41 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_base.hh"
|
||||
#include "BLI_math_interp.hh"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_simd.h"
|
||||
#include "BLI_strict_flags.h"
|
||||
|
||||
/* Cubic B-Spline coefficients. f is offset from texel center in pixel space.
|
||||
* This is Mitchell-Netravali filter with B=1, C=0 parameters. */
|
||||
static blender::float4 cubic_bspline_coefficients(float f)
|
||||
enum class eCubicFilter {
|
||||
BSpline,
|
||||
Mitchell,
|
||||
};
|
||||
|
||||
/* Calculate cubic filter coefficients, for samples at -1,0,+1,+2.
|
||||
* f is 0..1 offset from texel center in pixel space. */
|
||||
template<enum eCubicFilter filter> static blender::float4 cubic_filter_coefficients(float f)
|
||||
{
|
||||
float f2 = f * f;
|
||||
float f3 = f2 * f;
|
||||
|
||||
float w3 = f3 / 6.0f;
|
||||
float w0 = -w3 + f2 * 0.5f - f * 0.5f + 1.0f / 6.0f;
|
||||
float w1 = f3 * 0.5f - f2 * 1.0f + 2.0f / 3.0f;
|
||||
float w2 = 1.0f - w0 - w1 - w3;
|
||||
return blender::float4(w0, w1, w2, w3);
|
||||
if constexpr (filter == eCubicFilter::BSpline) {
|
||||
/* Cubic B-Spline (Mitchell-Netravali filter with B=1, C=0 parameters). */
|
||||
float w3 = f3 * (1.0f / 6.0f);
|
||||
float w0 = -w3 + f2 * 0.5f - f * 0.5f + 1.0f / 6.0f;
|
||||
float w1 = f3 * 0.5f - f2 * 1.0f + 2.0f / 3.0f;
|
||||
float w2 = 1.0f - w0 - w1 - w3;
|
||||
return blender::float4(w0, w1, w2, w3);
|
||||
}
|
||||
else if constexpr (filter == eCubicFilter::Mitchell) {
|
||||
/* Cubic Mitchell-Netravali filter with B=1/3, C=1/3 parameters. */
|
||||
float w0 = -7.0f / 18.0f * f3 + 5.0f / 6.0f * f2 - 0.5f * f + 1.0f / 18.0f;
|
||||
float w1 = 7.0f / 6.0f * f3 - 2.0f * f2 + 8.0f / 9.0f;
|
||||
float w2 = -7.0f / 6.0f * f3 + 3.0f / 2.0f * f2 + 0.5f * f + 1.0f / 18.0f;
|
||||
float w3 = 7.0f / 18.0f * f3 - 1.0f / 3.0f * f2;
|
||||
return blender::float4(w0, w1, w2, w3);
|
||||
}
|
||||
}
|
||||
|
||||
#if BLI_HAVE_SSE2
|
||||
|
@ -51,6 +68,7 @@ BLI_INLINE __m128 floor_simd(__m128 v)
|
|||
return v_floor;
|
||||
}
|
||||
|
||||
template<eCubicFilter filter>
|
||||
BLI_INLINE void bicubic_interpolation_uchar_simd(
|
||||
const uchar *src_buffer, uchar *output, int width, int height, float u, float v)
|
||||
{
|
||||
|
@ -72,8 +90,8 @@ BLI_INLINE void bicubic_interpolation_uchar_simd(
|
|||
__m128 frac_uv = _mm_sub_ps(uv, uv_floor);
|
||||
|
||||
/* Calculate pixel weights. */
|
||||
blender::float4 wx = cubic_bspline_coefficients(_mm_cvtss_f32(frac_uv));
|
||||
blender::float4 wy = cubic_bspline_coefficients(
|
||||
blender::float4 wx = cubic_filter_coefficients<filter>(_mm_cvtss_f32(frac_uv));
|
||||
blender::float4 wy = cubic_filter_coefficients<filter>(
|
||||
_mm_cvtss_f32(_mm_shuffle_ps(frac_uv, frac_uv, 1)));
|
||||
|
||||
/* Read 4x4 source pixels and blend them. */
|
||||
|
@ -102,7 +120,8 @@ BLI_INLINE void bicubic_interpolation_uchar_simd(
|
|||
}
|
||||
|
||||
/* Pack and write to destination: pack to 16 bit signed, then to 8 bit
|
||||
* unsigned, then write resulting 32-bit value. */
|
||||
* unsigned, then write resulting 32-bit value. This will clamp
|
||||
* out of range values too. */
|
||||
out = _mm_add_ps(out, _mm_set1_ps(0.5f));
|
||||
__m128i rgba32 = _mm_cvttps_epi32(out);
|
||||
__m128i rgba16 = _mm_packs_epi32(rgba32, _mm_setzero_si128());
|
||||
|
@ -111,7 +130,7 @@ BLI_INLINE void bicubic_interpolation_uchar_simd(
|
|||
}
|
||||
#endif /* BLI_HAVE_SSE2 */
|
||||
|
||||
template<typename T>
|
||||
template<typename T, eCubicFilter filter>
|
||||
static void bicubic_interpolation(
|
||||
const T *src_buffer, T *output, int width, int height, int components, float u, float v)
|
||||
{
|
||||
|
@ -122,7 +141,7 @@ static void bicubic_interpolation(
|
|||
#if BLI_HAVE_SSE2
|
||||
if constexpr (std::is_same_v<T, uchar>) {
|
||||
if (components == 4) {
|
||||
bicubic_interpolation_uchar_simd(src_buffer, output, width, height, u, v);
|
||||
bicubic_interpolation_uchar_simd<filter>(src_buffer, output, width, height, u, v);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -143,8 +162,8 @@ static void bicubic_interpolation(
|
|||
float4 out{0.0f};
|
||||
|
||||
/* Calculate pixel weights. */
|
||||
float4 wx = cubic_bspline_coefficients(frac_u);
|
||||
float4 wy = cubic_bspline_coefficients(frac_v);
|
||||
float4 wx = cubic_filter_coefficients<filter>(frac_u);
|
||||
float4 wy = cubic_filter_coefficients<filter>(frac_v);
|
||||
|
||||
/* Read 4x4 source pixels and blend them. */
|
||||
for (int n = 0; n < 4; n++) {
|
||||
|
@ -175,6 +194,16 @@ static void bicubic_interpolation(
|
|||
}
|
||||
}
|
||||
|
||||
/* Mitchell filter has negative lobes; prevent output from going out of range. */
|
||||
if constexpr (filter == eCubicFilter::Mitchell) {
|
||||
for (int i = 0; i < components; i++) {
|
||||
out[i] = math::max(out[i], 0.0f);
|
||||
if constexpr (std::is_same_v<T, uchar>) {
|
||||
out[i] = math::min(out[i], 255.0f);
|
||||
aras_p marked this conversation as resolved
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write result. */
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
if (components == 1) {
|
||||
|
@ -551,21 +580,44 @@ float4 interpolate_bilinear_wrap_fl(const float *buffer, int width, int height,
|
|||
uchar4 interpolate_cubic_bspline_byte(const uchar *buffer, int width, int height, float u, float v)
|
||||
{
|
||||
uchar4 res;
|
||||
bicubic_interpolation<uchar>(buffer, res, width, height, 4, u, v);
|
||||
bicubic_interpolation<uchar, eCubicFilter::BSpline>(buffer, res, width, height, 4, u, v);
|
||||
return res;
|
||||
}
|
||||
|
||||
float4 interpolate_cubic_bspline_fl(const float *buffer, int width, int height, float u, float v)
|
||||
{
|
||||
float4 res;
|
||||
bicubic_interpolation<float>(buffer, res, width, height, 4, u, v);
|
||||
bicubic_interpolation<float, eCubicFilter::BSpline>(buffer, res, width, height, 4, u, v);
|
||||
return res;
|
||||
}
|
||||
|
||||
void interpolate_cubic_bspline_fl(
|
||||
const float *buffer, float *output, int width, int height, int components, float u, float v)
|
||||
{
|
||||
bicubic_interpolation<float>(buffer, output, width, height, components, u, v);
|
||||
bicubic_interpolation<float, eCubicFilter::BSpline>(
|
||||
buffer, output, width, height, components, u, v);
|
||||
}
|
||||
|
||||
uchar4 interpolate_cubic_mitchell_byte(
|
||||
const uchar *buffer, int width, int height, float u, float v)
|
||||
{
|
||||
uchar4 res;
|
||||
bicubic_interpolation<uchar, eCubicFilter::Mitchell>(buffer, res, width, height, 4, u, v);
|
||||
return res;
|
||||
}
|
||||
|
||||
float4 interpolate_cubic_mitchell_fl(const float *buffer, int width, int height, float u, float v)
|
||||
{
|
||||
float4 res;
|
||||
bicubic_interpolation<float, eCubicFilter::Mitchell>(buffer, res, width, height, 4, u, v);
|
||||
return res;
|
||||
}
|
||||
|
||||
void interpolate_cubic_mitchell_fl(
|
||||
const float *buffer, float *output, int width, int height, int components, float u, float v)
|
||||
{
|
||||
bicubic_interpolation<float, eCubicFilter::Mitchell>(
|
||||
buffer, output, width, height, components, u, v);
|
||||
}
|
||||
|
||||
} // namespace blender::math
|
||||
|
|
|
@ -256,3 +256,65 @@ TEST(math_interp, CubicBSplineCharFullyOutsideImage)
|
|||
res = interpolate_cubic_bspline_byte(image_char[0][0], image_width, image_height, 0, 500.0f);
|
||||
EXPECT_EQ(exp, res);
|
||||
}
|
||||
|
||||
TEST(math_interp, CubicMitchellCharExactSamples)
|
||||
{
|
||||
uchar4 res;
|
||||
uchar4 exp1 = {72, 101, 140, 223};
|
||||
res = interpolate_cubic_mitchell_byte(image_char[0][0], image_width, image_height, 1.0f, 2.0f);
|
||||
EXPECT_EQ(int4(exp1), int4(res));
|
||||
uchar4 exp2 = {233, 162, 99, 37};
|
||||
res = interpolate_cubic_mitchell_byte(image_char[0][0], image_width, image_height, 2.0f, 0.0f);
|
||||
EXPECT_EQ(int4(exp2), int4(res));
|
||||
}
|
||||
|
||||
TEST(math_interp, CubicMitchellCharSamples)
|
||||
{
|
||||
uchar4 res;
|
||||
uchar4 exp1 = {135, 132, 130, 127};
|
||||
res = interpolate_cubic_mitchell_byte(
|
||||
image_char[0][0], image_width, image_height, 1.25f, 0.625f);
|
||||
EXPECT_EQ(int4(exp1), int4(res));
|
||||
uchar4 exp2 = {216, 189, 167, 143};
|
||||
res = interpolate_cubic_mitchell_byte(image_char[0][0], image_width, image_height, 1.4f, 0.1f);
|
||||
EXPECT_EQ(int4(exp2), int4(res));
|
||||
}
|
||||
|
||||
TEST(math_interp, CubicMitchellFloatSamples)
|
||||
{
|
||||
float4 res;
|
||||
float4 exp1 = {134.5659f, 131.91309f, 130.17685f, 126.66989f};
|
||||
res = interpolate_cubic_mitchell_fl(image_fl[0][0], image_width, image_height, 1.25f, 0.625f);
|
||||
EXPECT_V4_NEAR(exp1, res, float_tolerance);
|
||||
float4 exp2 = {216.27115f, 189.30673f, 166.93599f, 143.31964f};
|
||||
res = interpolate_cubic_mitchell_fl(image_fl[0][0], image_width, image_height, 1.4f, 0.1f);
|
||||
EXPECT_V4_NEAR(exp2, res, float_tolerance);
|
||||
}
|
||||
|
||||
TEST(math_interp, CubicMitchellCharPartiallyOutsideImage)
|
||||
{
|
||||
uchar4 res;
|
||||
uchar4 exp1 = {0, 0, 0, 0};
|
||||
res = interpolate_cubic_mitchell_byte(image_char[0][0], image_width, image_height, -0.5f, 2.0f);
|
||||
EXPECT_EQ(int4(exp1), int4(res));
|
||||
uchar4 exp2 = {88, 116, 151, 228};
|
||||
res = interpolate_cubic_mitchell_byte(image_char[0][0], image_width, image_height, 1.25f, 2.9f);
|
||||
EXPECT_EQ(int4(exp2), int4(res));
|
||||
uchar4 exp3 = {239, 159, 89, 19};
|
||||
res = interpolate_cubic_mitchell_byte(image_char[0][0], image_width, image_height, 2.2f, -0.1f);
|
||||
EXPECT_EQ(int4(exp3), int4(res));
|
||||
}
|
||||
|
||||
TEST(math_interp, CubicMitchellFloatPartiallyOutsideImage)
|
||||
{
|
||||
float4 res;
|
||||
float4 exp1 = {0, 0, 0, 0};
|
||||
res = interpolate_cubic_mitchell_fl(image_fl[0][0], image_width, image_height, -0.5f, 2.0f);
|
||||
EXPECT_V4_NEAR(exp1, res, float_tolerance);
|
||||
float4 exp2 = {87.98676f, 115.63634f, 151.13014f, 228.19823f};
|
||||
res = interpolate_cubic_mitchell_fl(image_fl[0][0], image_width, image_height, 1.25f, 2.9f);
|
||||
EXPECT_V4_NEAR(exp2, res, float_tolerance);
|
||||
float4 exp3 = {238.6136f, 158.58293f, 88.55761f, 18.53225f};
|
||||
res = interpolate_cubic_mitchell_fl(image_fl[0][0], image_width, image_height, 2.2f, -0.1f);
|
||||
EXPECT_V4_NEAR(exp3, res, float_tolerance);
|
||||
}
|
||||
|
|
|
@ -264,7 +264,8 @@ void IMB_rectblend_threaded(ImBuf *dbuf,
|
|||
enum eIMBInterpolationFilterMode {
|
||||
IMB_FILTER_NEAREST,
|
||||
IMB_FILTER_BILINEAR,
|
||||
IMB_FILTER_BICUBIC,
|
||||
IMB_FILTER_CUBIC_BSPLINE,
|
||||
IMB_FILTER_CUBIC_MITCHELL,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -91,6 +91,16 @@ inline void interpolate_cubic_bspline_fl(const ImBuf *in, float output[4], float
|
|||
memcpy(output, &col, sizeof(col));
|
||||
}
|
||||
|
||||
[[nodiscard]] inline uchar4 interpolate_cubic_mitchell_byte(const ImBuf *in, float u, float v)
|
||||
{
|
||||
return math::interpolate_cubic_mitchell_byte(in->byte_buffer.data, in->x, in->y, u, v);
|
||||
}
|
||||
inline void interpolate_cubic_mitchell_byte(const ImBuf *in, uchar output[4], float u, float v)
|
||||
{
|
||||
uchar4 col = math::interpolate_cubic_mitchell_byte(in->byte_buffer.data, in->x, in->y, u, v);
|
||||
memcpy(output, &col, sizeof(col));
|
||||
}
|
||||
|
||||
} // namespace blender::imbuf
|
||||
|
||||
/**
|
||||
|
|
|
@ -146,10 +146,10 @@ static void sample_image(const ImBuf *source, float u, float v, T *r_sample)
|
|||
u = wrap_uv(u, source->x);
|
||||
v = wrap_uv(v, source->y);
|
||||
}
|
||||
/* BLI_bilinear_interpolation functions use `floor(uv)` and `floor(uv)+1`
|
||||
/* Bilinear/cubic interpolation functions use `floor(uv)` and `floor(uv)+1`
|
||||
* texels. For proper mapping between pixel and texel spaces, need to
|
||||
* subtract 0.5. Same for bicubic. */
|
||||
if constexpr (ELEM(Filter, IMB_FILTER_BILINEAR, IMB_FILTER_BICUBIC)) {
|
||||
* subtract 0.5. */
|
||||
if constexpr (Filter != IMB_FILTER_NEAREST) {
|
||||
u -= 0.5f;
|
||||
v -= 0.5f;
|
||||
}
|
||||
|
@ -185,14 +185,24 @@ static void sample_image(const ImBuf *source, float u, float v, T *r_sample)
|
|||
math::interpolate_nearest_fl(
|
||||
source->float_buffer.data, r_sample, source->x, source->y, NumChannels, u, v);
|
||||
}
|
||||
else if constexpr (Filter == IMB_FILTER_BICUBIC && std::is_same_v<T, float>) {
|
||||
else if constexpr (Filter == IMB_FILTER_CUBIC_BSPLINE && std::is_same_v<T, float>) {
|
||||
math::interpolate_cubic_bspline_fl(
|
||||
source->float_buffer.data, r_sample, source->x, source->y, NumChannels, u, v);
|
||||
}
|
||||
else if constexpr (Filter == IMB_FILTER_BICUBIC && std::is_same_v<T, uchar> && NumChannels == 4)
|
||||
else if constexpr (Filter == IMB_FILTER_CUBIC_BSPLINE && std::is_same_v<T, uchar> &&
|
||||
NumChannels == 4)
|
||||
{
|
||||
interpolate_cubic_bspline_byte(source, r_sample, u, v);
|
||||
}
|
||||
else if constexpr (Filter == IMB_FILTER_CUBIC_MITCHELL && std::is_same_v<T, float>) {
|
||||
math::interpolate_cubic_mitchell_fl(
|
||||
source->float_buffer.data, r_sample, source->x, source->y, NumChannels, u, v);
|
||||
}
|
||||
else if constexpr (Filter == IMB_FILTER_CUBIC_MITCHELL && std::is_same_v<T, uchar> &&
|
||||
NumChannels == 4)
|
||||
{
|
||||
interpolate_cubic_mitchell_byte(source, r_sample, u, v);
|
||||
}
|
||||
else {
|
||||
/* Unsupported sampler. */
|
||||
BLI_assert_unreachable();
|
||||
|
@ -385,8 +395,11 @@ void IMB_transform(const ImBuf *src,
|
|||
else if (filter == IMB_FILTER_BILINEAR) {
|
||||
transform_scanlines_filter<IMB_FILTER_BILINEAR>(ctx, y_range);
|
||||
}
|
||||
else if (filter == IMB_FILTER_BICUBIC) {
|
||||
transform_scanlines_filter<IMB_FILTER_BICUBIC>(ctx, y_range);
|
||||
else if (filter == IMB_FILTER_CUBIC_BSPLINE) {
|
||||
Sergey Sharybin
commented
This should probably become a This should probably become a `switch` statement.
|
||||
transform_scanlines_filter<IMB_FILTER_CUBIC_BSPLINE>(ctx, y_range);
|
||||
}
|
||||
else if (filter == IMB_FILTER_CUBIC_MITCHELL) {
|
||||
transform_scanlines_filter<IMB_FILTER_CUBIC_MITCHELL>(ctx, y_range);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -87,9 +87,9 @@ TEST(imbuf_transform, bilinear_2x_smaller)
|
|||
IMB_freeImBuf(res);
|
||||
}
|
||||
|
||||
TEST(imbuf_transform, bicubic_2x_smaller)
|
||||
TEST(imbuf_transform, cubic_bspline_2x_smaller)
|
||||
{
|
||||
ImBuf *res = transform_2x_smaller(IMB_FILTER_BICUBIC, 1);
|
||||
ImBuf *res = transform_2x_smaller(IMB_FILTER_CUBIC_BSPLINE, 1);
|
||||
const ColorTheme4b *got = reinterpret_cast<ColorTheme4b *>(res->byte_buffer.data);
|
||||
EXPECT_EQ(got[0], ColorTheme4b(189, 126, 62, 250));
|
||||
EXPECT_EQ(got[1], ColorTheme4b(134, 57, 33, 26));
|
||||
|
@ -97,16 +97,26 @@ TEST(imbuf_transform, bicubic_2x_smaller)
|
|||
IMB_freeImBuf(res);
|
||||
}
|
||||
|
||||
TEST(imbuf_transform, bicubic_fractional_larger)
|
||||
TEST(imbuf_transform, cubic_mitchell_2x_smaller)
|
||||
{
|
||||
ImBuf *res = transform_fractional_larger(IMB_FILTER_BICUBIC, 1);
|
||||
ImBuf *res = transform_2x_smaller(IMB_FILTER_CUBIC_MITCHELL, 1);
|
||||
const ColorTheme4b *got = reinterpret_cast<ColorTheme4b *>(res->byte_buffer.data);
|
||||
EXPECT_EQ(got[0 + 0 * res->x], ColorTheme4b(35, 11, 1, 255));
|
||||
EXPECT_EQ(got[1 + 0 * res->x], ColorTheme4b(131, 12, 6, 250));
|
||||
EXPECT_EQ(got[7 + 0 * res->x], ColorTheme4b(54, 93, 19, 249));
|
||||
EXPECT_EQ(got[2 + 2 * res->x], ColorTheme4b(206, 70, 56, 192));
|
||||
EXPECT_EQ(got[3 + 2 * res->x], ColorTheme4b(165, 60, 42, 78));
|
||||
EXPECT_EQ(got[8 + 6 * res->x], ColorTheme4b(57, 1, 90, 252));
|
||||
EXPECT_EQ(got[0], ColorTheme4b(195, 130, 67, 255));
|
||||
EXPECT_EQ(got[1], ColorTheme4b(132, 51, 28, 0));
|
||||
EXPECT_EQ(got[2], ColorTheme4b(52, 52, 48, 255));
|
||||
IMB_freeImBuf(res);
|
||||
}
|
||||
|
||||
TEST(imbuf_transform, cubic_mitchell_fractional_larger)
|
||||
{
|
||||
ImBuf *res = transform_fractional_larger(IMB_FILTER_CUBIC_MITCHELL, 1);
|
||||
const ColorTheme4b *got = reinterpret_cast<ColorTheme4b *>(res->byte_buffer.data);
|
||||
EXPECT_EQ(got[0 + 0 * res->x], ColorTheme4b(0, 0, 0, 255));
|
||||
EXPECT_EQ(got[1 + 0 * res->x], ColorTheme4b(127, 0, 0, 255));
|
||||
EXPECT_EQ(got[7 + 0 * res->x], ColorTheme4b(49, 109, 13, 255));
|
||||
EXPECT_EQ(got[2 + 2 * res->x], ColorTheme4b(236, 53, 50, 215));
|
||||
EXPECT_EQ(got[3 + 2 * res->x], ColorTheme4b(155, 55, 35, 54));
|
||||
EXPECT_EQ(got[8 + 6 * res->x], ColorTheme4b(57, 0, 98, 252));
|
||||
IMB_freeImBuf(res);
|
||||
}
|
||||
|
||||
|
|
|
@ -839,7 +839,8 @@ enum {
|
|||
SEQ_TRANSFORM_FILTER_NEAREST = 0,
|
||||
SEQ_TRANSFORM_FILTER_BILINEAR = 1,
|
||||
SEQ_TRANSFORM_FILTER_NEAREST_3x3 = 2,
|
||||
SEQ_TRANSFORM_FILTER_BICUBIC = 3,
|
||||
SEQ_TRANSFORM_FILTER_CUBIC_BSPLINE = 3,
|
||||
SEQ_TRANSFORM_FILTER_CUBIC_MITCHELL = 4,
|
||||
};
|
||||
|
||||
typedef enum eSeqChannelFlag {
|
||||
|
|
|
@ -1709,14 +1709,28 @@ static void rna_def_strip_crop(BlenderRNA *brna)
|
|||
}
|
||||
|
||||
static const EnumPropertyItem transform_filter_items[] = {
|
||||
{SEQ_TRANSFORM_FILTER_NEAREST, "NEAREST", 0, "Nearest", ""},
|
||||
{SEQ_TRANSFORM_FILTER_BILINEAR, "BILINEAR", 0, "Bilinear", ""},
|
||||
{SEQ_TRANSFORM_FILTER_BICUBIC, "BICUBIC", 0, "Bicubic", ""},
|
||||
{SEQ_TRANSFORM_FILTER_NEAREST, "NEAREST", 0, "Nearest", "Use nearest sample"},
|
||||
{SEQ_TRANSFORM_FILTER_BILINEAR,
|
||||
"BILINEAR",
|
||||
0,
|
||||
"Bilinear",
|
||||
"Interpolate between 2" BLI_STR_UTF8_MULTIPLICATION_SIGN "2 samples"},
|
||||
{SEQ_TRANSFORM_FILTER_CUBIC_MITCHELL,
|
||||
"CUBIC_MITCHELL",
|
||||
0,
|
||||
"Cubic Mitchell",
|
||||
"Cubic Mitchell filter on 4" BLI_STR_UTF8_MULTIPLICATION_SIGN "4 samples"},
|
||||
{SEQ_TRANSFORM_FILTER_CUBIC_BSPLINE,
|
||||
"CUBIC_BSPLINE",
|
||||
0,
|
||||
"Cubic B-Spline",
|
||||
"Cubic B-Spline filter (blurry but no ringing) on 4" BLI_STR_UTF8_MULTIPLICATION_SIGN
|
||||
"4 samples"},
|
||||
{SEQ_TRANSFORM_FILTER_NEAREST_3x3,
|
||||
"SUBSAMPLING_3x3",
|
||||
0,
|
||||
"Subsampling (3" BLI_STR_UTF8_MULTIPLICATION_SIGN "3)",
|
||||
"Use nearest with 3" BLI_STR_UTF8_MULTIPLICATION_SIGN "3 subsamples during rendering"},
|
||||
"Use nearest with 3" BLI_STR_UTF8_MULTIPLICATION_SIGN "3 subsamples"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
|
|
|
@ -545,8 +545,11 @@ static void sequencer_preprocess_transform_crop(
|
|||
case SEQ_TRANSFORM_FILTER_BILINEAR:
|
||||
filter = IMB_FILTER_BILINEAR;
|
||||
break;
|
||||
case SEQ_TRANSFORM_FILTER_BICUBIC:
|
||||
filter = IMB_FILTER_BICUBIC;
|
||||
case SEQ_TRANSFORM_FILTER_CUBIC_BSPLINE:
|
||||
filter = IMB_FILTER_CUBIC_BSPLINE;
|
||||
break;
|
||||
case SEQ_TRANSFORM_FILTER_CUBIC_MITCHELL:
|
||||
filter = IMB_FILTER_CUBIC_MITCHELL;
|
||||
break;
|
||||
case SEQ_TRANSFORM_FILTER_NEAREST_3x3:
|
||||
filter = IMB_FILTER_NEAREST;
|
||||
|
|
Loading…
Reference in New Issue
Not very obvious why negative lobe could lead to values above 255.