|
|
@ -82,7 +82,7 @@
|
|
|
|
and 99% opaque black produces 50% transparent dark green when
|
|
|
|
and 99% opaque black produces 50% transparent dark green when
|
|
|
|
non-premultiplied, whereas premultiplied it produces 50%
|
|
|
|
non-premultiplied, whereas premultiplied it produces 50%
|
|
|
|
transparent near-black. The former introduces green energy
|
|
|
|
transparent near-black. The former introduces green energy
|
|
|
|
that doesn't exist in the source.)
|
|
|
|
that doesn't exist in the source image.)
|
|
|
|
|
|
|
|
|
|
|
|
2. Artists should not edit premultiplied-alpha images; artists
|
|
|
|
2. Artists should not edit premultiplied-alpha images; artists
|
|
|
|
want non-premultiplied alpha images. Thus, art tools generally output
|
|
|
|
want non-premultiplied alpha images. Thus, art tools generally output
|
|
|
@ -247,10 +247,10 @@ STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels
|
|
|
|
typedef enum
|
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
{
|
|
|
|
STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses
|
|
|
|
STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses
|
|
|
|
STBIR_FILTER_BOX = 1, // Actually a trapezoid. See https://developer.nvidia.com/content/non-power-two-mipmapping
|
|
|
|
STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios
|
|
|
|
STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering
|
|
|
|
STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering
|
|
|
|
STBIR_FILTER_CUBIC = 3, // A cubic b-spline: why this one ????????????
|
|
|
|
STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque
|
|
|
|
STBIR_FILTER_CATMULLROM = 4, // interpolating cubic spline
|
|
|
|
STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline
|
|
|
|
STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3
|
|
|
|
STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3
|
|
|
|
} stbir_filter;
|
|
|
|
} stbir_filter;
|
|
|
|
|
|
|
|
|
|
|
@ -488,6 +488,16 @@ typedef struct
|
|
|
|
|
|
|
|
|
|
|
|
float* horizontal_buffer;
|
|
|
|
float* horizontal_buffer;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// cache these because ceil/floor are inexplicably showing up in profile
|
|
|
|
|
|
|
|
int horizontal_coefficient_width;
|
|
|
|
|
|
|
|
int vertical_coefficient_width;
|
|
|
|
|
|
|
|
int horizontal_filter_pixel_width;
|
|
|
|
|
|
|
|
int vertical_filter_pixel_width;
|
|
|
|
|
|
|
|
int horizontal_filter_pixel_margin;
|
|
|
|
|
|
|
|
int vertical_filter_pixel_margin;
|
|
|
|
|
|
|
|
int horizontal_num_contributors;
|
|
|
|
|
|
|
|
int vertical_num_contributors;
|
|
|
|
|
|
|
|
|
|
|
|
int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)
|
|
|
|
int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter)
|
|
|
|
int ring_buffer_first_scanline;
|
|
|
|
int ring_buffer_first_scanline;
|
|
|
|
int ring_buffer_last_scanline;
|
|
|
|
int ring_buffer_last_scanline;
|
|
|
@ -555,6 +565,10 @@ static float stbir__srgb_uchar_to_linear_float[256] = {
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// sRGB transition values, scaled by 1<<28
|
|
|
|
// sRGB transition values, scaled by 1<<28
|
|
|
|
|
|
|
|
// note that if you only scaled by 1<<16, all the values would be 4K smaller,
|
|
|
|
|
|
|
|
// so [1] would be ~10, and so that would have around 5% error (10 +- 0.5)
|
|
|
|
|
|
|
|
// at the boundary between uint8 0 and 1. This also means that a 64K-entry table
|
|
|
|
|
|
|
|
// would have the same 5% error there.
|
|
|
|
static int stbir__srgb_offset_to_linear_scaled[256] =
|
|
|
|
static int stbir__srgb_offset_to_linear_scaled[256] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
0, 40738, 122216, 203693, 285170, 366648, 448125, 529603,
|
|
|
|
0, 40738, 122216, 203693, 285170, 366648, 448125, 529603,
|
|
|
@ -749,7 +763,7 @@ stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info)
|
|
|
|
|
|
|
|
|
|
|
|
// This is the maximum number of input samples that can affect an output sample
|
|
|
|
// This is the maximum number of input samples that can affect an output sample
|
|
|
|
// with the given filter
|
|
|
|
// with the given filter
|
|
|
|
stbir__inline static int stbir__get_filter_pixel_width(stbir_filter filter, float scale)
|
|
|
|
static int stbir__get_filter_pixel_width(stbir_filter filter, float scale)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
STBIR_ASSERT(filter != 0);
|
|
|
|
STBIR_ASSERT(filter != 0);
|
|
|
|
STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
|
|
|
|
STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
|
|
|
@ -760,34 +774,14 @@ stbir__inline static int stbir__get_filter_pixel_width(stbir_filter filter, floa
|
|
|
|
return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);
|
|
|
|
return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_filter_pixel_width_horizontal(stbir__info* stbir_info)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return stbir__get_filter_pixel_width(stbir_info->horizontal_filter, stbir_info->horizontal_scale);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_filter_pixel_width_vertical(stbir__info* stbir_info)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return stbir__get_filter_pixel_width(stbir_info->vertical_filter, stbir_info->vertical_scale);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is how much to expand buffers to account for filters seeking outside
|
|
|
|
// This is how much to expand buffers to account for filters seeking outside
|
|
|
|
// the image boundaries.
|
|
|
|
// the image boundaries.
|
|
|
|
stbir__inline static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale)
|
|
|
|
static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return stbir__get_filter_pixel_width(filter, scale) / 2;
|
|
|
|
return stbir__get_filter_pixel_width(filter, scale) / 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_filter_pixel_margin_horizontal(stbir__info* stbir_info)
|
|
|
|
static int stbir__get_coefficient_width(stbir_filter filter, float scale)
|
|
|
|
{
|
|
|
|
|
|
|
|
return stbir__get_filter_pixel_width(stbir_info->horizontal_filter, stbir_info->horizontal_scale) / 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_filter_pixel_margin_vertical(stbir__info* stbir_info)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return stbir__get_filter_pixel_width(stbir_info->vertical_filter, stbir_info->vertical_scale) / 2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_coefficient_width(stbir_filter filter, float scale)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (stbir__use_upsampling(scale))
|
|
|
|
if (stbir__use_upsampling(scale))
|
|
|
|
return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
|
|
|
|
return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
|
|
|
@ -795,7 +789,7 @@ stbir__inline static int stbir__get_coefficient_width(stbir_filter filter, float
|
|
|
|
return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2);
|
|
|
|
return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size)
|
|
|
|
static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (stbir__use_upsampling(scale))
|
|
|
|
if (stbir__use_upsampling(scale))
|
|
|
|
return output_size;
|
|
|
|
return output_size;
|
|
|
@ -803,67 +797,31 @@ stbir__inline static int stbir__get_contributors(float scale, stbir_filter filte
|
|
|
|
return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);
|
|
|
|
return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_horizontal_contributors(stbir__info* info)
|
|
|
|
static int stbir__get_total_horizontal_coefficients(stbir__info* info)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);
|
|
|
|
return info->horizontal_num_contributors
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_vertical_contributors(stbir__info* info)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return stbir__get_contributors(info->vertical_scale, info->vertical_filter, info->input_h, info->output_h);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_total_horizontal_coefficients(stbir__info* info)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return stbir__get_horizontal_contributors(info)
|
|
|
|
|
|
|
|
* stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);
|
|
|
|
* stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static int stbir__get_total_vertical_coefficients(stbir__info* info)
|
|
|
|
static int stbir__get_total_vertical_coefficients(stbir__info* info)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return stbir__get_vertical_contributors(info)
|
|
|
|
return info->vertical_num_contributors
|
|
|
|
* stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale);
|
|
|
|
* stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n)
|
|
|
|
static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return &contributors[n];
|
|
|
|
return &contributors[n];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static stbir__contributors* stbir__get_horizontal_contributor(stbir__info* stbir_info, int n)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(n >= 0 && n < stbir__get_horizontal_contributors(stbir_info));
|
|
|
|
|
|
|
|
return stbir__get_contributor(stbir_info->horizontal_contributors, n);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static stbir__contributors* stbir__get_vertical_contributor(stbir__info* stbir_info, int n)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(n >= 0 && n < stbir__get_vertical_contributors(stbir_info));
|
|
|
|
|
|
|
|
return stbir__get_contributor(stbir_info->vertical_contributors, n);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample,
|
|
|
|
// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample,
|
|
|
|
// if you change it here change it there too.
|
|
|
|
// if you change it here change it there too.
|
|
|
|
stbir__inline static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c)
|
|
|
|
static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int width = stbir__get_coefficient_width(filter, scale);
|
|
|
|
int width = stbir__get_coefficient_width(filter, scale);
|
|
|
|
return &coefficients[width*n + c];
|
|
|
|
return &coefficients[width*n + c];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static float* stbir__get_horizontal_coefficient(stbir__info* stbir_info, int n, int c)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(c >= 0 && c < stbir__get_coefficient_width(stbir_info->horizontal_filter, stbir_info->horizontal_scale));
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(n >= 0 && n < stbir__get_total_horizontal_coefficients(stbir_info));
|
|
|
|
|
|
|
|
return stbir__get_coefficient(stbir_info->horizontal_coefficients, stbir_info->horizontal_filter, stbir_info->horizontal_scale, n, c);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stbir__inline static float* stbir__get_vertical_coefficient(stbir__info* stbir_info, int n, int c)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(c >= 0 && c < stbir__get_coefficient_width(stbir_info->vertical_filter, stbir_info->vertical_scale));
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(n >= 0 && n < stbir__get_total_vertical_coefficients(stbir_info));
|
|
|
|
|
|
|
|
return stbir__get_coefficient(stbir_info->vertical_coefficients, stbir_info->vertical_filter, stbir_info->vertical_scale, n, c);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)
|
|
|
|
static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
switch (edge)
|
|
|
|
switch (edge)
|
|
|
@ -1081,7 +1039,7 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st
|
|
|
|
// Do this after normalizing because normalization depends on the n0/n1 values.
|
|
|
|
// Do this after normalizing because normalization depends on the n0/n1 values.
|
|
|
|
for (j = 0; j < num_contributors; j++)
|
|
|
|
for (j = 0; j < num_contributors; j++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int range, max;
|
|
|
|
int range, max, width;
|
|
|
|
|
|
|
|
|
|
|
|
skip = 0;
|
|
|
|
skip = 0;
|
|
|
|
while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)
|
|
|
|
while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)
|
|
|
@ -1098,9 +1056,10 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st
|
|
|
|
range = contributors[j].n1 - contributors[j].n0 + 1;
|
|
|
|
range = contributors[j].n1 - contributors[j].n0 + 1;
|
|
|
|
max = stbir__min(num_coefficients, range);
|
|
|
|
max = stbir__min(num_coefficients, range);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
width = stbir__get_coefficient_width(filter, scale_ratio);
|
|
|
|
for (i = 0; i < max; i++)
|
|
|
|
for (i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (i + skip >= stbir__get_coefficient_width(filter, scale_ratio))
|
|
|
|
if (i + skip >= width)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
*stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);
|
|
|
|
*stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);
|
|
|
@ -1160,7 +1119,7 @@ static float* stbir__get_decode_buffer(stbir__info* stbir_info)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// The 0 index of the decode buffer starts after the margin. This makes
|
|
|
|
// The 0 index of the decode buffer starts after the margin. This makes
|
|
|
|
// it okay to use negative indexes on the decode buffer.
|
|
|
|
// it okay to use negative indexes on the decode buffer.
|
|
|
|
return &stbir_info->decode_buffer[stbir__get_filter_pixel_margin_horizontal(stbir_info) * stbir_info->channels];
|
|
|
|
return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace))
|
|
|
|
#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace))
|
|
|
@ -1179,10 +1138,10 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n)
|
|
|
|
stbir_edge edge_vertical = stbir_info->edge_vertical;
|
|
|
|
stbir_edge edge_vertical = stbir_info->edge_vertical;
|
|
|
|
int in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;
|
|
|
|
int in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;
|
|
|
|
const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset;
|
|
|
|
const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset;
|
|
|
|
int max_x = input_w + stbir__get_filter_pixel_margin_horizontal(stbir_info);
|
|
|
|
int max_x = input_w + stbir_info->horizontal_filter_pixel_margin;
|
|
|
|
int decode = STBIR__DECODE(type, colorspace);
|
|
|
|
int decode = STBIR__DECODE(type, colorspace);
|
|
|
|
|
|
|
|
|
|
|
|
int x = -stbir__get_filter_pixel_margin_horizontal(stbir_info);
|
|
|
|
int x = -stbir_info->horizontal_filter_pixel_margin;
|
|
|
|
|
|
|
|
|
|
|
|
// special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input,
|
|
|
|
// special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input,
|
|
|
|
// and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO
|
|
|
|
// and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO
|
|
|
@ -1296,7 +1255,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n)
|
|
|
|
|
|
|
|
|
|
|
|
if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED))
|
|
|
|
if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (x = -stbir__get_filter_pixel_margin_horizontal(stbir_info); x < max_x; x++)
|
|
|
|
for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int decode_pixel_index = x * channels;
|
|
|
|
int decode_pixel_index = x * channels;
|
|
|
|
|
|
|
|
|
|
|
@ -1320,7 +1279,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n)
|
|
|
|
|
|
|
|
|
|
|
|
if (edge_horizontal == STBIR_EDGE_ZERO)
|
|
|
|
if (edge_horizontal == STBIR_EDGE_ZERO)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (x = -stbir__get_filter_pixel_margin_horizontal(stbir_info); x < 0; x++)
|
|
|
|
for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
decode_buffer[x*channels + c] = 0;
|
|
|
|
decode_buffer[x*channels + c] = 0;
|
|
|
@ -1350,7 +1309,7 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir__get_filter_pixel_width_vertical(stbir_info);
|
|
|
|
ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width;
|
|
|
|
STBIR__DEBUG_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
|
|
|
|
STBIR__DEBUG_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1367,12 +1326,12 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int x, k;
|
|
|
|
int x, k;
|
|
|
|
int output_w = stbir_info->output_w;
|
|
|
|
int output_w = stbir_info->output_w;
|
|
|
|
int kernel_pixel_width = stbir__get_filter_pixel_width_horizontal(stbir_info);
|
|
|
|
int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width;
|
|
|
|
int channels = stbir_info->channels;
|
|
|
|
int channels = stbir_info->channels;
|
|
|
|
float* decode_buffer = stbir__get_decode_buffer(stbir_info);
|
|
|
|
float* decode_buffer = stbir__get_decode_buffer(stbir_info);
|
|
|
|
stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
|
|
|
|
stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
|
|
|
|
float* horizontal_coefficients = stbir_info->horizontal_coefficients;
|
|
|
|
float* horizontal_coefficients = stbir_info->horizontal_coefficients;
|
|
|
|
int coefficient_width = stbir__get_coefficient_width(stbir_info->horizontal_filter, stbir_info->horizontal_scale);
|
|
|
|
int coefficient_width = stbir_info->horizontal_coefficient_width;
|
|
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1384,22 +1343,66 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n,
|
|
|
|
int coefficient_counter = 0;
|
|
|
|
int coefficient_counter = 0;
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(n1 >= n0);
|
|
|
|
STBIR__DEBUG_ASSERT(n1 >= n0);
|
|
|
|
STBIR__DEBUG_ASSERT(n0 >= -stbir__get_filter_pixel_margin_horizontal(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);
|
|
|
|
STBIR__DEBUG_ASSERT(n1 >= -stbir__get_filter_pixel_margin_horizontal(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);
|
|
|
|
STBIR__DEBUG_ASSERT(n0 < stbir_info->input_w + stbir__get_filter_pixel_margin_horizontal(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
|
|
|
|
STBIR__DEBUG_ASSERT(n1 < stbir_info->input_w + stbir__get_filter_pixel_margin_horizontal(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (channels) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = k * 1;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = k * 2;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = k * 3;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = k * 4;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int in_pixel_index = k * channels;
|
|
|
|
int in_pixel_index = k * channels;
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int c;
|
|
|
|
int c;
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
|
|
|
|
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1408,17 +1411,109 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
|
|
|
|
int x, k;
|
|
|
|
int x, k;
|
|
|
|
int input_w = stbir_info->input_w;
|
|
|
|
int input_w = stbir_info->input_w;
|
|
|
|
int output_w = stbir_info->output_w;
|
|
|
|
int output_w = stbir_info->output_w;
|
|
|
|
int kernel_pixel_width = stbir__get_filter_pixel_width_horizontal(stbir_info);
|
|
|
|
int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width;
|
|
|
|
int channels = stbir_info->channels;
|
|
|
|
int channels = stbir_info->channels;
|
|
|
|
float* decode_buffer = stbir__get_decode_buffer(stbir_info);
|
|
|
|
float* decode_buffer = stbir__get_decode_buffer(stbir_info);
|
|
|
|
stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
|
|
|
|
stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
|
|
|
|
float* horizontal_coefficients = stbir_info->horizontal_coefficients;
|
|
|
|
float* horizontal_coefficients = stbir_info->horizontal_coefficients;
|
|
|
|
int coefficient_width = stbir__get_coefficient_width(stbir_info->horizontal_filter, stbir_info->horizontal_scale);
|
|
|
|
int coefficient_width = stbir_info->horizontal_coefficient_width;
|
|
|
|
int filter_pixel_margin = stbir__get_filter_pixel_margin_horizontal(stbir_info);
|
|
|
|
int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin;
|
|
|
|
int max_x = input_w + filter_pixel_margin * 2;
|
|
|
|
int max_x = input_w + filter_pixel_margin * 2;
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(!stbir__use_width_upsampling(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(!stbir__use_width_upsampling(stbir_info));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (channels) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
for (x = 0; x < max_x; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int n0 = horizontal_contributors[x].n0;
|
|
|
|
|
|
|
|
int n1 = horizontal_contributors[x].n1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int in_x = x - filter_pixel_margin;
|
|
|
|
|
|
|
|
int in_pixel_index = in_x * 1;
|
|
|
|
|
|
|
|
int max_n = n1;
|
|
|
|
|
|
|
|
int coefficient_group = coefficient_width * x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (k = n0; k <= max_n; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int out_pixel_index = k * 1;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
for (x = 0; x < max_x; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int n0 = horizontal_contributors[x].n0;
|
|
|
|
|
|
|
|
int n1 = horizontal_contributors[x].n1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int in_x = x - filter_pixel_margin;
|
|
|
|
|
|
|
|
int in_pixel_index = in_x * 2;
|
|
|
|
|
|
|
|
int max_n = n1;
|
|
|
|
|
|
|
|
int coefficient_group = coefficient_width * x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (k = n0; k <= max_n; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int out_pixel_index = k * 2;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
for (x = 0; x < max_x; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int n0 = horizontal_contributors[x].n0;
|
|
|
|
|
|
|
|
int n1 = horizontal_contributors[x].n1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int in_x = x - filter_pixel_margin;
|
|
|
|
|
|
|
|
int in_pixel_index = in_x * 3;
|
|
|
|
|
|
|
|
int max_n = n1;
|
|
|
|
|
|
|
|
int coefficient_group = coefficient_width * x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (k = n0; k <= max_n; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int out_pixel_index = k * 3;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
|
|
for (x = 0; x < max_x; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int n0 = horizontal_contributors[x].n0;
|
|
|
|
|
|
|
|
int n1 = horizontal_contributors[x].n1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int in_x = x - filter_pixel_margin;
|
|
|
|
|
|
|
|
int in_pixel_index = in_x * 4;
|
|
|
|
|
|
|
|
int max_n = n1;
|
|
|
|
|
|
|
|
int coefficient_group = coefficient_width * x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (k = n0; k <= max_n; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int out_pixel_index = k * 4;
|
|
|
|
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
for (x = 0; x < max_x; x++)
|
|
|
|
for (x = 0; x < max_x; x++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int n0 = horizontal_contributors[x].n0;
|
|
|
|
int n0 = horizontal_contributors[x].n0;
|
|
|
@ -1431,16 +1526,16 @@ static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n
|
|
|
|
|
|
|
|
|
|
|
|
for (k = n0; k <= max_n; k++)
|
|
|
|
for (k = n0; k <= max_n; k++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
int c;
|
|
|
|
int out_pixel_index = k * channels;
|
|
|
|
int out_pixel_index = k * channels;
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
|
|
|
|
float coefficient = horizontal_coefficients[coefficient_group + k - n0];
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
STBIR__DEBUG_ASSERT(coefficient != 0);
|
|
|
|
|
|
|
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
|
|
|
|
output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n)
|
|
|
|
static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n)
|
|
|
@ -1504,6 +1599,8 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) //#define STBIR__ROUND_INT(f) (floor((f)+0.5))
|
|
|
|
|
|
|
|
|
|
|
|
switch (decode)
|
|
|
|
switch (decode)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):
|
|
|
|
case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR):
|
|
|
@ -1514,7 +1611,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int index = pixel_index + n;
|
|
|
|
int index = pixel_index + n;
|
|
|
|
((unsigned char*)output_buffer)[index] = (unsigned char)(floor(stbir__saturate(encode_buffer[index]) * 255 + 0.5f));
|
|
|
|
((unsigned char*)output_buffer)[index] = (unsigned char) STBIR__ROUND_INT(stbir__saturate(encode_buffer[index]) * 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -1531,7 +1628,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
|
|
|
|
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
|
|
|
|
((unsigned char*)output_buffer)[pixel_index + alpha_channel] = (unsigned char)(floor(stbir__saturate(encode_buffer[pixel_index + alpha_channel]) * 255+0.5f));
|
|
|
|
((unsigned char*)output_buffer)[pixel_index + alpha_channel] = (unsigned char) STBIR__ROUND_INT(stbir__saturate(encode_buffer[pixel_index + alpha_channel]) * 255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
@ -1543,7 +1640,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int index = pixel_index + n;
|
|
|
|
int index = pixel_index + n;
|
|
|
|
((unsigned short*)output_buffer)[index] = (unsigned short)(floor(stbir__saturate(encode_buffer[index]) * 65535+0.5f));
|
|
|
|
((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__saturate(encode_buffer[index]) * 65535);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -1556,11 +1653,11 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int index = pixel_index + n;
|
|
|
|
int index = pixel_index + n;
|
|
|
|
((unsigned short*)output_buffer)[index] = (unsigned short)(floor(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * 65535 + 0.5f));
|
|
|
|
((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * 65535);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
|
|
|
|
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
|
|
|
|
((unsigned short*)output_buffer)[pixel_index + alpha_channel] = (unsigned short)(floor(stbir__saturate(encode_buffer[pixel_index + alpha_channel]) * 65535 + 0.5f));
|
|
|
|
((unsigned short*)output_buffer)[pixel_index + alpha_channel] = (unsigned short)STBIR__ROUND_INT(stbir__saturate(encode_buffer[pixel_index + alpha_channel]) * 65535);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -1573,7 +1670,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int index = pixel_index + n;
|
|
|
|
int index = pixel_index + n;
|
|
|
|
((unsigned int*)output_buffer)[index] = (unsigned int)(floor(((double)stbir__saturate(encode_buffer[index])) * 4294967295 + 0.5f));
|
|
|
|
((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[index])) * 4294967295);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -1586,11 +1683,11 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
for (n = 0; n < channels; n++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int index = pixel_index + n;
|
|
|
|
int index = pixel_index + n;
|
|
|
|
((unsigned int*)output_buffer)[index] = (unsigned int)(floor(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * 4294967295 + 0.5f));
|
|
|
|
((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_INT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * 4294967295);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
|
|
|
|
if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE))
|
|
|
|
((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)(floor(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * 4294967295 + 0.5f));
|
|
|
|
((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * 4294967295);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
@ -1639,11 +1736,12 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
|
|
|
int alpha_channel = stbir_info->alpha_channel;
|
|
|
|
int alpha_channel = stbir_info->alpha_channel;
|
|
|
|
int type = stbir_info->type;
|
|
|
|
int type = stbir_info->type;
|
|
|
|
int colorspace = stbir_info->colorspace;
|
|
|
|
int colorspace = stbir_info->colorspace;
|
|
|
|
int kernel_pixel_width = stbir__get_filter_pixel_width_vertical(stbir_info);
|
|
|
|
int kernel_pixel_width = stbir_info->vertical_filter_pixel_width;
|
|
|
|
void* output_data = stbir_info->output_data;
|
|
|
|
void* output_data = stbir_info->output_data;
|
|
|
|
float* encode_buffer = stbir_info->encode_buffer;
|
|
|
|
float* encode_buffer = stbir_info->encode_buffer;
|
|
|
|
int decode = STBIR__DECODE(type, colorspace);
|
|
|
|
int decode = STBIR__DECODE(type, colorspace);
|
|
|
|
int coefficient_width = stbir__get_coefficient_width(stbir_info->vertical_filter, stbir_info->vertical_scale);
|
|
|
|
int coefficient_width = stbir_info->vertical_coefficient_width;
|
|
|
|
|
|
|
|
int coefficient_counter;
|
|
|
|
int contributor = n;
|
|
|
|
int contributor = n;
|
|
|
|
|
|
|
|
|
|
|
|
float* ring_buffer = stbir_info->ring_buffer;
|
|
|
|
float* ring_buffer = stbir_info->ring_buffer;
|
|
|
@ -1664,22 +1762,82 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in
|
|
|
|
|
|
|
|
|
|
|
|
memset(encode_buffer, 0, output_w * sizeof(float) * channels);
|
|
|
|
memset(encode_buffer, 0, output_w * sizeof(float) * channels);
|
|
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
coefficient_counter = 0;
|
|
|
|
{
|
|
|
|
switch (channels) {
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
case 1:
|
|
|
|
int coefficient_counter = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int coefficient_index = coefficient_counter++;
|
|
|
|
int coefficient_index = coefficient_counter++;
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
|
|
|
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int coefficient_index = coefficient_counter++;
|
|
|
|
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
|
|
|
|
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int coefficient_index = coefficient_counter++;
|
|
|
|
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
|
|
|
|
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int coefficient_index = coefficient_counter++;
|
|
|
|
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
|
|
|
|
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
for (k = n0; k <= n1; k++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int coefficient_index = coefficient_counter++;
|
|
|
|
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
|
|
|
|
float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
int c;
|
|
|
|
int c;
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;
|
|
|
|
encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);
|
|
|
|
stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1691,11 +1849,11 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n,
|
|
|
|
stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
|
|
|
|
stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
|
|
|
|
float* vertical_coefficients = stbir_info->vertical_coefficients;
|
|
|
|
float* vertical_coefficients = stbir_info->vertical_coefficients;
|
|
|
|
int channels = stbir_info->channels;
|
|
|
|
int channels = stbir_info->channels;
|
|
|
|
int kernel_pixel_width = stbir__get_filter_pixel_width_vertical(stbir_info);
|
|
|
|
int kernel_pixel_width = stbir_info->vertical_filter_pixel_width;
|
|
|
|
void* output_data = stbir_info->output_data;
|
|
|
|
void* output_data = stbir_info->output_data;
|
|
|
|
float* horizontal_buffer = stbir_info->horizontal_buffer;
|
|
|
|
float* horizontal_buffer = stbir_info->horizontal_buffer;
|
|
|
|
int coefficient_width = stbir__get_coefficient_width(stbir_info->vertical_filter, stbir_info->vertical_scale);
|
|
|
|
int coefficient_width = stbir_info->vertical_coefficient_width;
|
|
|
|
int contributor = n + stbir__get_filter_pixel_margin_vertical(stbir_info);
|
|
|
|
int contributor = n + stbir_info->vertical_filter_pixel_margin;
|
|
|
|
|
|
|
|
|
|
|
|
float* ring_buffer = stbir_info->ring_buffer;
|
|
|
|
float* ring_buffer = stbir_info->ring_buffer;
|
|
|
|
int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
|
|
|
|
int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
|
|
|
@ -1717,6 +1875,42 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n,
|
|
|
|
|
|
|
|
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (channels) {
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * 1;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * 2;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * 3;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int in_pixel_index = x * 4;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
|
|
|
|
|
|
|
|
ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
for (x = 0; x < output_w; x++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
|
int in_pixel_index = x * channels;
|
|
|
@ -1725,6 +1919,8 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n,
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
for (c = 0; c < channels; c++)
|
|
|
|
ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient;
|
|
|
|
ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1743,7 +1939,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
|
|
|
|
|
|
|
|
|
|
|
|
stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);
|
|
|
|
stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out);
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbir__get_filter_pixel_width_vertical(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width);
|
|
|
|
|
|
|
|
|
|
|
|
if (stbir_info->ring_buffer_begin_index >= 0)
|
|
|
|
if (stbir_info->ring_buffer_begin_index >= 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1762,7 +1958,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
stbir_info->ring_buffer_first_scanline++;
|
|
|
|
stbir_info->ring_buffer_first_scanline++;
|
|
|
|
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir__get_filter_pixel_width_vertical(stbir_info);
|
|
|
|
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1820,7 +2016,7 @@ static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessar
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
stbir_info->ring_buffer_first_scanline++;
|
|
|
|
stbir_info->ring_buffer_first_scanline++;
|
|
|
|
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir__get_filter_pixel_width_vertical(stbir_info);
|
|
|
|
stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1832,7 +2028,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
|
|
|
|
float scale_ratio = stbir_info->vertical_scale;
|
|
|
|
float scale_ratio = stbir_info->vertical_scale;
|
|
|
|
int output_h = stbir_info->output_h;
|
|
|
|
int output_h = stbir_info->output_h;
|
|
|
|
float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio;
|
|
|
|
float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio;
|
|
|
|
int pixel_margin = stbir__get_filter_pixel_margin_vertical(stbir_info);
|
|
|
|
int pixel_margin = stbir_info->vertical_filter_pixel_margin;
|
|
|
|
int max_y = stbir_info->input_h + pixel_margin;
|
|
|
|
int max_y = stbir_info->input_h + pixel_margin;
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info));
|
|
|
@ -1844,7 +2040,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
|
|
|
|
|
|
|
|
|
|
|
|
stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);
|
|
|
|
stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in);
|
|
|
|
|
|
|
|
|
|
|
|
STBIR__DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbir__get_filter_pixel_width_vertical(stbir_info));
|
|
|
|
STBIR__DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width);
|
|
|
|
|
|
|
|
|
|
|
|
if (out_last_scanline < 0 || out_first_scanline >= output_h)
|
|
|
|
if (out_last_scanline < 0 || out_first_scanline >= output_h)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
@ -1915,9 +2111,12 @@ static stbir_uint32 stbir__calculate_memory(stbir__info *info)
|
|
|
|
int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
|
|
|
|
int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
|
|
|
|
int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);
|
|
|
|
int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);
|
|
|
|
|
|
|
|
|
|
|
|
info->horizontal_contributors_size = stbir__get_horizontal_contributors(info) * sizeof(stbir__contributors);
|
|
|
|
info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);
|
|
|
|
|
|
|
|
info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors);
|
|
|
|
info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float);
|
|
|
|
info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float);
|
|
|
|
info->vertical_contributors_size = stbir__get_vertical_contributors(info) * sizeof(stbir__contributors);
|
|
|
|
info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors);
|
|
|
|
info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float);
|
|
|
|
info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float);
|
|
|
|
info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float);
|
|
|
|
info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float);
|
|
|
|
info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float);
|
|
|
|
info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float);
|
|
|
@ -2018,8 +2217,15 @@ static int stbir__resize_allocated(stbir__info *info,
|
|
|
|
info->edge_vertical = edge_vertical;
|
|
|
|
info->edge_vertical = edge_vertical;
|
|
|
|
info->colorspace = colorspace;
|
|
|
|
info->colorspace = colorspace;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);
|
|
|
|
|
|
|
|
info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale );
|
|
|
|
|
|
|
|
info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale);
|
|
|
|
|
|
|
|
info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale );
|
|
|
|
|
|
|
|
info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
|
|
|
|
|
|
|
|
info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale );
|
|
|
|
|
|
|
|
|
|
|
|
info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float);
|
|
|
|
info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float);
|
|
|
|
info->decode_buffer_pixels = info->input_w + stbir__get_filter_pixel_margin_horizontal(info) * 2;
|
|
|
|
info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2;
|
|
|
|
|
|
|
|
|
|
|
|
#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)
|
|
|
|
#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)
|
|
|
|
|
|
|
|
|
|
|
|