Add catmull rom filter. Also, move the debug asserts for values <= 1 to the very end of the process. This will make these bugs a lot harder to find, but because some filter kernels have negative values it's possible for the buffers to have values > 1 up until the point where it's converted back to an int.
This commit is contained in:
parent
12acf87eec
commit
69af963c42
@ -30,6 +30,7 @@ typedef enum
|
|||||||
STBR_FILTER_NEAREST = 1,
|
STBR_FILTER_NEAREST = 1,
|
||||||
STBR_FILTER_BILINEAR = 2,
|
STBR_FILTER_BILINEAR = 2,
|
||||||
STBR_FILTER_BICUBIC = 3, // A cubic b spline
|
STBR_FILTER_BICUBIC = 3, // A cubic b spline
|
||||||
|
STBR_FILTER_CATMULLROM = 4,
|
||||||
} stbr_filter;
|
} stbr_filter;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -245,11 +246,26 @@ static float stbr__filter_bicubic(float x)
|
|||||||
return (0.0f);
|
return (0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float stbr__filter_catmullrom(float x)
|
||||||
|
{
|
||||||
|
x = (float)fabs(x);
|
||||||
|
|
||||||
|
float xx = x*x;
|
||||||
|
|
||||||
|
if (x < 1.0f)
|
||||||
|
return 1.5f * (x * xx) - 2.5f * xx + 1;
|
||||||
|
else if (x < 2.0f)
|
||||||
|
return -0.5f * (x * xx) + 2.5f * xx - 4 * x + 2;
|
||||||
|
|
||||||
|
return (0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
static stbr__filter_info stbr__filter_info_table[] = {
|
static stbr__filter_info stbr__filter_info_table[] = {
|
||||||
{ NULL, 0.0f },
|
{ NULL, 0.0f },
|
||||||
{ stbr__filter_nearest, 0.5f },
|
{ stbr__filter_nearest, 0.5f },
|
||||||
{ stbr__filter_bilinear, 1.0f },
|
{ stbr__filter_bilinear, 1.0f },
|
||||||
{ stbr__filter_bicubic, 2.0f },
|
{ stbr__filter_bicubic, 2.0f },
|
||||||
|
{ stbr__filter_catmullrom, 2.0f },
|
||||||
};
|
};
|
||||||
|
|
||||||
stbr_inline static int stbr__use_width_upsampling_noinfo(int output_w, int input_w)
|
stbr_inline static int stbr__use_width_upsampling_noinfo(int output_w, int input_w)
|
||||||
@ -515,8 +531,6 @@ static void stbr__output_decode_coefficients_1(float* output_buffer, int out_tex
|
|||||||
STBR_DEBUG_ASSERT(channels == 1);
|
STBR_DEBUG_ASSERT(channels == 1);
|
||||||
|
|
||||||
output_buffer[out_texel_index] += input_buffer[input_texel_index] * coefficient;
|
output_buffer[out_texel_index] += input_buffer[input_texel_index] * coefficient;
|
||||||
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index] <= 1.001f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbr__output_decode_coefficients_2(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
static void stbr__output_decode_coefficients_2(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
||||||
@ -525,9 +539,6 @@ static void stbr__output_decode_coefficients_2(float* output_buffer, int out_tex
|
|||||||
|
|
||||||
output_buffer[out_texel_index ] += input_buffer[input_texel_index ] * coefficient;
|
output_buffer[out_texel_index ] += input_buffer[input_texel_index ] * coefficient;
|
||||||
output_buffer[out_texel_index + 1] += input_buffer[input_texel_index + 1] * coefficient;
|
output_buffer[out_texel_index + 1] += input_buffer[input_texel_index + 1] * coefficient;
|
||||||
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index ] <= 1.001f);
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + 1] <= 1.001f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbr__output_decode_coefficients_3(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
static void stbr__output_decode_coefficients_3(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
||||||
@ -537,10 +548,6 @@ static void stbr__output_decode_coefficients_3(float* output_buffer, int out_tex
|
|||||||
output_buffer[out_texel_index ] += input_buffer[input_texel_index ] * coefficient;
|
output_buffer[out_texel_index ] += input_buffer[input_texel_index ] * coefficient;
|
||||||
output_buffer[out_texel_index + 1] += input_buffer[input_texel_index + 1] * coefficient;
|
output_buffer[out_texel_index + 1] += input_buffer[input_texel_index + 1] * coefficient;
|
||||||
output_buffer[out_texel_index + 2] += input_buffer[input_texel_index + 2] * coefficient;
|
output_buffer[out_texel_index + 2] += input_buffer[input_texel_index + 2] * coefficient;
|
||||||
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index ] <= 1.001f);
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + 1] <= 1.001f);
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + 2] <= 1.001f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbr__output_decode_coefficients_4(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
static void stbr__output_decode_coefficients_4(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
||||||
@ -551,22 +558,13 @@ static void stbr__output_decode_coefficients_4(float* output_buffer, int out_tex
|
|||||||
output_buffer[out_texel_index + 1] += input_buffer[input_texel_index + 1] * coefficient;
|
output_buffer[out_texel_index + 1] += input_buffer[input_texel_index + 1] * coefficient;
|
||||||
output_buffer[out_texel_index + 2] += input_buffer[input_texel_index + 2] * coefficient;
|
output_buffer[out_texel_index + 2] += input_buffer[input_texel_index + 2] * coefficient;
|
||||||
output_buffer[out_texel_index + 3] += input_buffer[input_texel_index + 3] * coefficient;
|
output_buffer[out_texel_index + 3] += input_buffer[input_texel_index + 3] * coefficient;
|
||||||
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index ] <= 1.001f);
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + 1] <= 1.001f);
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + 2] <= 1.001f);
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + 3] <= 1.001f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbr__output_decode_coefficients_n(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
static void stbr__output_decode_coefficients_n(float* output_buffer, int out_texel_index, float* input_buffer, int input_texel_index, int channels, float coefficient)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
for (c = 0; c < channels; c++)
|
for (c = 0; c < channels; c++)
|
||||||
{
|
|
||||||
output_buffer[out_texel_index + c] += input_buffer[input_texel_index + c] * coefficient;
|
output_buffer[out_texel_index + c] += input_buffer[input_texel_index + c] * coefficient;
|
||||||
|
|
||||||
STBR_DEBUG_ASSERT(output_buffer[out_texel_index + c] <= 1.001f);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static stbr__output_decode_coefficients stbr__get_output_decode_coefficients_function(int channels)
|
static stbr__output_decode_coefficients stbr__get_output_decode_coefficients_function(int channels)
|
||||||
@ -751,8 +749,12 @@ static void stbr__resample_vertical_upsample(stbr__info* stbr_info, int n, int i
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (c = 0; c < channels; c++)
|
for (c = 0; c < channels; c++)
|
||||||
|
{
|
||||||
|
STBR_DEBUG_ASSERT(encode_buffer[c] < 1.0f + 1.0f/255);
|
||||||
|
|
||||||
((unsigned char*)output_data)[out_texel_index + c] = (unsigned char)(encode_buffer[c] * 255);
|
((unsigned char*)output_data)[out_texel_index + c] = (unsigned char)(encode_buffer[c] * 255);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stbr__resample_vertical_downsample(stbr__info* stbr_info, int n, int in_first_scanline, int in_last_scanline, float in_center_of_out)
|
static void stbr__resample_vertical_downsample(stbr__info* stbr_info, int n, int in_first_scanline, int in_last_scanline, float in_center_of_out)
|
||||||
@ -885,9 +887,13 @@ static void stbr__empty_ring_buffer(stbr__info* stbr_info, int first_necessary_s
|
|||||||
int ring_texel_index = texel_index;
|
int ring_texel_index = texel_index;
|
||||||
int output_texel_index = output_row + texel_index;
|
int output_texel_index = output_row + texel_index;
|
||||||
for (c = 0; c < channels; c++)
|
for (c = 0; c < channels; c++)
|
||||||
|
{
|
||||||
|
STBR_DEBUG_ASSERT(ring_buffer_entry[ring_texel_index + c] < 1.0f + 1.0f / 255);
|
||||||
|
|
||||||
((unsigned char*)output_data)[output_texel_index + c] = (unsigned char)(ring_buffer_entry[ring_texel_index + c] * 255);
|
((unsigned char*)output_data)[output_texel_index + c] = (unsigned char)(ring_buffer_entry[ring_texel_index + c] * 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stbr_info->ring_buffer_first_scanline == stbr_info->ring_buffer_last_scanline)
|
if (stbr_info->ring_buffer_first_scanline == stbr_info->ring_buffer_last_scanline)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user