Floating point rounding causes stbir__calculate_sample_range_upsample to sometimes think it needs one more scanline than it really does. This patch adds one extra entry to the ringbuffer to avoid the problem.
This commit is contained in:
parent
59a5a155b4
commit
638267b6d5
@ -533,10 +533,11 @@ typedef struct
|
||||
int horizontal_num_contributors;
|
||||
int vertical_num_contributors;
|
||||
|
||||
int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)
|
||||
int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)
|
||||
int ring_buffer_num_entries; // Total number of entries in the ring buffer.
|
||||
int ring_buffer_first_scanline;
|
||||
int ring_buffer_last_scanline;
|
||||
int ring_buffer_begin_index;
|
||||
int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer
|
||||
float* ring_buffer;
|
||||
|
||||
float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds.
|
||||
@ -1411,6 +1412,8 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)
|
||||
int ring_buffer_index;
|
||||
float* ring_buffer;
|
||||
|
||||
stbir_info->ring_buffer_last_scanline = n;
|
||||
|
||||
if (stbir_info->ring_buffer_begin_index < 0)
|
||||
{
|
||||
ring_buffer_index = stbir_info->ring_buffer_begin_index = 0;
|
||||
@ -1418,15 +1421,13 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)
|
||||
}
|
||||
else
|
||||
{
|
||||
ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width;
|
||||
ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;
|
||||
STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
|
||||
}
|
||||
|
||||
ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float));
|
||||
memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes);
|
||||
|
||||
stbir_info->ring_buffer_last_scanline = n;
|
||||
|
||||
return ring_buffer;
|
||||
}
|
||||
|
||||
@ -1678,9 +1679,9 @@ static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n
|
||||
}
|
||||
|
||||
// Get the specified scan line from the ring buffer.
|
||||
static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_size, int ring_buffer_length)
|
||||
static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length)
|
||||
{
|
||||
int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_size;
|
||||
int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries;
|
||||
return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length);
|
||||
}
|
||||
|
||||
@ -1865,7 +1866,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
||||
int alpha_channel = stbir_info->alpha_channel;
|
||||
int type = stbir_info->type;
|
||||
int colorspace = stbir_info->colorspace;
|
||||
int kernel_pixel_width = stbir_info->vertical_filter_pixel_width;
|
||||
int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
|
||||
void* output_data = stbir_info->output_data;
|
||||
float* encode_buffer = stbir_info->encode_buffer;
|
||||
int decode = STBIR__DECODE(type, colorspace);
|
||||
@ -1900,7 +1901,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
||||
for (k = n0; k <= n1; k++)
|
||||
{
|
||||
int coefficient_index = coefficient_counter++;
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
|
||||
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
||||
for (x = 0; x < output_w; ++x)
|
||||
{
|
||||
@ -1913,7 +1914,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
||||
for (k = n0; k <= n1; k++)
|
||||
{
|
||||
int coefficient_index = coefficient_counter++;
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
|
||||
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
||||
for (x = 0; x < output_w; ++x)
|
||||
{
|
||||
@ -1927,7 +1928,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
||||
for (k = n0; k <= n1; k++)
|
||||
{
|
||||
int coefficient_index = coefficient_counter++;
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
|
||||
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
||||
for (x = 0; x < output_w; ++x)
|
||||
{
|
||||
@ -1942,7 +1943,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
||||
for (k = n0; k <= n1; k++)
|
||||
{
|
||||
int coefficient_index = coefficient_counter++;
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
|
||||
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
||||
for (x = 0; x < output_w; ++x)
|
||||
{
|
||||
@ -1958,7 +1959,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
||||
for (k = n0; k <= n1; k++)
|
||||
{
|
||||
int coefficient_index = coefficient_counter++;
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
|
||||
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
||||
for (x = 0; x < output_w; ++x)
|
||||
{
|
||||
@ -1981,7 +1982,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n,
|
||||
stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
|
||||
float* vertical_coefficients = stbir_info->vertical_coefficients;
|
||||
int channels = stbir_info->channels;
|
||||
int kernel_pixel_width = stbir_info->vertical_filter_pixel_width;
|
||||
int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
|
||||
void* output_data = stbir_info->output_data;
|
||||
float* horizontal_buffer = stbir_info->horizontal_buffer;
|
||||
int coefficient_width = stbir_info->vertical_coefficient_width;
|
||||
@ -2005,7 +2006,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n,
|
||||
int coefficient_group = coefficient_width * contributor;
|
||||
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
||||
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
||||
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
|
||||
|
||||
switch (channels) {
|
||||
case 1:
|
||||
@ -2071,7 +2072,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
|
||||
|
||||
stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);
|
||||
|
||||
STBIR_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width);
|
||||
STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
|
||||
|
||||
if (stbir_info->ring_buffer_begin_index >= 0)
|
||||
{
|
||||
@ -2090,7 +2091,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
|
||||
else
|
||||
{
|
||||
stbir_info->ring_buffer_first_scanline++;
|
||||
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width;
|
||||
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2148,7 +2149,7 @@ static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessar
|
||||
else
|
||||
{
|
||||
stbir_info->ring_buffer_first_scanline++;
|
||||
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width;
|
||||
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2172,7 +2173,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
|
||||
|
||||
stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);
|
||||
|
||||
STBIR_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width);
|
||||
STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
|
||||
|
||||
if (out_last_scanline < 0 || out_first_scanline >= output_h)
|
||||
continue;
|
||||
@ -2246,13 +2247,16 @@ static stbir_uint32 stbir__calculate_memory(stbir__info *info)
|
||||
info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);
|
||||
info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h);
|
||||
|
||||
// One extra entry because floating point precision problems sometimes cause an extra to be necessary.
|
||||
info->ring_buffer_num_entries = filter_height + 1;
|
||||
|
||||
info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors);
|
||||
info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float);
|
||||
info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors);
|
||||
info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float);
|
||||
info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float);
|
||||
info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float);
|
||||
info->ring_buffer_size = info->output_w * info->channels * filter_height * sizeof(float);
|
||||
info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float);
|
||||
info->encode_buffer_size = info->output_w * info->channels * sizeof(float);
|
||||
|
||||
STBIR_ASSERT(info->horizontal_filter != 0);
|
||||
|
Loading…
Reference in New Issue
Block a user