Fix shorts. Add test cases for shorts.

pull/32/head
Jorge Rodriguez 2014-07-30 00:16:13 -07:00
parent 7ead9a748d
commit 1fcbe0daaf
2 changed files with 51 additions and 14 deletions

View File

@ -92,7 +92,7 @@ typedef enum
STBR_TYPE_UINT16 = 2, STBR_TYPE_UINT16 = 2,
STBR_TYPE_UINT32 = 3, STBR_TYPE_UINT32 = 3,
STBR_TYPE_FLOAT = 4, STBR_TYPE_FLOAT = 4,
// If you add here, update STBR_MAX_TYPES // If you add here, update STBR_MAX_TYPES and stbr__type_size
} stbr_type; } stbr_type;
#define STBR_MAX_TYPES 4 #define STBR_MAX_TYPES 4
@ -303,6 +303,14 @@ static unsigned char stbr__linear_uchar_to_srgb_uchar[256] = {
0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255 0, 12, 21, 28, 33, 38, 42, 46, 49, 52, 55, 58, 61, 63, 66, 68, 70, 73, 75, 77, 79, 81, 82, 84, 86, 88, 89, 91, 93, 94, 96, 97, 99, 100, 102, 103, 104, 106, 107, 109, 110, 111, 112, 114, 115, 116, 117, 118, 120, 121, 122, 123, 124, 125, 126, 127, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255
}; };
static unsigned char stbr__type_size[] = {
0,
1, // STBR_TYPE_UINT8
2, // STBR_TYPE_UINT16
4, // STBR_TYPE_UINT32
4, // STBR_TYPE_FLOAT
};
float stbr__srgb_to_linear(float f) float stbr__srgb_to_linear(float f)
{ {
if (f <= 0.04045f) if (f <= 0.04045f)
@ -671,11 +679,11 @@ static void stbr__decode_scanline(stbr__info* stbr_info, int n)
int type = stbr_info->type; int type = stbr_info->type;
int colorspace = stbr_info->colorspace; int colorspace = stbr_info->colorspace;
int input_w = stbr_info->input_w; int input_w = stbr_info->input_w;
int input_stride_bytes = stbr_info->input_stride_bytes; int input_stride = stbr_info->input_stride_bytes / stbr__type_size[stbr_info->type];
const void* input_data = stbr_info->input_data; const void* input_data = stbr_info->input_data;
float* decode_buffer = stbr__get_decode_buffer(stbr_info); float* decode_buffer = stbr__get_decode_buffer(stbr_info);
stbr_edge edge = stbr_info->edge; stbr_edge edge = stbr_info->edge;
int in_buffer_row_index = stbr__edge_wrap(edge, n, stbr_info->input_h) * input_stride_bytes; int in_buffer_row_index = stbr__edge_wrap(edge, n, stbr_info->input_h) * input_stride;
int max_x = input_w + stbr__get_filter_texel_margin(stbr_info->filter, stbr_info->input_w, stbr_info->output_w); 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); int decode = STBR__DECODE(type, colorspace);
@ -901,7 +909,7 @@ static stbr_inline void stbr__encode_scanline(void* output_buffer, int output_te
case STBR__DECODE(STBR_TYPE_UINT16, STBR_COLORSPACE_SRGB): case STBR__DECODE(STBR_TYPE_UINT16, STBR_COLORSPACE_SRGB):
for (int n = 0; n < channels; n++) for (int n = 0; n < channels; n++)
((unsigned short*)output_buffer)[output_texel_index + n] = (unsigned short)stbr__linear_to_srgb((stbr__saturate(encode_buffer[encode_texel_index + n]) * 65535)); ((unsigned short*)output_buffer)[output_texel_index + n] = (unsigned short)(stbr__linear_to_srgb(stbr__saturate(encode_buffer[encode_texel_index + n])) * 65535);
break; break;
case STBR__DECODE(STBR_TYPE_UINT32, STBR_COLORSPACE_LINEAR): case STBR__DECODE(STBR_TYPE_UINT32, STBR_COLORSPACE_LINEAR):
@ -911,7 +919,7 @@ static stbr_inline void stbr__encode_scanline(void* output_buffer, int output_te
case STBR__DECODE(STBR_TYPE_UINT32, STBR_COLORSPACE_SRGB): case STBR__DECODE(STBR_TYPE_UINT32, STBR_COLORSPACE_SRGB):
for (int n = 0; n < channels; n++) for (int n = 0; n < channels; n++)
((unsigned int*)output_buffer)[output_texel_index + n] = (unsigned int)stbr__linear_to_srgb((stbr__saturate(encode_buffer[encode_texel_index + n]) * 4294967295)); ((unsigned int*)output_buffer)[output_texel_index + n] = (unsigned int)(stbr__linear_to_srgb(stbr__saturate(encode_buffer[encode_texel_index + n])) * 4294967295);
break; break;
case STBR__DECODE(STBR_TYPE_FLOAT, STBR_COLORSPACE_LINEAR): case STBR__DECODE(STBR_TYPE_FLOAT, STBR_COLORSPACE_LINEAR):
@ -1091,7 +1099,7 @@ static void stbr__buffer_loop_upsample(stbr__info* stbr_info)
static void stbr__empty_ring_buffer(stbr__info* stbr_info, int first_necessary_scanline) static void stbr__empty_ring_buffer(stbr__info* stbr_info, int first_necessary_scanline)
{ {
int output_stride_bytes = stbr_info->output_stride_bytes; int output_stride = stbr_info->output_stride_bytes / stbr__type_size[stbr_info->type];
int channels = stbr_info->channels; int channels = stbr_info->channels;
int type = stbr_info->type; int type = stbr_info->type;
int colorspace = stbr_info->colorspace; int colorspace = stbr_info->colorspace;
@ -1107,12 +1115,10 @@ static void stbr__empty_ring_buffer(stbr__info* stbr_info, int first_necessary_s
// Get rid of whatever we don't need anymore. // Get rid of whatever we don't need anymore.
while (first_necessary_scanline > stbr_info->ring_buffer_first_scanline) while (first_necessary_scanline > stbr_info->ring_buffer_first_scanline)
{ {
STBR_UNIMPLEMENTED(stbr_info->type != STBR_TYPE_UINT8);
if (stbr_info->ring_buffer_first_scanline >= 0 && stbr_info->ring_buffer_first_scanline < stbr_info->output_h) if (stbr_info->ring_buffer_first_scanline >= 0 && stbr_info->ring_buffer_first_scanline < stbr_info->output_h)
{ {
int x; int x;
int output_row = stbr_info->ring_buffer_first_scanline * output_stride_bytes; int output_row = stbr_info->ring_buffer_first_scanline * output_stride;
float* ring_buffer_entry = stbr__get_ring_buffer_entry(ring_buffer, stbr_info->ring_buffer_begin_index, ring_buffer_length); float* ring_buffer_entry = stbr__get_ring_buffer_entry(ring_buffer, stbr_info->ring_buffer_begin_index, ring_buffer_length);
for (x = 0; x < output_w; x++) for (x = 0; x < output_w; x++)
@ -1186,8 +1192,8 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input
int channels, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace, int channels, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace,
void* tempmem, stbr_size_t tempmem_size_in_bytes) void* tempmem, stbr_size_t tempmem_size_in_bytes)
{ {
int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : channels * input_w; int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : channels * input_w * stbr__type_size[type];
int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : channels * output_w; int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : channels * output_w * stbr__type_size[type];
#ifdef STBR_DEBUG_OVERWRITE_TEST #ifdef STBR_DEBUG_OVERWRITE_TEST
#define OVERWRITE_ARRAY_SIZE 8 #define OVERWRITE_ARRAY_SIZE 8
@ -1196,15 +1202,13 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input
unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE];
unsigned char overwrite_tempmem_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; stbr_size_t begin_forbidden = width_stride_output * (output_h - 1) + output_w * channels * stbr__type_size[type];
memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], 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_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_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); memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE);
#endif #endif
STBR_UNIMPLEMENTED(type != STBR_TYPE_UINT8);
STBR_ASSERT(filter != 0); STBR_ASSERT(filter != 0);
STBR_ASSERT(filter < STBR_ARRAY_SIZE(stbr__filter_info_table)); STBR_ASSERT(filter < STBR_ARRAY_SIZE(stbr__filter_info_table));

View File

@ -87,6 +87,7 @@ int main(int argc, char** argv)
#endif #endif
free(extra_memory); free(extra_memory);
stbi_image_free(input_data);
stbi_write_png("output.png", out_w, out_h, n, output_data, out_stride); stbi_write_png("output.png", out_w, out_h, n, output_data, out_stride);
@ -117,12 +118,21 @@ void resize_image(const char* filename, float width_percent, float height_percen
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); 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); free(extra_memory);
stbi_image_free(input_data);
stbi_write_png(output_filename, out_w, out_h, n, output_data, 0); stbi_write_png(output_filename, out_w, out_h, n, output_data, 0);
free(output_data); free(output_data);
} }
template <typename F, typename T>
void convert_image(const F* input, T* output, int length)
{
float f = (pow(2.0f, 8.0f * sizeof(T)) - 1) / (pow(2.0f, 8.0f * sizeof(F)) - 1);
for (int i = 0; i < length; i++)
output[i] = (T)(((float)input[i]) * f);
}
void test_suite() void test_suite()
{ {
// sRGB tests // sRGB tests
@ -164,6 +174,29 @@ void test_suite()
sprintf(outname, "test-output/barbara-width-height-%d.jpg", i); sprintf(outname, "test-output/barbara-width-height-%d.jpg", i);
resize_image("barbara.png", 100 / (float)i, (float)i / 100, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, outname); resize_image("barbara.png", 100 / (float)i, (float)i / 100, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, outname);
} }
{
int w, h, n;
unsigned char* input_data = stbi_load("barbara.png", &w, &h, &n, 0);
unsigned short* short_data = (unsigned short*)malloc(w * h * n * sizeof(unsigned short));
convert_image<unsigned char, unsigned short>(input_data, short_data, w * h * n);
unsigned short* output_data = (unsigned short*)malloc(w * h * n * sizeof(unsigned short));
stbr_resize_srgb_uint16(short_data, w, h, output_data, w * 2, h / 2, n, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP);
free(short_data);
stbi_image_free(input_data);
char* char_data = (char*)malloc(w * h * n * sizeof(char));
convert_image<unsigned short, char>(output_data, char_data, w * h * n);
stbi_write_png("test-output/barbara-short.png", w * 2, h / 2, n, char_data, 0);
free(char_data);
free(output_data);
}
} }