I had the whole premultiply thing backwards.

pull/32/head
Jorge Rodriguez 2014-07-31 18:46:00 -07:00
parent 21c7c8f5d9
commit 13acfca829
2 changed files with 49 additions and 41 deletions

View File

@ -49,8 +49,8 @@
//
// Other function groups are provided, one for each data type, for more advanced functionality:
//
// stbr_resize_type_premultiplied(input_data, input_w, input_h, output_data, output_w, output_h, channels, premultiplied_alpha_channel, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP)
// * premultiplied_alpha_channel is 0 if there are no premultiplied alpha channels. If nonzero, the specified channel will be divided from all other channels before resampling, then multiplied back in after.
// stbr_resize_type_premultiply(input_data, input_w, input_h, output_data, output_w, output_h, channels, premultiply_alpha_channel, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP)
// * premultiply_alpha_channel - if nonzero, the specified channel will be multiplied into all other channels before resampling, then divided back out after.
//
// stbr_resize_type_subpixel(input_data, input_w, input_h, output_data, output_w, output_h, s0, t0, s1, t1, channels, filter, edge)
// * s0, t0, s1, t1 are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use.
@ -61,7 +61,7 @@
// result = stbr_resize_arbitrary(input_data, input_w, input_h, input_stride_in_bytes,
// output_data, output_w, output_h, output_stride_in_bytes,
// s0, t0, s1, t1,
// channels, premultiplied_alpha_channel, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB);
// channels, premultiply_alpha_channel, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB);
//
//
// Control over memory allocation is offered like so:
@ -71,13 +71,13 @@
// result = stbr_resize_advanced(input_data, input_w, input_h, input_stride_in_bytes,
// output_data, output_w, output_h, output_stride_in_bytes,
// s0, t0, s1, t1,
// channels, premultiplied_alpha_channel, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB,
// channels, premultiply_alpha_channel, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB,
// extra_memory, memory_required);
// free(extra_memory);
//
// * input_stride_in_bytes and output_stride_in_bytes can be 0. If so they will be automatically calculated as width * channels.
// * s0, t0, s1, t1 are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use.
// * premultiplied_alpha_channel is 0 if there are no premultiplied alpha channels. If nonzero, the specified channel will be divided from all other channels before resampling, then multiplied back in after.
// * premultiply_alpha_channel - if nonzero, the specified channel will be multiplied into all other channels before resampling, then divided back out after.
// * Returned result is 1 for success or 0 in case of an error. In the case of an error an assert with be triggered, #define STBR_ASSERT() to see it.
// * stbr_resize_advanced() will not allocate any memory, it will use the memory you pass in to do its work. Memory required grows
// approximately linearly with input and output size, but with discontinuities at input_w == output_w and input_h == output_height.
@ -165,21 +165,21 @@ extern "C" {
int channels, stbr_filter filter, stbr_edge edge);
STBRDEF int stbr_resize_uint8_premultiplied(const stbr_uint8* input_data, int input_w, int input_h,
STBRDEF int stbr_resize_uint8_premultiply(const stbr_uint8* input_data, int input_w, int input_h,
stbr_uint8* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge);
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge);
STBRDEF int stbr_resize_uint16_premultiplied(const stbr_uint16* input_data, int input_w, int input_h,
STBRDEF int stbr_resize_uint16_premultiply(const stbr_uint16* input_data, int input_w, int input_h,
stbr_uint16* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge);
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge);
STBRDEF int stbr_resize_uint32_premultiplied(const stbr_uint32* input_data, int input_w, int input_h,
STBRDEF int stbr_resize_uint32_premultiply(const stbr_uint32* input_data, int input_w, int input_h,
stbr_uint32* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge);
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge);
STBRDEF int stbr_resize_float_premultiplied(const float* input_data, int input_w, int input_h,
STBRDEF int stbr_resize_float_premultiply(const float* input_data, int input_w, int input_h,
float* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge);
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge);
STBRDEF int stbr_resize_uint8_subpixel(const stbr_uint8* input_data, int input_w, int input_h,
@ -206,7 +206,7 @@ extern "C" {
STBRDEF int stbr_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 premultiplied_alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace);
int channels, int premultiply_alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace);
//////////////////////////////////////////////////////////////////////////////
@ -219,7 +219,7 @@ extern "C" {
STBRDEF int stbr_resize_advanced(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 premultiplied_alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace,
int channels, int premultiply_alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace,
void* tempmem, stbr_size_t tempmem_size_in_bytes);
@ -847,7 +847,7 @@ static void stbr__decode_scanline(stbr__info* stbr_info, int n)
if (c == premul_alpha_channel)
continue;
decode_buffer[decode_texel_index + c] /= decode_buffer[decode_texel_index + premul_alpha_channel];
decode_buffer[decode_texel_index + c] *= decode_buffer[decode_texel_index + premul_alpha_channel];
}
}
}
@ -1011,7 +1011,7 @@ static stbr_inline void stbr__encode_scanline(void* output_buffer, int output_te
if (n == premul_alpha_channel)
continue;
encode_buffer[encode_texel_index + n] *= encode_buffer[encode_texel_index + premul_alpha_channel];
encode_buffer[encode_texel_index + n] /= encode_buffer[encode_texel_index + premul_alpha_channel];
}
}
@ -1070,7 +1070,7 @@ static stbr_inline void stbr__encode_scanline(void* output_buffer, int output_te
if (n == premul_alpha_channel)
continue;
encode_buffer[encode_texel_index + n] /= encode_buffer[encode_texel_index + premul_alpha_channel];
encode_buffer[encode_texel_index + n] *= encode_buffer[encode_texel_index + premul_alpha_channel];
}
}
}
@ -1564,9 +1564,9 @@ STBRDEF stbr_inline int stbr_resize_float_srgb(const float* input_data, int inpu
return result;
}
STBRDEF stbr_inline int stbr_resize_uint8_premultiplied(const stbr_uint8* input_data, int input_w, int input_h,
STBRDEF stbr_inline int stbr_resize_uint8_premultiply(const stbr_uint8* input_data, int input_w, int input_h,
stbr_uint8* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge)
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge)
{
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, 0, 0, 1, 1, channels, filter);
void* extra_memory = STBR_MALLOC(memory_required);
@ -1574,16 +1574,16 @@ STBRDEF stbr_inline int stbr_resize_uint8_premultiplied(const stbr_uint8* input_
if (!extra_memory)
return 0;
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiplied_alpha_channel, STBR_TYPE_UINT8, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiply_alpha_channel, STBR_TYPE_UINT8, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
STBR_FREE(extra_memory);
return result;
}
STBRDEF stbr_inline int stbr_resize_uint16_premultiplied(const stbr_uint16* input_data, int input_w, int input_h,
STBRDEF stbr_inline int stbr_resize_uint16_premultiply(const stbr_uint16* input_data, int input_w, int input_h,
stbr_uint16* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge)
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge)
{
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, 0, 0, 1, 1, channels, filter);
void* extra_memory = STBR_MALLOC(memory_required);
@ -1591,16 +1591,16 @@ STBRDEF stbr_inline int stbr_resize_uint16_premultiplied(const stbr_uint16* inpu
if (!extra_memory)
return 0;
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiplied_alpha_channel, STBR_TYPE_UINT16, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiply_alpha_channel, STBR_TYPE_UINT16, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
STBR_FREE(extra_memory);
return result;
}
STBRDEF stbr_inline int stbr_resize_uint32_premultiplied(const stbr_uint32* input_data, int input_w, int input_h,
STBRDEF stbr_inline int stbr_resize_uint32_premultiply(const stbr_uint32* input_data, int input_w, int input_h,
stbr_uint32* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge)
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge)
{
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, 0, 0, 1, 1, channels, filter);
void* extra_memory = STBR_MALLOC(memory_required);
@ -1608,16 +1608,16 @@ STBRDEF stbr_inline int stbr_resize_uint32_premultiplied(const stbr_uint32* inpu
if (!extra_memory)
return 0;
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiplied_alpha_channel, STBR_TYPE_UINT32, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiply_alpha_channel, STBR_TYPE_UINT32, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
STBR_FREE(extra_memory);
return result;
}
STBRDEF stbr_inline int stbr_resize_float_premultiplied(const float* input_data, int input_w, int input_h,
STBRDEF stbr_inline int stbr_resize_float_premultiply(const float* input_data, int input_w, int input_h,
float* output_data, int output_w, int output_h,
int channels, int premultiplied_alpha_channel, stbr_filter filter, stbr_edge edge)
int channels, int premultiply_alpha_channel, stbr_filter filter, stbr_edge edge)
{
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, 0, 0, 1, 1, channels, filter);
void* extra_memory = STBR_MALLOC(memory_required);
@ -1625,7 +1625,7 @@ STBRDEF stbr_inline int stbr_resize_float_premultiplied(const float* input_data,
if (!extra_memory)
return 0;
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiplied_alpha_channel, STBR_TYPE_FLOAT, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
int result = stbr_resize_advanced(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, 0, 0, 1, 1, channels, premultiply_alpha_channel, STBR_TYPE_FLOAT, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
STBR_FREE(extra_memory);
@ -1707,7 +1707,7 @@ STBRDEF stbr_inline int stbr_resize_float_subpixel(const float* input_data, int
STBRDEF int stbr_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 premultiplied_alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace)
int channels, int premultiply_alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace)
{
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, s0, t0, s1, t1, channels, filter);
void* extra_memory = STBR_MALLOC(memory_required);
@ -1715,7 +1715,7 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input
if (!extra_memory)
return 0;
int result = stbr_resize_advanced(input_data, input_w, input_h, input_stride_in_bytes, output_data, output_w, output_h, output_stride_in_bytes, s0, t0, s1, t1, channels, premultiplied_alpha_channel, type, filter, edge, colorspace, extra_memory, memory_required);
int result = stbr_resize_advanced(input_data, input_w, input_h, input_stride_in_bytes, output_data, output_w, output_h, output_stride_in_bytes, s0, t0, s1, t1, channels, premultiply_alpha_channel, type, filter, edge, colorspace, extra_memory, memory_required);
STBR_FREE(extra_memory);

View File

@ -286,11 +286,14 @@ void test_premul(const char* file)
unsigned char* input_data = stbi_load(file, &w, &h, &n, 4);
n = 4;
// Premultiply the first texel.
input_data[0] /= 2;
input_data[1] /= 2;
input_data[2] /= 2;
input_data[3] = 255 / 2;
// Set alpha for the top half.
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h / 2; y++)
input_data[(y*w + x)*n + 3] = input_data[(y*w + x)*n + 0];
}
stbi_write_png("test-output/premul-original.png", w, h, n, input_data, 0);
int new_w = (int)(w * .5);
int new_h = (int)(h * .5);
@ -302,14 +305,19 @@ void test_premul(const char* file)
stbr_resize_advanced(input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, n, 3, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB, tempmem, tempmem_size);
free(tempmem);
stbi_image_free(input_data);
char output[200];
sprintf(output, "test-output/premul-%s", file);
stbi_write_png(output, new_w, new_h, n, output_data, 0);
stbr_resize_advanced(input_data, w, h, 0, output_data, new_w, new_h, 0, 0, 0, 1, 1, n, 0, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB, tempmem, tempmem_size);
sprintf(output, "test-output/nopremul-%s", file);
stbi_write_png(output, new_w, new_h, n, output_data, 0);
free(tempmem);
stbi_image_free(input_data);
free(output_data);
}