refactor internal interfaces to avoid passing things multiple times;

finish prepping 'stbir__info' even before calculate_memory;
get rid of 'noinfo' functions since now calculate_memory doesn't need 'em;
add new binary-searched sRGB function (untested)
This commit is contained in:
Sean Barrett 2014-09-01 16:52:04 -07:00
parent 24c540e1b0
commit aee30095c7
2 changed files with 200 additions and 262 deletions

View File

@ -19,10 +19,10 @@
supported filters see the stbir_filter enum. To add a new filter, supported filters see the stbir_filter enum. To add a new filter,
write a filter function and add it to stbir__filter_info_table. write a filter function and add it to stbir__filter_info_table.
Latest revisions: STBIR_MAX_CHANNELS: defaults to 16, if you need more, bump it up
0.50 (2014-07-29) first released version
See end of file for full revision history. Revisions:
0.50 (2014-??-??) first released version
TODO: TODO:
Installable filters Installable filters
@ -209,8 +209,8 @@ STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int
stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,
stbir_filter filter_horizontal, stbir_filter filter_vertical, stbir_filter filter_horizontal, stbir_filter filter_vertical,
stbir_colorspace space, void *alloc_context, stbir_colorspace space, void *alloc_context,
float x_scale, float x_offset, float x_scale, float y_scale,
float y_scale, float y_offset); float x_offset, float y_offset);
STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
@ -290,6 +290,10 @@ typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]
#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL
#endif #endif
#ifndef STBIR_MAX_CHANNELS
#define STBIR_MAX_CHANNELS 16
#endif
// must match stbir_datatype // must match stbir_datatype
static unsigned char stbir__type_size[] = { static unsigned char stbir__type_size[] = {
1, // STBIR_TYPE_UINT8 1, // STBIR_TYPE_UINT8
@ -412,21 +416,44 @@ static float stbir__srgb_uchar_to_linear_float[256] = {
0.982251f, 0.991102f, 1.0f 0.982251f, 0.991102f, 1.0f
}; };
static unsigned char stbir__linear_uchar_to_srgb_uchar[256] = { // sRGB transition values, scaled by 1<<28
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, static int stbir__srgb_offset_to_linear_scaled[256] =
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, 40579, 121738, 202897, 284056, 365216, 446375, 527534, 608693,
151, 151, 152, 153, 154, 155, 156, 157, 157, 158, 159, 160, 161, 161, 162, 163, 164, 165, 165, 166, 167, 168, 168, 169, 689852, 771011, 852421, 938035, 1028466, 1123787, 1224073, 1329393,
170, 171, 171, 172, 173, 174, 174, 175, 176, 176, 177, 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 1439819, 1555418, 1676257, 1802402, 1933917, 2070867, 2213313, 2361317,
187, 187, 188, 189, 189, 190, 191, 191, 192, 193, 193, 194, 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 201, 201, 2514938, 2674237, 2839271, 3010099, 3186776, 3369359, 3557903, 3752463,
202, 202, 203, 204, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 3953090, 4159840, 4372764, 4591913, 4817339, 5049091, 5287220, 5531775,
215, 216, 217, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 5782804, 6040356, 6304477, 6575216, 6852618, 7136729, 7427596, 7725263,
228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239, 8029775, 8341176, 8659511, 8984821, 9317151, 9656544, 10003040, 10356683,
240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 10717513, 11085572, 11460901, 11843540, 12233529, 12630908, 13035717, 13447994,
251, 251, 252, 252, 253, 253, 254, 254, 255 13867779, 14295110, 14730025, 15172563, 15622760, 16080655, 16546285, 17019686,
17500894, 17989948, 18486882, 18991734, 19504536, 20025326, 20554138, 21091010,
21635972, 22189062, 22750312, 23319758, 23897432, 24483368, 25077600, 25680162,
26291086, 26910406, 27538152, 28174360, 28819058, 29472282, 30134062, 30804430,
31483418, 32171058, 32867378, 33572412, 34286192, 35008744, 35740104, 36480296,
37229356, 37987316, 38754196, 39530036, 40314860, 41108700, 41911584, 42723540,
43544600, 44374792, 45214140, 46062680, 46920440, 47787444, 48663720, 49549300,
50444212, 51348480, 52262136, 53185204, 54117712, 55059688, 56011160, 56972156,
57942704, 58922824, 59912552, 60911908, 61920920, 62939616, 63968024, 65006168,
66054072, 67111760, 68179272, 69256616, 70343832, 71440936, 72547952, 73664920,
74791848, 75928776, 77075720, 78232704, 79399760, 80576904, 81764168, 82961576,
84169152, 85386920, 86614904, 87853120, 89101608, 90360384, 91629480, 92908904,
94198688, 95498864, 96809440, 98130456, 99461928, 100803872, 102156320, 103519296,
104892824, 106276920, 107671616, 109076928, 110492880, 111919504, 113356808, 114804824,
116263576, 117733080, 119213360, 120704448, 122206352, 123719104, 125242720, 126777232,
128322648, 129879000, 131446312, 133024600, 134613888, 136214192, 137825552, 139447968,
141081456, 142726080, 144381808, 146048704, 147726768, 149416016, 151116496, 152828192,
154551168, 156285408, 158030944, 159787808, 161556000, 163335568, 165126512, 166928864,
168742640, 170567856, 172404544, 174252704, 176112384, 177983568, 179866320, 181760640,
183666528, 185584032, 187513168, 189453952, 191406400, 193370544, 195346384, 197333952,
199333264, 201344352, 203367216, 205401904, 207448400, 209506752, 211576960, 213659056,
215753056, 217858976, 219976832, 222106656, 224248464, 226402272, 228568096, 230745952,
232935872, 235137872, 237351968, 239578176, 241816512, 244066992, 246329648, 248604512,
250891568, 253190848, 255502368, 257826160, 260162240, 262510608, 264871312, 267244336,
}; };
float stbir__srgb_to_linear(float f) static float stbir__srgb_to_linear(float f)
{ {
if (f <= 0.04045f) if (f <= 0.04045f)
return f / 12.92f; return f / 12.92f;
@ -434,7 +461,7 @@ float stbir__srgb_to_linear(float f)
return (float)pow((f + 0.055f) / 1.055f, 2.4f); return (float)pow((f + 0.055f) / 1.055f, 2.4f);
} }
float stbir__linear_to_srgb(float f) static float stbir__linear_to_srgb(float f)
{ {
if (f <= 0.0031308f) if (f <= 0.0031308f)
return f * 12.92f; return f * 12.92f;
@ -442,7 +469,21 @@ float stbir__linear_to_srgb(float f)
return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f;
} }
static unsigned char stbir__linear_to_srgb_uchar(float f)
{
int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp
int v = 0;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+128 ]) v += 128;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 64 ]) v += 64;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 32 ]) v += 32;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 16 ]) v += 16;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 8 ]) v += 8;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 4 ]) v += 4;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 2 ]) v += 2;
if (x >= stbir__srgb_offset_to_linear_scaled[ v+ 1 ]) v += 1;
return (unsigned char) v;
}
static float stbir__filter_nearest(float x) static float stbir__filter_nearest(float x)
{ {
@ -502,7 +543,7 @@ static float stbir__filter_mitchell(float x)
static stbir__filter_info stbir__filter_info_table[] = { static stbir__filter_info stbir__filter_info_table[] = {
{ NULL, 0.0f }, { NULL, 0.0f },
{ stbir__filter_nearest, 0.5f }, { stbir__filter_nearest, 0.5f }, // 0.000001?
{ stbir__filter_bilinear, 1.0f }, { stbir__filter_bilinear, 1.0f },
{ stbir__filter_bicubic, 2.0f }, { stbir__filter_bicubic, 2.0f },
{ stbir__filter_catmullrom, 2.0f }, { stbir__filter_catmullrom, 2.0f },
@ -564,28 +605,18 @@ stbir__inline static int stbir__get_filter_pixel_margin_vertical(stbir__info* st
return stbir__get_filter_pixel_width(stbir_info->vertical_filter, stbir_info->input_h, stbir_info->output_h, stbir_info->vertical_scale) / 2; return stbir__get_filter_pixel_width(stbir_info->vertical_filter, stbir_info->input_h, stbir_info->output_h, stbir_info->vertical_scale) / 2;
} }
stbir__inline static int stbir__get_horizontal_contributors_noinfo(stbir_filter filter, int input_w, int output_w, float horizontal_scale) stbir__inline static int stbir__get_horizontal_contributors(stbir__info* info)
{ {
if (stbir__use_upsampling(horizontal_scale)) if (stbir__use_upsampling(info->horizontal_scale))
return output_w; return info->output_w;
else else
return (input_w + stbir__get_filter_pixel_margin(filter, input_w, output_w, horizontal_scale) * 2); return (info->input_w + stbir__get_filter_pixel_margin(info->horizontal_filter, info->input_w, info->output_w, info->horizontal_scale) * 2);
} }
stbir__inline static int stbir__get_horizontal_contributors(stbir__info* stbir_info) stbir__inline static int stbir__get_total_coefficients(stbir__info* info)
{ {
return stbir__get_horizontal_contributors_noinfo(stbir_info->horizontal_filter, stbir_info->input_w, stbir_info->output_w, stbir_info->horizontal_scale); return stbir__get_horizontal_contributors(info)
} * stbir__get_filter_pixel_width (info->horizontal_filter, info->input_w, info->output_w, info->horizontal_scale);
stbir__inline static int stbir__get_total_coefficients_noinfo(stbir_filter h_filter, int input_w, int output_w, float horizontal_scale)
{
return stbir__get_horizontal_contributors_noinfo(h_filter, input_w, output_w, horizontal_scale)
* stbir__get_filter_pixel_width (h_filter, input_w, output_w, horizontal_scale);
}
stbir__inline static int stbir__get_total_coefficients(stbir__info* stbir_info)
{
return stbir__get_total_coefficients_noinfo(stbir_info->horizontal_filter, stbir_info->input_w, stbir_info->output_w, stbir_info->horizontal_scale);
} }
stbir__inline static stbir__contributors* stbir__get_contributor(stbir__info* stbir_info, int n) stbir__inline static stbir__contributors* stbir__get_contributor(stbir__info* stbir_info, int n)
@ -1151,7 +1182,7 @@ static stbir__inline void stbir__encode_pixel(stbir__info* stbir_info, void* out
case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB):
for (n = 0; n < channels; n++) for (n = 0; n < channels; n++)
((unsigned char*)output_buffer)[output_pixel_index + n] = stbir__linear_uchar_to_srgb_uchar[(unsigned char)(stbir__saturate(encode_buffer[encode_pixel_index + n]) * 255)]; ((unsigned char*)output_buffer)[output_pixel_index + n] = stbir__linear_to_srgb_uchar(encode_buffer[encode_pixel_index + n]);
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
((unsigned char*)output_buffer)[output_pixel_index + alpha_channel] = (unsigned char)(stbir__saturate(encode_buffer[encode_pixel_index + alpha_channel]) * 255); ((unsigned char*)output_buffer)[output_pixel_index + alpha_channel] = (unsigned char)(stbir__saturate(encode_buffer[encode_pixel_index + alpha_channel]) * 255);
@ -1457,22 +1488,36 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); stbir__empty_ring_buffer(stbir_info, stbir_info->output_h);
} }
static void stbir__calculate_transform(stbir__info *stbir_info, int input_w, int input_h, int output_w, int output_h, float s0, float t0, float s1, float t1, float *transform) static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels)
{ {
info->input_w = input_w;
info->input_h = input_h;
info->output_w = output_w;
info->output_h = output_h;
info->channels = channels;
}
static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform)
{
info->s0 = s0;
info->t0 = t0;
info->s1 = s1;
info->t1 = t1;
if (transform) if (transform)
{ {
stbir_info->horizontal_scale = transform[0]; info->horizontal_scale = transform[0];
stbir_info->vertical_scale = transform[1]; info->vertical_scale = transform[1];
stbir_info->horizontal_shift = transform[2]; info->horizontal_shift = transform[2];
stbir_info->vertical_shift = transform[3]; info->vertical_shift = transform[3];
} }
else else
{ {
stbir_info->horizontal_scale = ((float)output_w / input_w) / (s1 - s0); info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);
stbir_info->vertical_scale = ((float)output_h / input_h) / (t1 - t0); info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);
stbir_info->horizontal_shift = s0 * input_w / (s1 - s0); info->horizontal_shift = s0 * info->input_w / (s1 - s0);
stbir_info->vertical_shift = t0 * input_h / (t1 - t0); info->vertical_shift = t0 * info->input_h / (t1 - t0);
} }
} }
@ -1486,26 +1531,25 @@ static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir
info->vertical_filter = v_filter; info->vertical_filter = v_filter;
} }
static stbir_uint32 stbir__calculate_memory(stbir__info *stbir_info, int input_w, int input_h, int output_w, int output_h, float s0, float t0, float s1, float t1, int channels) static stbir_uint32 stbir__calculate_memory(stbir__info *info)
{ {
int pixel_margin = stbir__get_filter_pixel_margin(stbir_info->horizontal_filter, input_w, output_w, stbir_info->horizontal_scale); int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->input_w, info->output_w, info->horizontal_scale);
int filter_height = stbir__get_filter_pixel_width(stbir_info->vertical_filter, input_h, output_h, stbir_info->vertical_scale); int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->input_h, info->output_h, info->vertical_scale);
int info_size = sizeof(stbir__info); int contributors_size = stbir__get_horizontal_contributors(info) * sizeof(stbir__contributors);
int contributors_size = stbir__get_horizontal_contributors_noinfo(stbir_info->horizontal_filter, input_w, output_w, stbir_info->horizontal_scale) * sizeof(stbir__contributors); int horizontal_coefficients_size = stbir__get_total_coefficients(info) * sizeof(float);
int horizontal_coefficients_size = stbir__get_total_coefficients_noinfo(stbir_info->horizontal_filter, input_w, output_w, stbir_info->horizontal_scale) * sizeof(float);
int vertical_coefficients_size = filter_height * sizeof(float); int vertical_coefficients_size = filter_height * sizeof(float);
int decode_buffer_size = (input_w + pixel_margin*2) * channels * sizeof(float); int decode_buffer_size = (info->input_w + pixel_margin*2) * info->channels * sizeof(float);
int horizontal_buffer_size = output_w * channels * sizeof(float); int horizontal_buffer_size = info->output_w * info->channels * sizeof(float);
int ring_buffer_size = output_w * channels * filter_height * sizeof(float); int ring_buffer_size = info->output_w * info->channels * filter_height * sizeof(float);
int encode_buffer_size = output_w * channels * sizeof(float); int encode_buffer_size = info->output_w * info->channels * sizeof(float);
STBIR_ASSERT(stbir_info->horizontal_filter != 0); STBIR_ASSERT(info->horizontal_filter != 0);
STBIR_ASSERT(stbir_info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late
STBIR_ASSERT(stbir_info->vertical_filter != 0); STBIR_ASSERT(info->vertical_filter != 0);
STBIR_ASSERT(stbir_info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late
if (stbir__use_upsampling(stbir_info->horizontal_scale)) if (stbir__use_upsampling(info->horizontal_scale))
// The horizontal buffer is for when we're downsampling the height and we // The horizontal buffer is for when we're downsampling the height and we
// can't output the result of sampling the decode buffer directly into the // can't output the result of sampling the decode buffer directly into the
// ring buffers. // ring buffers.
@ -1515,21 +1559,20 @@ static stbir_uint32 stbir__calculate_memory(stbir__info *stbir_info, int input_w
// and isn't used when height downsampling. // and isn't used when height downsampling.
encode_buffer_size = 0; encode_buffer_size = 0;
return info_size + contributors_size + horizontal_coefficients_size + vertical_coefficients_size + decode_buffer_size + horizontal_buffer_size + ring_buffer_size + encode_buffer_size; return contributors_size + horizontal_coefficients_size + vertical_coefficients_size + decode_buffer_size + horizontal_buffer_size + ring_buffer_size + encode_buffer_size;
} }
static int stbir__resize_allocated(stbir__info *stbir_info, static int stbir__resize_allocated(stbir__info *info,
const void* input_data, int input_w, int input_h, int input_stride_in_bytes, const void* input_data, int input_stride_in_bytes,
void* output_data, int output_w, int output_h, int output_stride_in_bytes, void* output_data, int output_stride_in_bytes,
float s0, float t0, float s1, float t1, float *transform, int alpha_channel, stbir_uint32 flags, stbir_datatype type,
int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, stbir_filter h_filter, stbir_filter v_filter,
stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace,
void* tempmem, size_t tempmem_size_in_bytes) void* tempmem, size_t tempmem_size_in_bytes)
{ {
size_t memory_required = stbir__calculate_memory(stbir_info, input_w, input_h, output_w, output_h, s0, t0, s1, t1, channels); size_t memory_required = stbir__calculate_memory(info);
int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : channels * input_w * stbir__type_size[type]; int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type];
int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : channels * output_w * stbir__type_size[type]; int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type];
#ifdef STBIR_DEBUG_OVERWRITE_TEST #ifdef STBIR_DEBUG_OVERWRITE_TEST
#define OVERWRITE_ARRAY_SIZE 8 #define OVERWRITE_ARRAY_SIZE 8
@ -1545,32 +1588,27 @@ static int stbir__resize_allocated(stbir__info *stbir_info,
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
STBIR_ASSERT(h_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS);
STBIR_ASSERT(v_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); STBIR_ASSERT(info->channels >= 0);
if (h_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) if (info->channels > STBIR_MAX_CHANNELS || info->channels < 0)
return 0;
if (v_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
return 0; return 0;
STBIR_ASSERT(s1 > s0); STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
STBIR_ASSERT(t1 > t0); STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
if (s1 <= s0 || t1 <= t0) if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
return 0; return 0;
if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
STBIR_ASSERT(s1 <= 1 && s0 >= 0 && t1 <= 1 && t0 >= 0);
if (s1 > 1 || s0 < 0 || t1 > 1 || t0 < 0)
return 0; return 0;
if (alpha_channel < 0) if (alpha_channel < 0)
flags = STBIR_FLAG_ALPHA_USES_COLORSPACE; // this shouldn't be necessary in the long run, but safety for now flags = STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_PREMULTIPLIED_ALPHA;
if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_PREMULTIPLIED_ALPHA)) if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_PREMULTIPLIED_ALPHA))
STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < channels); STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels);
if (alpha_channel >= channels) if (alpha_channel >= info->channels)
return 0; return 0;
STBIR_ASSERT(tempmem); STBIR_ASSERT(tempmem);
@ -1585,69 +1623,57 @@ static int stbir__resize_allocated(stbir__info *stbir_info,
memset(tempmem, 0, tempmem_size_in_bytes); memset(tempmem, 0, tempmem_size_in_bytes);
stbir_info->input_data = input_data; info->input_data = input_data;
stbir_info->input_w = input_w; info->input_stride_bytes = width_stride_input;
stbir_info->input_h = input_h;
stbir_info->input_stride_bytes = width_stride_input;
stbir_info->output_data = output_data; info->output_data = output_data;
stbir_info->output_w = output_w; info->output_stride_bytes = width_stride_output;
stbir_info->output_h = output_h;
stbir_info->output_stride_bytes = width_stride_output;
stbir_info->s0 = s0; info->alpha_channel = alpha_channel;
stbir_info->t0 = t0; info->flags = flags;
stbir_info->s1 = s1; info->type = type;
stbir_info->t1 = t1; info->edge_horizontal = edge_horizontal;
info->edge_vertical = edge_vertical;
info->colorspace = colorspace;
stbir_info->channels = channels; info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float);
stbir_info->alpha_channel = alpha_channel; info->decode_buffer_pixels = info->input_w + stbir__get_filter_pixel_margin_horizontal(info) * 2;
stbir_info->flags = flags;
stbir_info->type = type;
//stbir_info->horizontal_filter = h_filter;
//stbir_info->vertical_filter = v_filter;
stbir_info->edge_horizontal = edge_horizontal;
stbir_info->edge_vertical = edge_vertical;
stbir_info->colorspace = colorspace;
stbir_info->ring_buffer_length_bytes = output_w * channels * sizeof(float);
stbir_info->decode_buffer_pixels = input_w + stbir__get_filter_pixel_margin_horizontal(stbir_info) * 2;
#define STBIR__NEXT_MEMPTR(current, old, newtype) (newtype*)(((unsigned char*)current) + old) #define STBIR__NEXT_MEMPTR(current, old, newtype) (newtype*)(((unsigned char*)current) + old)
stbir_info->horizontal_contributors = (stbir__contributors *) tempmem; info->horizontal_contributors = (stbir__contributors *) tempmem;
stbir_info->horizontal_coefficients = STBIR__NEXT_MEMPTR(stbir_info->horizontal_contributors, stbir__get_horizontal_contributors(stbir_info) * sizeof(stbir__contributors), float); info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, stbir__get_horizontal_contributors(info) * sizeof(stbir__contributors), float);
stbir_info->vertical_coefficients = STBIR__NEXT_MEMPTR(stbir_info->horizontal_coefficients, stbir__get_total_coefficients(stbir_info) * sizeof(float), float); info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__get_total_coefficients(info) * sizeof(float), float);
stbir_info->decode_buffer = STBIR__NEXT_MEMPTR(stbir_info->vertical_coefficients, stbir__get_filter_pixel_width_vertical(stbir_info) * sizeof(float), float); info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, stbir__get_filter_pixel_width_vertical(info) * sizeof(float), float);
if (stbir__use_height_upsampling(stbir_info)) if (stbir__use_height_upsampling(info))
{ {
stbir_info->horizontal_buffer = NULL; info->horizontal_buffer = NULL;
stbir_info->ring_buffer = STBIR__NEXT_MEMPTR(stbir_info->decode_buffer, stbir_info->decode_buffer_pixels * channels * sizeof(float), float); info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, info->decode_buffer_pixels * info->channels * sizeof(float), float);
stbir_info->encode_buffer = STBIR__NEXT_MEMPTR(stbir_info->ring_buffer, stbir_info->ring_buffer_length_bytes * stbir__get_filter_pixel_width_horizontal(stbir_info), float); info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, info->ring_buffer_length_bytes * stbir__get_filter_pixel_width_horizontal(info), float);
STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(stbir_info->encode_buffer, stbir_info->channels * sizeof(float), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, info->channels * sizeof(float), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
} }
else else
{ {
stbir_info->horizontal_buffer = STBIR__NEXT_MEMPTR(stbir_info->decode_buffer, stbir_info->decode_buffer_pixels * channels * sizeof(float), float); info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, info->decode_buffer_pixels * info->channels * sizeof(float), float);
stbir_info->ring_buffer = STBIR__NEXT_MEMPTR(stbir_info->horizontal_buffer, output_w * channels * sizeof(float), float); info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, info->output_w * info->channels * sizeof(float), float);
stbir_info->encode_buffer = NULL; info->encode_buffer = NULL;
STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(stbir_info->ring_buffer, stbir_info->ring_buffer_length_bytes * stbir__get_filter_pixel_width_vertical(stbir_info), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); STBIR__DEBUG_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, info->ring_buffer_length_bytes * stbir__get_filter_pixel_width_vertical(info), unsigned char) == (size_t)tempmem + tempmem_size_in_bytes);
} }
#undef STBIR__NEXT_MEMPTR #undef STBIR__NEXT_MEMPTR
// This signals that the ring buffer is empty // This signals that the ring buffer is empty
stbir_info->ring_buffer_begin_index = -1; info->ring_buffer_begin_index = -1;
stbir__calculate_horizontal_filters(stbir_info); stbir__calculate_horizontal_filters(info);
if (stbir__use_height_upsampling(stbir_info)) if (stbir__use_height_upsampling(info))
stbir__buffer_loop_upsample(stbir_info); stbir__buffer_loop_upsample(info);
else else
stbir__buffer_loop_downsample(stbir_info); stbir__buffer_loop_downsample(info);
#ifdef STBIR_DEBUG_OVERWRITE_TEST #ifdef STBIR_DEBUG_OVERWRITE_TEST
STBIR__DEBUG_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); STBIR__DEBUG_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
@ -1660,7 +1686,7 @@ static int stbir__resize_allocated(stbir__info *stbir_info,
} }
STBIRDEF int stbir_resize_arbitrary2( static int stbir_resize_arbitrary(
void *alloc_context, void *alloc_context,
const void* input_data, int input_w, int input_h, int input_stride_in_bytes, const void* input_data, int input_w, int input_h, int input_stride_in_bytes,
void* output_data, int output_w, int output_h, int output_stride_in_bytes, void* output_data, int output_w, int output_h, int output_stride_in_bytes,
@ -1673,123 +1699,32 @@ STBIRDEF int stbir_resize_arbitrary2(
int result; int result;
size_t memory_required; size_t memory_required;
void* extra_memory; void* extra_memory;
stbir__calculate_transform(&info, input_w, input_h, output_w, output_h, s0,t0,s1,t1,transform);
stbir__setup(&info, input_w, input_h, output_w, output_h, channels);
stbir__calculate_transform(&info, s0,t0,s1,t1,transform);
stbir__choose_filter(&info, h_filter, v_filter); stbir__choose_filter(&info, h_filter, v_filter);
memory_required = stbir__calculate_memory(&info, input_w, input_h, output_w, output_h, 0, 0, 1, 1, channels); memory_required = stbir__calculate_memory(&info);
extra_memory = STBIR_MALLOC(NULL, memory_required); extra_memory = STBIR_MALLOC(NULL, memory_required);
if (!extra_memory) if (!extra_memory)
return 0; return 0;
result = stbir__resize_allocated(&info, input_data, input_w, input_h, input_stride_in_bytes, output_data, output_w, output_h, output_stride_in_bytes, s0, t0, s1, t1, NULL, result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes,
channels, alpha_channel, flags, type, h_filter, v_filter, edge_horizontal, edge_vertical, colorspace, extra_memory, memory_required); output_data, output_stride_in_bytes,
alpha_channel, flags, type,
edge_horizontal, edge_vertical,
colorspace, extra_memory, memory_required);
STBIR_FREE(context, extra_memory); STBIR_FREE(context, extra_memory);
return result; return result;
} }
#if 0
STBIRDEF int stbir_resize_arbitrary(const void* input_data, int input_w, int input_h, int input_stride_in_bytes,
void* output_data, int output_w, int output_h, int output_stride_in_bytes,
float s0, float t0, float s1, float t1,
int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type,
stbir_filter filter, stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace)
{
return stbir_resize_arbitrary2(NULL, input_data, input_w, input_h, input_stride_in_bytes,
output_data, output_w, output_h, output_stride_in_bytes,
s0,t0,s1,t1,NULL, channels, alpha_channel, flags, type,
filter,filter, edge_horizontal,edge_vertical, colorspace);
}
STBIRDEF int stbir_resize_uint16_srgb(const stbir_uint16* input_data, int input_w, int input_h,
stbir_uint16* output_data, int output_w, int output_h,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, 0, 0, STBIR_TYPE_UINT16, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
STBIRDEF int stbir_resize_uint32_srgb(const stbir_uint32* input_data, int input_w, int input_h,
stbir_uint32* output_data, int output_w, int output_h,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, 0, 0, STBIR_TYPE_UINT32, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
STBIRDEF int stbir_resize_float_srgb(const float* input_data, int input_w, int input_h,
float* output_data, int output_w, int output_h,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, 0, 0, STBIR_TYPE_FLOAT, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
STBIRDEF int stbir_resize_uint8_alphaweighted(const stbir_uint8* input_data, int input_w, int input_h,
stbir_uint8* output_data, int output_w, int output_h,
int channels, int alpha_channel, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, alpha_channel, STBIR_FLAG_NONPREMUL_ALPHA, STBIR_TYPE_UINT8, filter, edge, edge, colorspace);
}
STBIRDEF int stbir_resize_uint16_alphaweighted(const stbir_uint16* input_data, int input_w, int input_h,
stbir_uint16* output_data, int output_w, int output_h,
int channels, int alpha_channel, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, alpha_channel, STBIR_FLAG_NONPREMUL_ALPHA, STBIR_TYPE_UINT16, filter, edge, edge, colorspace);
}
STBIRDEF int stbir_resize_uint32_alphaweighted(const stbir_uint32* input_data, int input_w, int input_h,
stbir_uint32* output_data, int output_w, int output_h,
int channels, int alpha_channel, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, alpha_channel, STBIR_FLAG_NONPREMUL_ALPHA, STBIR_TYPE_UINT32, filter, edge, edge, colorspace);
}
STBIRDEF int stbir_resize_float_alphaweighted(const float* input_data, int input_w, int input_h,
float* output_data, int output_w, int output_h,
int channels, int alpha_channel, stbir_filter filter, stbir_edge edge, stbir_colorspace colorspace)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, alpha_channel, STBIR_FLAG_NONPREMUL_ALPHA, STBIR_TYPE_FLOAT, filter, edge, edge, colorspace);
}
STBIRDEF int stbir_resize_uint8_subpixel(const stbir_uint8* input_data, int input_w, int input_h,
stbir_uint8* output_data, int output_w, int output_h,
float s0, float t0, float s1, float t1,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, s0, t0, s1, t1, channels, 0, 0, STBIR_TYPE_UINT8, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
STBIRDEF int stbir_resize_uint16_subpixel(const stbir_uint16* input_data, int input_w, int input_h,
stbir_uint16* output_data, int output_w, int output_h,
float s0, float t0, float s1, float t1,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, s0, t0, s1, t1, channels, 0, 0, STBIR_TYPE_UINT16, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
STBIRDEF int stbir_resize_uint32_subpixel(const stbir_uint32* input_data, int input_w, int input_h,
stbir_uint32* output_data, int output_w, int output_h,
float s0, float t0, float s1, float t1,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, s0, t0, s1, t1, channels, 0, 0, STBIR_TYPE_UINT32, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
STBIRDEF int stbir_resize_float_subpixel(const float* input_data, int input_w, int input_h,
float* output_data, int output_w, int output_h,
float s0, float t0, float s1, float t1,
int channels, stbir_filter filter, stbir_edge edge)
{
return stbir_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, s0, t0, s1, t1, channels, 0, 0, STBIR_TYPE_FLOAT, filter, edge, edge, STBIR_COLORSPACE_SRGB);
}
#endif
STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
int num_channels) int num_channels)
{ {
return stbir_resize_arbitrary2(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
@ -1799,7 +1734,7 @@ STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , i
float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, float *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
int num_channels) int num_channels)
{ {
return stbir_resize_arbitrary2(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
@ -1809,7 +1744,7 @@ STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int inp
unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
int num_channels, int alpha_channel, int flags) int num_channels, int alpha_channel, int flags)
{ {
return stbir_resize_arbitrary2(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
@ -1820,7 +1755,7 @@ STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels
int num_channels, int alpha_channel, int flags, int num_channels, int alpha_channel, int flags,
stbir_edge edge_wrap_mode) stbir_edge edge_wrap_mode)
{ {
return stbir_resize_arbitrary2(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT,
edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB);
@ -1832,7 +1767,7 @@ STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int
stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,
void *alloc_context) void *alloc_context)
{ {
return stbir_resize_arbitrary2(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter,
edge_wrap_mode, edge_wrap_mode, space); edge_wrap_mode, edge_wrap_mode, space);
@ -1844,7 +1779,7 @@ STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int
stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,
void *alloc_context) void *alloc_context)
{ {
return stbir_resize_arbitrary2(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter,
edge_wrap_mode, edge_wrap_mode, space); edge_wrap_mode, edge_wrap_mode, space);
@ -1857,7 +1792,7 @@ STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int
stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space,
void *alloc_context) void *alloc_context)
{ {
return stbir_resize_arbitrary2(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter,
edge_wrap_mode, edge_wrap_mode, space); edge_wrap_mode, edge_wrap_mode, space);
@ -1872,7 +1807,7 @@ STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int
stbir_filter filter_horizontal, stbir_filter filter_vertical, stbir_filter filter_horizontal, stbir_filter filter_vertical,
stbir_colorspace space, void *alloc_context) stbir_colorspace space, void *alloc_context)
{ {
return stbir_resize_arbitrary2(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
edge_mode_horizontal, edge_mode_vertical, space); edge_mode_horizontal, edge_mode_vertical, space);
@ -1886,15 +1821,15 @@ STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int
stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,
stbir_filter filter_horizontal, stbir_filter filter_vertical, stbir_filter filter_horizontal, stbir_filter filter_vertical,
stbir_colorspace space, void *alloc_context, stbir_colorspace space, void *alloc_context,
float x_scale, float x_offset, float x_scale, float y_scale,
float y_scale, float y_offset) float x_offset, float y_offset)
{ {
float transform[4]; float transform[4];
transform[0] = x_scale; transform[0] = x_scale;
transform[1] = y_scale; transform[1] = y_scale;
transform[2] = x_offset; transform[2] = x_offset;
transform[3] = y_offset; transform[3] = y_offset;
return stbir_resize_arbitrary2(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
edge_mode_horizontal, edge_mode_vertical, space); edge_mode_horizontal, edge_mode_vertical, space);
@ -1909,16 +1844,10 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int
stbir_colorspace space, void *alloc_context, stbir_colorspace space, void *alloc_context,
float s0, float t0, float s1, float t1) float s0, float t0, float s1, float t1)
{ {
return stbir_resize_arbitrary2(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, return stbir_resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
output_pixels, output_w, output_h, output_stride_in_bytes, output_pixels, output_w, output_h, output_stride_in_bytes,
s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
edge_mode_horizontal, edge_mode_vertical, space); edge_mode_horizontal, edge_mode_vertical, space);
} }
#endif // STB_IMAGE_RESIZE_IMPLEMENTATION #endif // STB_IMAGE_RESIZE_IMPLEMENTATION
/*
revision history:
0.50 (2014-07-29)
first released version
*/

