diff --git a/stb_resample.h b/stb_resample.h index c89c254..a563210 100644 --- a/stb_resample.h +++ b/stb_resample.h @@ -408,19 +408,22 @@ stbr_inline static int stbr__use_height_upsampling(stbr__info* stbr_info) // This is the maximum number of input samples that can affect an output sample // with the given filter -stbr_inline static int stbr__get_filter_texel_width(stbr_filter filter) +stbr_inline static int stbr__get_filter_texel_width(stbr_filter filter, int input_w, int output_w) { STBR_ASSERT(filter != 0); STBR_ASSERT(filter < STBR_ARRAY_SIZE(stbr__filter_info_table)); - return (int)ceil(stbr__filter_info_table[filter].support * 2); + if (stbr__use_height_upsampling_noinfo(output_w, input_w)) + return (int)ceil(stbr__filter_info_table[filter].support * 2); + else + return (int)ceil(stbr__filter_info_table[filter].support * 2 * input_w / output_w); } // This is how much to expand buffers to account for filters seeking outside // the image boundaries. -stbr_inline static int stbr__get_filter_texel_margin(stbr_filter filter) +stbr_inline static int stbr__get_filter_texel_margin(stbr_filter filter, int input_w, int output_w) { - return stbr__get_filter_texel_width(filter) / 2; + return stbr__get_filter_texel_width(filter, input_w, output_w) / 2; } stbr_inline static int stbr__get_horizontal_contributors(stbr_filter filter, int input_w, int output_w) @@ -428,12 +431,12 @@ stbr_inline static int stbr__get_horizontal_contributors(stbr_filter filter, int if (stbr__use_width_upsampling_noinfo(output_w, input_w)) return output_w; else - return (input_w + stbr__get_filter_texel_margin(filter) * 2); + return (input_w + stbr__get_filter_texel_margin(filter, input_w, output_w) * 2); } stbr_inline static int stbr__get_total_coefficients(stbr_filter filter, int input_w, int output_w) { - return stbr__get_horizontal_contributors(filter, input_w, output_w) * stbr__get_filter_texel_width(filter); + return stbr__get_horizontal_contributors(filter, input_w, output_w) * stbr__get_filter_texel_width(filter, input_w, output_w); } stbr_inline static stbr__contributors* stbr__get_contributor(stbr__info* stbr_info, int n) @@ -444,7 +447,7 @@ stbr_inline static stbr__contributors* stbr__get_contributor(stbr__info* stbr_in stbr_inline static float* stbr__get_coefficient(stbr__info* stbr_info, int n, int c) { - return &stbr_info->horizontal_coefficients[stbr__get_filter_texel_width(stbr_info->filter)*n + c]; + return &stbr_info->horizontal_coefficients[stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)*n + c]; } stbr_inline static int stbr__edge_wrap(stbr_edge edge, int n, int max) @@ -538,12 +541,14 @@ static void stbr__calculate_coefficients_upsample(stbr__info* stbr_info, int in_ float filter_scale; stbr_filter filter = stbr_info->filter; - STBR_DEBUG_ASSERT(in_last_texel - in_first_texel <= stbr__get_filter_texel_width(filter)); + STBR_DEBUG_ASSERT(in_last_texel - in_first_texel <= stbr__get_filter_texel_width(filter, stbr_info->input_w, stbr_info->output_w)); STBR_DEBUG_ASSERT(in_last_texel < stbr__get_horizontal_contributors(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)); contributor->n0 = in_first_texel; contributor->n1 = in_last_texel; + STBR_DEBUG_ASSERT(contributor->n1 >= contributor->n0); + for (i = 0; i <= in_last_texel - in_first_texel; i++) { float in_texel_center = (float)(i + in_first_texel) + 0.5f; @@ -565,12 +570,14 @@ static void stbr__calculate_coefficients_downsample(stbr__info* stbr_info, float int i; stbr_filter filter = stbr_info->filter; - STBR_DEBUG_ASSERT(out_last_texel - out_first_texel <= stbr__get_filter_texel_width(filter)); + STBR_DEBUG_ASSERT(out_last_texel - out_first_texel <= stbr__get_filter_texel_width(filter, stbr_info->input_w, stbr_info->output_w)); STBR_DEBUG_ASSERT(out_last_texel < stbr__get_horizontal_contributors(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)); contributor->n0 = out_first_texel; contributor->n1 = out_last_texel; + STBR_DEBUG_ASSERT(contributor->n1 >= contributor->n0); + for (i = 0; i <= out_last_texel - out_first_texel; i++) { float in_texel_center = (float)(i + out_first_texel) + 0.5f; @@ -628,14 +635,14 @@ static void stbr__calculate_horizontal_filters(stbr__info* stbr_info) } else { - float in_pixels_radius = stbr__filter_info_table[stbr_info->filter].support; + float in_pixels_radius = stbr__filter_info_table[stbr_info->filter].support / scale_ratio; // Looping through in texels for (n = 0; n < total_contributors; n++) { float out_center_of_in; // Center of the current out texel in the in texel space int out_first_texel, out_last_texel; - int n_adjusted = n - stbr__get_filter_texel_margin(stbr_info->filter); + int n_adjusted = n - stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); stbr__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, &out_first_texel, &out_last_texel, &out_center_of_in); @@ -652,7 +659,7 @@ static float* stbr__get_decode_buffer(stbr__info* stbr_info) { // The 0 index of the decode buffer starts after the margin. This makes // it okay to use negative indexes on the decode buffer. - return &stbr_info->decode_buffer[stbr__get_filter_texel_margin(stbr_info->filter) * stbr_info->channels]; + return &stbr_info->decode_buffer[stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w) * stbr_info->channels]; } #define STBR__DECODE(type, colorspace) ((type) * (STBR_MAX_COLORSPACES) + (colorspace)) @@ -669,10 +676,10 @@ static void stbr__decode_scanline(stbr__info* stbr_info, int n) float* decode_buffer = stbr__get_decode_buffer(stbr_info); stbr_edge edge = stbr_info->edge; int in_buffer_row_index = stbr__edge_wrap(edge, n, stbr_info->input_h) * input_stride_bytes; - int max_x = input_w + stbr__get_filter_texel_margin(stbr_info->filter); + int max_x = input_w + stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); int decode = STBR__DECODE(type, colorspace); - for (x = -stbr__get_filter_texel_margin(stbr_info->filter); x < max_x; x++) + for (x = -stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); x < max_x; x++) { int decode_texel_index = x * channels; int input_texel_index = in_buffer_row_index + stbr__edge_wrap(edge, x, input_w) * channels; @@ -743,7 +750,7 @@ static float* stbr__add_empty_ring_buffer_entry(stbr__info* stbr_info, int n) } else { - ring_buffer_index = (stbr_info->ring_buffer_begin_index + (stbr_info->ring_buffer_last_scanline - stbr_info->ring_buffer_first_scanline) + 1) % stbr__get_filter_texel_width(stbr_info->filter); + ring_buffer_index = (stbr_info->ring_buffer_begin_index + (stbr_info->ring_buffer_last_scanline - stbr_info->ring_buffer_first_scanline) + 1) % stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); STBR_DEBUG_ASSERT(ring_buffer_index != stbr_info->ring_buffer_begin_index); } @@ -760,7 +767,7 @@ static void stbr__resample_horizontal_upsample(stbr__info* stbr_info, int n, flo { int x, k; int output_w = stbr_info->output_w; - int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter); + int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); int channels = stbr_info->channels; float* decode_buffer = stbr__get_decode_buffer(stbr_info); stbr__contributors* horizontal_contributors = stbr_info->horizontal_contributors; @@ -776,10 +783,10 @@ static void stbr__resample_horizontal_upsample(stbr__info* stbr_info, int n, flo int coefficient_counter = 0; STBR_DEBUG_ASSERT(n1 >= n0); - STBR_DEBUG_ASSERT(n0 >= -stbr__get_filter_texel_margin(stbr_info->filter)); - STBR_DEBUG_ASSERT(n1 >= -stbr__get_filter_texel_margin(stbr_info->filter)); - STBR_DEBUG_ASSERT(n0 < stbr_info->input_w + stbr__get_filter_texel_margin(stbr_info->filter)); - STBR_DEBUG_ASSERT(n1 < stbr_info->input_w + stbr__get_filter_texel_margin(stbr_info->filter)); + STBR_DEBUG_ASSERT(n0 >= -stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)); + STBR_DEBUG_ASSERT(n1 >= -stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)); + STBR_DEBUG_ASSERT(n0 < stbr_info->input_w + stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)); + STBR_DEBUG_ASSERT(n1 < stbr_info->input_w + stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w)); for (k = n0; k <= n1; k++) { @@ -799,12 +806,12 @@ static void stbr__resample_horizontal_downsample(stbr__info* stbr_info, int n, f int x, k; int input_w = stbr_info->input_w; int output_w = stbr_info->output_w; - int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter); + int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); int channels = stbr_info->channels; float* decode_buffer = stbr__get_decode_buffer(stbr_info); stbr__contributors* horizontal_contributors = stbr_info->horizontal_contributors; float* horizontal_coefficients = stbr_info->horizontal_coefficients; - int filter_texel_margin = stbr__get_filter_texel_margin(stbr_info->filter); + int filter_texel_margin = stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); int max_x = input_w + filter_texel_margin * 2; STBR_DEBUG_ASSERT(!stbr__use_width_upsampling(stbr_info)); @@ -932,7 +939,7 @@ static void stbr__resample_vertical_upsample(stbr__info* stbr_info, int n, int i int channels = stbr_info->channels; int type = stbr_info->type; int colorspace = stbr_info->colorspace; - int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter); + int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); void* output_data = stbr_info->output_data; float* encode_buffer = stbr_info->encode_buffer; int decode = STBR__DECODE(type, colorspace); @@ -989,7 +996,7 @@ static void stbr__resample_vertical_downsample(stbr__info* stbr_info, int n, int stbr__contributors* vertical_contributors = &stbr_info->vertical_contributors; float* vertical_coefficients = stbr_info->vertical_coefficients; int channels = stbr_info->channels; - int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter); + int kernel_texel_width = stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); void* output_data = stbr_info->output_data; float* horizontal_buffer = stbr_info->horizontal_buffer; @@ -1044,9 +1051,9 @@ static void stbr__buffer_loop_upsample(stbr__info* stbr_info) stbr__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, &in_first_scanline, &in_last_scanline, &in_center_of_out); - STBR_DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbr__get_filter_texel_width(stbr_info->filter)); - STBR_DEBUG_ASSERT(in_first_scanline >= -stbr__get_filter_texel_margin(stbr_info->filter)); - STBR_DEBUG_ASSERT(in_last_scanline < stbr_info->input_w + stbr__get_filter_texel_margin(stbr_info->filter)); + STBR_DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h)); + STBR_DEBUG_ASSERT(in_first_scanline >= -stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_h, stbr_info->output_h)); + STBR_DEBUG_ASSERT(in_last_scanline < stbr_info->input_w + stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_h, stbr_info->output_h)); if (stbr_info->ring_buffer_begin_index >= 0) { @@ -1065,7 +1072,7 @@ static void stbr__buffer_loop_upsample(stbr__info* stbr_info) else { stbr_info->ring_buffer_first_scanline++; - stbr_info->ring_buffer_begin_index = (stbr_info->ring_buffer_begin_index + 1) % stbr__get_filter_texel_width(stbr_info->filter); + stbr_info->ring_buffer_begin_index = (stbr_info->ring_buffer_begin_index + 1) % stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); } } } @@ -1130,7 +1137,7 @@ static void stbr__empty_ring_buffer(stbr__info* stbr_info, int first_necessary_s else { stbr_info->ring_buffer_first_scanline++; - stbr_info->ring_buffer_begin_index = (stbr_info->ring_buffer_begin_index + 1) % stbr__get_filter_texel_width(stbr_info->filter); + stbr_info->ring_buffer_begin_index = (stbr_info->ring_buffer_begin_index + 1) % stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); } } } @@ -1141,20 +1148,20 @@ static void stbr__buffer_loop_downsample(stbr__info* stbr_info) int y; float scale_ratio = (float)stbr_info->output_h / stbr_info->input_h; float in_pixels_radius = stbr__filter_info_table[stbr_info->filter].support; - int max_y = stbr_info->input_h + stbr__get_filter_texel_margin(stbr_info->filter); + int max_y = stbr_info->input_h + stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); STBR_DEBUG_ASSERT(!stbr__use_height_upsampling(stbr_info)); - for (y = -stbr__get_filter_texel_margin(stbr_info->filter); y < max_y; y++) + for (y = -stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_h, stbr_info->output_h); y < max_y; y++) { float out_center_of_in; // Center of the current out scanline in the in scanline space int out_first_scanline, out_last_scanline; stbr__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, &out_first_scanline, &out_last_scanline, &out_center_of_in); - STBR_DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbr__get_filter_texel_width(stbr_info->filter)); - STBR_DEBUG_ASSERT(out_first_scanline >= -2*stbr__get_filter_texel_margin(stbr_info->filter)); - STBR_DEBUG_ASSERT(out_last_scanline < stbr_info->input_w + 2*stbr__get_filter_texel_margin(stbr_info->filter)); + STBR_DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbr__get_filter_texel_width(stbr_info->filter, stbr_info->input_h, stbr_info->output_h)); + STBR_DEBUG_ASSERT(out_first_scanline >= -2 * stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_h, stbr_info->output_h)); + STBR_DEBUG_ASSERT(out_last_scanline < stbr_info->input_w + 2 * stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_h, stbr_info->output_h)); stbr__empty_ring_buffer(stbr_info, out_first_scanline); @@ -1183,13 +1190,17 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : channels * output_w; #ifdef STBR_DEBUG_OVERWRITE_TEST -#define OVERWRITE_ARRAY_SIZE 64 - unsigned char overwrite_output_pre[OVERWRITE_ARRAY_SIZE]; - unsigned char overwrite_tempmem_pre[OVERWRITE_ARRAY_SIZE]; +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; stbr_size_t begin_forbidden = width_stride_output * (output_h - 1) + output_w * channels; - memcpy(overwrite_output_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); - memcpy(overwrite_tempmem_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); #endif STBR_UNIMPLEMENTED(type != STBR_TYPE_UINT8); @@ -1224,20 +1235,20 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input stbr_info->colorspace = colorspace; stbr_info->ring_buffer_length_bytes = output_w * channels * sizeof(float); - stbr_info->decode_buffer_texels = input_w + stbr__get_filter_texel_margin(filter) * 2; + stbr_info->decode_buffer_texels = input_w + stbr__get_filter_texel_margin(filter, input_w, output_w) * 2; #define STBR__NEXT_MEMPTR(current, old, newtype) (newtype*)(((unsigned char*)current) + old) stbr_info->horizontal_contributors = STBR__NEXT_MEMPTR(stbr_info, sizeof(stbr__info), stbr__contributors); stbr_info->horizontal_coefficients = STBR__NEXT_MEMPTR(stbr_info->horizontal_contributors, stbr__get_horizontal_contributors(filter, input_w, output_w) * sizeof(stbr__contributors), float); stbr_info->vertical_coefficients = STBR__NEXT_MEMPTR(stbr_info->horizontal_coefficients, stbr__get_total_coefficients(filter, input_w, output_w) * sizeof(float), float); - stbr_info->decode_buffer = STBR__NEXT_MEMPTR(stbr_info->vertical_coefficients, stbr__get_filter_texel_width(filter) * sizeof(float), float); + stbr_info->decode_buffer = STBR__NEXT_MEMPTR(stbr_info->vertical_coefficients, stbr__get_filter_texel_width(filter, input_h, output_h) * sizeof(float), float); if (stbr__use_height_upsampling(stbr_info)) { stbr_info->horizontal_buffer = NULL; stbr_info->ring_buffer = STBR__NEXT_MEMPTR(stbr_info->decode_buffer, stbr_info->decode_buffer_texels * channels * sizeof(float), float); - stbr_info->encode_buffer = STBR__NEXT_MEMPTR(stbr_info->ring_buffer, stbr_info->ring_buffer_length_bytes * stbr__get_filter_texel_width(filter), float); + stbr_info->encode_buffer = STBR__NEXT_MEMPTR(stbr_info->ring_buffer, stbr_info->ring_buffer_length_bytes * stbr__get_filter_texel_width(filter, input_w, output_w), float); STBR_DEBUG_ASSERT((size_t)STBR__NEXT_MEMPTR(stbr_info->encode_buffer, stbr_info->channels * sizeof(float), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); } @@ -1247,7 +1258,7 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input stbr_info->ring_buffer = STBR__NEXT_MEMPTR(stbr_info->horizontal_buffer, output_w * channels * sizeof(float), float); stbr_info->encode_buffer = NULL; - STBR_DEBUG_ASSERT((size_t)STBR__NEXT_MEMPTR(stbr_info->ring_buffer, stbr_info->ring_buffer_length_bytes * stbr__get_filter_texel_width(filter), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + STBR_DEBUG_ASSERT((size_t)STBR__NEXT_MEMPTR(stbr_info->ring_buffer, stbr_info->ring_buffer_length_bytes * stbr__get_filter_texel_width(filter, input_h, output_h), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); } #undef STBR__NEXT_MEMPTR @@ -1263,8 +1274,10 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input stbr__buffer_loop_downsample(stbr_info); #ifdef STBR_DEBUG_OVERWRITE_TEST - STBR_DEBUG_ASSERT(memcmp(overwrite_output_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); - STBR_DEBUG_ASSERT(memcmp(overwrite_tempmem_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); + STBR_DEBUG_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBR_DEBUG_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBR_DEBUG_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBR_DEBUG_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); #endif return 1; @@ -1276,15 +1289,15 @@ STBRDEF stbr_size_t stbr_calculate_memory(int input_w, int input_h, int output_w STBR_ASSERT(filter != 0); STBR_ASSERT(filter < STBR_ARRAY_SIZE(stbr__filter_info_table)); - int texel_margin = stbr__get_filter_texel_margin(filter); + int texel_margin = stbr__get_filter_texel_margin(filter, input_w, output_w); int info_size = sizeof(stbr__info); int contributors_size = stbr__get_horizontal_contributors(filter, input_w, output_w) * sizeof(stbr__contributors); int horizontal_coefficients_size = stbr__get_total_coefficients(filter, input_w, output_w) * sizeof(float); - int vertical_coefficients_size = stbr__get_filter_texel_width(filter) * sizeof(float); + int vertical_coefficients_size = stbr__get_filter_texel_width(filter, input_h, output_h) * sizeof(float); int decode_buffer_size = (input_w + texel_margin*2) * channels * sizeof(float); int horizontal_buffer_size = output_w * channels * sizeof(float); - int ring_buffer_size = output_w * channels * sizeof(float) * stbr__get_filter_texel_width(filter); + int ring_buffer_size = output_w * channels * sizeof(float) * stbr__get_filter_texel_width(filter, input_h, output_h); int encode_buffer_size = channels * sizeof(float); if (stbr__use_height_upsampling_noinfo(output_h, input_h)) diff --git a/tests/resample_test.cpp b/tests/resample_test.cpp index 645846c..b446442 100644 --- a/tests/resample_test.cpp +++ b/tests/resample_test.cpp @@ -18,6 +18,8 @@ #include #endif +void test_suite(); + int main(int argc, char** argv) { unsigned char* input_data; @@ -26,6 +28,11 @@ int main(int argc, char** argv) int n; int out_w, out_h, out_stride; +#if 1 + test_suite(); + return 0; +#endif + if (argc <= 1) { printf("No input image\n"); @@ -87,3 +94,55 @@ int main(int argc, char** argv) return 0; } + +void resize_image(const char* filename, float width_percent, float height_percent, stbr_filter filter, stbr_edge edge, const char* output_filename) +{ + int w, h, n; + + unsigned char* input_data = stbi_load(filename, &w, &h, &n, 0); + if (!input_data) + { + printf("Input image could not be loaded"); + return; + } + + int out_w = (int)(w * width_percent); + int out_h = (int)(h * height_percent); + + unsigned char* output_data = (unsigned char*)malloc(out_w * out_h * n); + + size_t memory_required = stbr_calculate_memory(w, h, out_w, out_h, n, filter); + void* extra_memory = malloc(memory_required); + + stbr_resize_arbitrary(input_data, w, h, 0, output_data, out_w, out_h, 0, n, STBR_TYPE_UINT8, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required); + + free(extra_memory); + + stbi_write_png(output_filename, out_w, out_h, n, output_data, 0); + + free(output_data); +} + +void test_suite() +{ + // sRGB tests + resize_image("gamma_colors.jpg", .5f, .5f, STBR_FILTER_CATMULLROM, STBR_EDGE_REFLECT, "test-output/gamma_colors.jpg"); + resize_image("gamma_2.2.jpg", .5f, .5f, STBR_FILTER_CATMULLROM, STBR_EDGE_REFLECT, "test-output/gamma_2.2.jpg"); + resize_image("gamma_dalai_lama_gray.jpg", .5f, .5f, STBR_FILTER_CATMULLROM, STBR_EDGE_REFLECT, "test-output/gamma_dalai_lama_gray.jpg"); + + for (int i = 10; i < 100; i++) + { + char outname[200]; + sprintf(outname, "test-output/barbara-width-%d.jpg", i); + resize_image("barbara.png", (float)i / 100, 1, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, outname); + } + + for (int i = 110; i < 1000; i += 10) + { + char outname[200]; + sprintf(outname, "test-output/barbara-width-%d.jpg", i); + resize_image("barbara.png", (float)i / 100, 1, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, outname); + } +} + +