View File

@ -129,7 +129,7 @@ int main(int argc, char** argv)
{ {
ftime(&initial_time_millis); ftime(&initial_time_millis);
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
stbir_resize_arbitrary2(NULL, input_data + w * border * n + border * n, in_w, in_h, w*n, output_data, out_w, out_h, out_stride, 0, 0, 1, 1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, input_data + w * border * n + border * n, in_w, in_h, w*n, output_data, out_w, out_h, out_stride, 0, 0, 1, 1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
ftime(&final_time_millis); ftime(&final_time_millis);
long lapsed_ms = (long)(final_time_millis.time - initial_time_millis.time) * 1000 + (final_time_millis.millitm - initial_time_millis.millitm); long lapsed_ms = (long)(final_time_millis.time - initial_time_millis.time) * 1000 + (final_time_millis.millitm - initial_time_millis.millitm);
printf("Resample: %dms\n", lapsed_ms); printf("Resample: %dms\n", lapsed_ms);
@ -141,7 +141,7 @@ int main(int argc, char** argv)
printf("Average: %dms\n", average); printf("Average: %dms\n", average);
#else #else
stbir_resize_arbitrary2(NULL, input_data + w * border * n + border * n, in_w, in_h, w*n, output_data, out_w, out_h, out_stride, s0, t0, s1, t1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, input_data + w * border * n + border * n, in_w, in_h, w*n, output_data, out_w, out_h, out_stride, s0, t0, s1, t1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
#endif #endif
stbi_image_free(input_data); stbi_image_free(input_data);
@ -169,7 +169,7 @@ void resize_image(const char* filename, float width_percent, float height_percen
unsigned char* output_data = (unsigned char*)malloc(out_w * out_h * n); unsigned char* output_data = (unsigned char*)malloc(out_w * out_h * n);
stbir_resize_arbitrary2(NULL, input_data, w, h, 0, output_data, out_w, out_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, STBIR_TYPE_UINT8, filter, filter, edge, edge, colorspace); stbir_resize_arbitrary(NULL, input_data, w, h, 0, output_data, out_w, out_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, STBIR_TYPE_UINT8, filter, filter, edge, edge, colorspace);
stbi_image_free(input_data); stbi_image_free(input_data);
@ -204,7 +204,7 @@ void test_format(const char* file, float width_percent, float height_percent, st
T* output_data = (T*)malloc(new_w * new_h * n * sizeof(T)); T* output_data = (T*)malloc(new_w * new_h * n * sizeof(T));
stbir_resize_arbitrary2(NULL, T_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, type, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, colorspace); stbir_resize_arbitrary(NULL, T_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, type, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, colorspace);
free(T_data); free(T_data);
stbi_image_free(input_data); stbi_image_free(input_data);
@ -248,7 +248,7 @@ void test_float(const char* file, float width_percent, float height_percent, stb
float* output_data = (float*)malloc(new_w * new_h * n * sizeof(float)); float* output_data = (float*)malloc(new_w * new_h * n * sizeof(float));
stbir_resize_arbitrary2(NULL, T_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, type, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, colorspace); stbir_resize_arbitrary(NULL, T_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, type, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, colorspace);
free(T_data); free(T_data);
stbi_image_free(input_data); stbi_image_free(input_data);
@ -288,7 +288,7 @@ void test_channels(const char* file, float width_percent, float height_percent,
unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * channels * sizeof(unsigned char)); unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * channels * sizeof(unsigned char));
stbir_resize_uint8_srgb(channels_data, w, h, 0, output_data, new_w, new_h, 0, channels); stbir_resize_uint8_srgb(channels_data, w, h, 0, output_data, new_w, new_h, 0, channels, -1,0);
free(channels_data); free(channels_data);
stbi_image_free(input_data); stbi_image_free(input_data);
@ -316,7 +316,7 @@ void test_subpixel(const char* file, float width_percent, float height_percent,
unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char)); unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char));
stbir_resize_arbitrary2(NULL, input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, s1, t1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, s1, t1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
stbi_image_free(input_data); stbi_image_free(input_data);
@ -351,13 +351,13 @@ void test_premul(const char* file)
unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char)); unsigned char* output_data = (unsigned char*)malloc(new_w * new_h * n * sizeof(unsigned char));
stbir_resize_arbitrary2(NULL, input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, 3, STBIR_FLAG_NONPREMUL_ALPHA, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, 3, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
char output[200]; char output[200];
sprintf(output, "test-output/premul-%s", file); sprintf(output, "test-output/premul-%s", file);
stbi_write_png(output, new_w, new_h, n, output_data, 0); stbi_write_png(output, new_w, new_h, n, output_data, 0);
stbir_resize_arbitrary2(NULL, input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, NULL, n, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
sprintf(output, "test-output/nopremul-%s", file); sprintf(output, "test-output/nopremul-%s", file);
stbi_write_png(output, new_w, new_h, n, output_data, 0); stbi_write_png(output, new_w, new_h, n, output_data, 0);
@ -379,13 +379,13 @@ void test_subpixel_1()
unsigned char output_data[16 * 16]; unsigned char output_data[16 * 16];
stbir_resize_arbitrary2(NULL, image, 8, 8, 0, output_data, 16, 16, 0, 0, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, image, 8, 8, 0, output_data, 16, 16, 0, 0, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
unsigned char output_left[8 * 16]; unsigned char output_left[8 * 16];
unsigned char output_right[8 * 16]; unsigned char output_right[8 * 16];
stbir_resize_arbitrary2(NULL, image, 8, 8, 0, output_left, 8, 16, 0, 0, 0, 0.5f, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, image, 8, 8, 0, output_left, 8, 16, 0, 0, 0, 0.5f, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
stbir_resize_arbitrary2(NULL, image, 8, 8, 0, output_right, 8, 16, 0, 0.5f, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, image, 8, 8, 0, output_right, 8, 16, 0, 0.5f, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
for (int x = 0; x < 8; x++) for (int x = 0; x < 8; x++)
{ {
@ -424,8 +424,8 @@ void test_subpixel_2()
unsigned char output_data_1[16 * 16]; unsigned char output_data_1[16 * 16];
unsigned char output_data_2[16 * 16]; unsigned char output_data_2[16 * 16];
stbir_resize_arbitrary2(NULL, image, 8, 8, 0, output_data_1, 16, 16, 0, 0, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_WRAP, STBIR_EDGE_WRAP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, image, 8, 8, 0, output_data_1, 16, 16, 0, 0, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_WRAP, STBIR_EDGE_WRAP, STBIR_COLORSPACE_SRGB);
stbir_resize_arbitrary2(NULL, large_image, 32, 32, 0, output_data_2, 16, 16, 0, 0.25f, 0.25f, 0.5f, 0.5f, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); stbir_resize_arbitrary(NULL, large_image, 32, 32, 0, output_data_2, 16, 16, 0, 0.25f, 0.25f, 0.5f, 0.5f, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_CATMULLROM, STBIR_FILTER_CATMULLROM, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB);
{for (int x = 0; x < 16; x++) {for (int x = 0; x < 16; x++)
{ {
@ -469,7 +469,7 @@ void test_subpixel_4()
unsigned char output[8 * 8]; unsigned char output[8 * 8];
stbir_resize_arbitrary2(NULL, image, 8, 8, 0, output, 8, 8, 0, 0, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_BILINEAR, STBIR_FILTER_BILINEAR, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); stbir_resize_arbitrary(NULL, image, 8, 8, 0, output, 8, 8, 0, 0, 0, 1, 1, NULL, 1, -1, 0, STBIR_TYPE_UINT8, STBIR_FILTER_BILINEAR, STBIR_FILTER_BILINEAR, STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR);
STBIR_ASSERT(memcmp(image, output, 8 * 8) == 0); STBIR_ASSERT(memcmp(image, output, 8 * 8) == 0);
} }
@ -477,6 +477,15 @@ void test_suite()
{ {
int i; int i;
#if 0 // linear_to_srgb_uchar table
for (i=0; i < 256; ++i) {
float f = stbir__srgb_to_linear((i+0.5f)/256.0f);
printf("%9d, ", (int) ((f) * (1<<28)));
if ((i & 7) == 7)
printf("\n");
}
#endif
test_subpixel_1(); test_subpixel_1();
test_subpixel_2(); test_subpixel_2();
test_subpixel_3(); test_subpixel_3();