176#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H
177#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H
190#ifdef STB_IMAGE_RESIZE_STATIC
191#define STBIRDEF static
194#define STBIRDEF extern "C"
196#define STBIRDEF extern
220 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
224 float* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
234#define STBIR_ALPHA_CHANNEL_NONE -1
239#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0)
242#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1)
245 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
246 int num_channels,
int alpha_channel,
int flags);
259 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
260 int num_channels,
int alpha_channel,
int flags,
299 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
300 int num_channels,
int alpha_channel,
int flags,
302 void* alloc_context);
305 stbir_uint16* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
306 int num_channels,
int alpha_channel,
int flags,
308 void* alloc_context);
311 float* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
312 int num_channels,
int alpha_channel,
int flags,
314 void* alloc_context);
342 void* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
344 int num_channels,
int alpha_channel,
int flags,
350 void* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
352 int num_channels,
int alpha_channel,
int flags,
356 float x_scale,
float y_scale,
357 float x_offset,
float y_offset);
360 void* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
362 int num_channels,
int alpha_channel,
int flags,
366 float s0,
float t0,
float s1,
float t1);
378#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION
382#define STBIR_ASSERT(x) assert(x)
386#define STBIR__DEBUG_ASSERT STBIR_ASSERT
388#define STBIR__DEBUG_ASSERT
392#define STBIR__UNIMPLEMENTED(x) STBIR_ASSERT(!(x))
401#define STBIR_MALLOC(size,c) malloc(size)
402#define STBIR_FREE(ptr,c) free(ptr)
407#define stbir__inline inline
412#define stbir__inline __forceinline
417typedef unsigned char stbir__validate_uint32[
sizeof(
stbir_uint32) == 4 ? 1 : -1];
420#define STBIR__NOTUSED(v) (void)(v)
422#define STBIR__NOTUSED(v) (void)sizeof(v)
425#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))
427#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE
428#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM
431#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE
432#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL
435#ifndef STBIR_PROGRESS_REPORT
436#define STBIR_PROGRESS_REPORT(float_0_to_1)
439#ifndef STBIR_MAX_CHANNELS
440#define STBIR_MAX_CHANNELS 64
443#if STBIR_MAX_CHANNELS > 65536
444#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536."
453#ifndef STBIR_ALPHA_EPSILON
454#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))
460#define STBIR__UNUSED_PARAM(v) (void)(v)
462#define STBIR__UNUSED_PARAM(v) (void)sizeof(v)
466static unsigned char stbir__type_size[] = {
474typedef float (stbir__kernel_fn)(
float x,
float scale);
475typedef float (stbir__support_fn)(
float scale);
479 stbir__kernel_fn* kernel;
480 stbir__support_fn* support;
489} stbir__contributors;
493 const void* input_data;
496 int input_stride_bytes;
501 int output_stride_bytes;
503 float s0, t0, s1, t1;
505 float horizontal_shift;
506 float vertical_shift;
507 float horizontal_scale;
508 float vertical_scale;
520 stbir__contributors* horizontal_contributors;
521 float* horizontal_coefficients;
523 stbir__contributors* vertical_contributors;
524 float* vertical_coefficients;
526 int decode_buffer_pixels;
527 float* decode_buffer;
529 float* horizontal_buffer;
532 int horizontal_coefficient_width;
533 int vertical_coefficient_width;
534 int horizontal_filter_pixel_width;
535 int vertical_filter_pixel_width;
536 int horizontal_filter_pixel_margin;
537 int vertical_filter_pixel_margin;
538 int horizontal_num_contributors;
539 int vertical_num_contributors;
541 int ring_buffer_length_bytes;
542 int ring_buffer_first_scanline;
543 int ring_buffer_last_scanline;
544 int ring_buffer_begin_index;
547 float* encode_buffer;
549 int horizontal_contributors_size;
550 int horizontal_coefficients_size;
551 int vertical_contributors_size;
552 int vertical_coefficients_size;
553 int decode_buffer_size;
554 int horizontal_buffer_size;
555 int ring_buffer_size;
556 int encode_buffer_size;
559static stbir__inline
int stbir__min(
int a,
int b)
561 return a < b ? a : b;
564static stbir__inline
int stbir__max(
int a,
int b)
566 return a > b ? a : b;
569static stbir__inline
float stbir__saturate(
float x)
580#ifdef STBIR_SATURATE_INT
581static stbir__inline
stbir_uint8 stbir__saturate8(
int x)
583 if ((
unsigned int)x <= 255)
592static stbir__inline
stbir_uint16 stbir__saturate16(
int x)
594 if ((
unsigned int)x <= 65535)
604static float stbir__srgb_uchar_to_linear_float[256] = {
605 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
606 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,
607 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,
608 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,
609 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,
610 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,
611 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,
612 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
613 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,
614 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,
615 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,
616 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,
617 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,
618 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,
619 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
620 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,
621 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,
622 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,
623 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,
624 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,
625 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,
626 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
627 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,
628 0.982251f, 0.991102f, 1.0f
631static float stbir__srgb_to_linear(
float f)
636 return (
float)
pow((f + 0.055f) / 1.055f, 2.4f);
639static float stbir__linear_to_srgb(
float f)
644 return 1.055f * (float)
pow(f, 1 / 2.4f) - 0.055f;
647#ifndef STBIR_NON_IEEE_FLOAT
657 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,
658 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,
659 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,
660 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,
661 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,
662 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,
663 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,
664 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,
665 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,
666 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,
667 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,
668 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,
669 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,
672static stbir_uint8 stbir__linear_to_srgb_uchar(
float in)
674 static const stbir__FP32 almostone = { 0x3f7fffff };
675 static const stbir__FP32 minval = { (127 - 13) << 23 };
682 if (!(in > minval.f))
684 if (in > almostone.f)
689 tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];
690 bias = (tab >> 16) << 9;
691 scale = tab & 0xffff;
694 t = (f.u >> 12) & 0xff;
695 return (
unsigned char)((bias + scale *
t) >> 16);
700static int stbir__srgb_offset_to_linear_scaled[256] =
702 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603,
703 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926,
704 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148,
705 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856,
706 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731,
707 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369,
708 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021,
709 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073,
710 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389,
711 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552,
712 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066,
713 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490,
714 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568,
715 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316,
716 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096,
717 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700,
718 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376,
719 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912,
720 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648,
721 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512,
722 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072,
723 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544,
724 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832,
725 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528,
726 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968,
727 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184,
728 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992,
729 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968,
730 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480,
731 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656,
732 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464,
733 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664,
736static stbir_uint8 stbir__linear_to_srgb_uchar(
float f)
738 int x = (int)(f * (1 << 28));
743 i = v + 128;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
744 i = v + 64;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
745 i = v + 32;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
746 i = v + 16;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
747 i = v + 8;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
748 i = v + 4;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
749 i = v + 2;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
750 i = v + 1;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
756static float stbir__filter_trapezoid(
float x,
float scale)
758 float halfscale = scale / 2;
759 float t = 0.5f + halfscale;
760 STBIR__DEBUG_ASSERT(scale <= 1);
768 float r = 0.5f - halfscale;
772 return (
t - x) / scale;
776static float stbir__support_trapezoid(
float scale)
778 STBIR__DEBUG_ASSERT(scale <= 1);
779 return 0.5f + scale / 2;
782static float stbir__filter_triangle(
float x,
float s)
784 STBIR__UNUSED_PARAM(s);
794static float stbir__filter_cubic(
float x,
float s)
796 STBIR__UNUSED_PARAM(s);
801 return (4 + x * x * (3 * x - 6)) / 6;
803 return (8 + x * (-12 + x * (6 - x))) / 6;
808static float stbir__filter_catmullrom(
float x,
float s)
810 STBIR__UNUSED_PARAM(s);
815 return 1 -
x *
x * (2.5f - 1.5f *
x);
817 return 2 -
x * (4 +
x * (0.5f *
x - 2.5f));
822static float stbir__filter_mitchell(
float x,
float s)
824 STBIR__UNUSED_PARAM(s);
829 return (16 + x * x * (21 * x - 36)) / 18;
831 return (32 + x * (-60 + x * (36 - 7 * x))) / 18;
836static float stbir__support_zero(
float s)
838 STBIR__UNUSED_PARAM(s);
842static float stbir__support_one(
float s)
844 STBIR__UNUSED_PARAM(s);
848static float stbir__support_two(
float s)
850 STBIR__UNUSED_PARAM(s);
854static stbir__filter_info stbir__filter_info_table[] = {
855 {
NULL, stbir__support_zero },
856 { stbir__filter_trapezoid, stbir__support_trapezoid },
857 { stbir__filter_triangle, stbir__support_one },
858 { stbir__filter_cubic, stbir__support_two },
859 { stbir__filter_catmullrom, stbir__support_two },
860 { stbir__filter_mitchell, stbir__support_two },
863stbir__inline
static int stbir__use_upsampling(
float ratio)
868stbir__inline
static int stbir__use_width_upsampling(stbir__info* stbir_info)
870 return stbir__use_upsampling(stbir_info->horizontal_scale);
873stbir__inline
static int stbir__use_height_upsampling(stbir__info* stbir_info)
875 return stbir__use_upsampling(stbir_info->vertical_scale);
880static int stbir__get_filter_pixel_width(
stbir_filter filter,
float scale)
882 STBIR_ASSERT(filter != 0);
883 STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
885 if (stbir__use_upsampling(scale))
886 return (
int)
ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
888 return (
int)
ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);
893static int stbir__get_filter_pixel_margin(
stbir_filter filter,
float scale)
895 return stbir__get_filter_pixel_width(filter, scale) / 2;
898static int stbir__get_coefficient_width(
stbir_filter filter,
float scale)
900 if (stbir__use_upsampling(scale))
901 return (
int)
ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
903 return (
int)
ceil(stbir__filter_info_table[filter].support(scale) * 2);
906static int stbir__get_contributors(
float scale,
stbir_filter filter,
int input_size,
int output_size)
908 if (stbir__use_upsampling(scale))
911 return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);
914static int stbir__get_total_horizontal_coefficients(stbir__info* info)
916 return info->horizontal_num_contributors
917 * stbir__get_coefficient_width(info->horizontal_filter, info->horizontal_scale);
920static int stbir__get_total_vertical_coefficients(stbir__info* info)
922 return info->vertical_num_contributors
923 * stbir__get_coefficient_width(info->vertical_filter, info->vertical_scale);
926static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors,
int n)
928 return &contributors[n];
933static float* stbir__get_coefficient(
float* coefficients,
stbir_filter filter,
float scale,
int n,
int c)
935 int width = stbir__get_coefficient_width(filter, scale);
936 return &coefficients[width * n + c];
939static int stbir__edge_wrap_slow(
stbir_edge edge,
int n,
int max)
992 STBIR__UNIMPLEMENTED(
"Unimplemented edge type");
997stbir__inline
static int stbir__edge_wrap(
stbir_edge edge,
int n,
int max)
1000 if (n >= 0 && n <
max)
1002 return stbir__edge_wrap_slow(edge, n,
max);
1006static void stbir__calculate_sample_range_upsample(
int n,
float out_filter_radius,
float scale_ratio,
float out_shift,
int* in_first_pixel,
int* in_last_pixel,
float* in_center_of_out)
1008 float out_pixel_center = (float)n + 0.5f;
1009 float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;
1010 float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;
1012 float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio;
1013 float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio;
1015 *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio;
1016 *in_first_pixel = (int)(
floor(in_pixel_influence_lowerbound + 0.5));
1017 *in_last_pixel = (int)(
floor(in_pixel_influence_upperbound - 0.5));
1021static void stbir__calculate_sample_range_downsample(
int n,
float in_pixels_radius,
float scale_ratio,
float out_shift,
int* out_first_pixel,
int* out_last_pixel,
float* out_center_of_in)
1023 float in_pixel_center = (float)n + 0.5f;
1024 float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;
1025 float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;
1027 float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift;
1028 float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift;
1030 *out_center_of_in = in_pixel_center * scale_ratio - out_shift;
1031 *out_first_pixel = (int)(
floor(out_pixel_influence_lowerbound + 0.5));
1032 *out_last_pixel = (int)(
floor(out_pixel_influence_upperbound - 0.5));
1035static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info,
stbir_filter filter,
float scale,
int in_first_pixel,
int in_last_pixel,
float in_center_of_out, stbir__contributors* contributor,
float* coefficient_group)
1038 float total_filter = 0;
1041 STBIR__DEBUG_ASSERT(in_last_pixel - in_first_pixel <= (
int)
ceil(stbir__filter_info_table[filter].support(1 / scale) * 2));
1043 contributor->n0 = in_first_pixel;
1044 contributor->n1 = in_last_pixel;
1046 STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0);
1048 for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
1050 float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;
1051 coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale);
1054 if (i == 0 && !coefficient_group[i])
1056 contributor->n0 = ++in_first_pixel;
1061 total_filter += coefficient_group[i];
1064 STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((
float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1 / scale) == 0);
1066 STBIR__DEBUG_ASSERT(total_filter > 0.9);
1067 STBIR__DEBUG_ASSERT(total_filter < 1.1f);
1070 filter_scale = 1 / total_filter;
1072 for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
1073 coefficient_group[i] *= filter_scale;
1075 for (i = in_last_pixel - in_first_pixel; i >= 0; i--)
1077 if (coefficient_group[i])
1081 contributor->n1 = contributor->n0 + i - 1;
1085static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info,
stbir_filter filter,
float scale_ratio,
int out_first_pixel,
int out_last_pixel,
float out_center_of_in, stbir__contributors* contributor,
float* coefficient_group)
1089 STBIR__DEBUG_ASSERT(out_last_pixel - out_first_pixel <= (
int)
ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2));
1091 contributor->n0 = out_first_pixel;
1092 contributor->n1 = out_last_pixel;
1094 STBIR__DEBUG_ASSERT(contributor->n1 >= contributor->n0);
1096 for (i = 0; i <= out_last_pixel - out_first_pixel; i++)
1098 float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;
1099 float x = out_pixel_center - out_center_of_in;
1100 coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;
1103 STBIR__DEBUG_ASSERT(stbir__filter_info_table[filter].kernel((
float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
1105 for (i = out_last_pixel - out_first_pixel; i >= 0; i--)
1107 if (coefficient_group[i])
1111 contributor->n1 = contributor->n0 + i - 1;
1115static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, stbir__contributors* contributors,
float* coefficients,
stbir_filter filter,
float scale_ratio,
float shift,
int input_size,
int output_size)
1117 int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
1118 int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio);
1122 for (i = 0; i < output_size; i++)
1127 for (j = 0; j < num_contributors; j++)
1129 if (i >= contributors[j].n0 && i <= contributors[j].n1)
1131 float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0);
1132 total += coefficient;
1134 else if (i < contributors[j].n0)
1138 STBIR__DEBUG_ASSERT(total > 0.9f);
1139 STBIR__DEBUG_ASSERT(total < 1.1f);
1143 for (j = 0; j < num_contributors; j++)
1145 if (i >= contributors[j].n0 && i <= contributors[j].n1)
1146 *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale;
1147 else if (i < contributors[j].n0)
1154 for (j = 0; j < num_contributors; j++)
1156 int range,
max, width;
1159 while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)
1162 contributors[j].n0 += skip;
1164 while (contributors[j].n0 < 0)
1166 contributors[j].n0++;
1170 range = contributors[j].n1 - contributors[j].n0 + 1;
1171 max = stbir__min(num_coefficients, range);
1173 width = stbir__get_coefficient_width(filter, scale_ratio);
1174 for (i = 0; i <
max; i++)
1176 if (i + skip >= width)
1179 *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);
1186 for (i = 0; i < num_contributors; i++)
1187 contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1);
1192static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributors* contributors,
float* coefficients,
stbir_filter filter,
float scale_ratio,
float shift,
int input_size,
int output_size)
1195 int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
1197 if (stbir__use_upsampling(scale_ratio))
1199 float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio;
1202 for (n = 0; n < total_contributors; n++)
1204 float in_center_of_out;
1205 int in_first_pixel, in_last_pixel;
1207 stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out);
1209 stbir__calculate_coefficients_upsample(stbir_info, filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));
1214 float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio;
1217 for (n = 0; n < total_contributors; n++)
1219 float out_center_of_in;
1220 int out_first_pixel, out_last_pixel;
1221 int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio);
1223 stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in);
1225 stbir__calculate_coefficients_downsample(stbir_info, filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0));
1228 stbir__normalize_downsample_coefficients(stbir_info, contributors, coefficients, filter, scale_ratio, shift, input_size, output_size);
1232static float* stbir__get_decode_buffer(stbir__info* stbir_info)
1236 return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];
1239#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace))
1241static void stbir__decode_scanline(stbir__info* stbir_info,
int n)
1244 int channels = stbir_info->channels;
1245 int alpha_channel = stbir_info->alpha_channel;
1246 int type = stbir_info->type;
1247 int colorspace = stbir_info->colorspace;
1248 int input_w = stbir_info->input_w;
1249 int input_stride_bytes = stbir_info->input_stride_bytes;
1250 float* decode_buffer = stbir__get_decode_buffer(stbir_info);
1251 stbir_edge edge_horizontal = stbir_info->edge_horizontal;
1252 stbir_edge edge_vertical = stbir_info->edge_vertical;
1253 int in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;
1254 const void* input_data = (
char*)stbir_info->input_data + in_buffer_row_offset;
1255 int max_x = input_w + stbir_info->horizontal_filter_pixel_margin;
1256 int decode = STBIR__DECODE(type, colorspace);
1258 int x = -stbir_info->horizontal_filter_pixel_margin;
1262 if (edge_vertical ==
STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h))
1264 for (;
x < max_x;
x++)
1265 for (c = 0; c < channels; c++)
1266 decode_buffer[x * channels + c] = 0;
1273 for (;
x < max_x;
x++)
1275 int decode_pixel_index =
x * channels;
1276 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1277 for (c = 0; c < channels; c++)
1278 decode_buffer[decode_pixel_index + c] = ((
float)((
const unsigned char*)input_data)[input_pixel_index + c]) / 255;
1283 for (;
x < max_x;
x++)
1285 int decode_pixel_index =
x * channels;
1286 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1287 for (c = 0; c < channels; c++)
1288 decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((
const unsigned char*)input_data)[input_pixel_index + c]];
1291 decode_buffer[decode_pixel_index + alpha_channel] = ((float)((
const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / 255;
1296 for (;
x < max_x;
x++)
1298 int decode_pixel_index =
x * channels;
1299 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1300 for (c = 0; c < channels; c++)
1301 decode_buffer[decode_pixel_index + c] = ((
float)((
const unsigned short*)input_data)[input_pixel_index + c]) / 65535;
1306 for (;
x < max_x;
x++)
1308 int decode_pixel_index =
x * channels;
1309 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1310 for (c = 0; c < channels; c++)
1311 decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((
float)((
const unsigned short*)input_data)[input_pixel_index + c]) / 65535);
1314 decode_buffer[decode_pixel_index + alpha_channel] = ((float)((
const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / 65535;
1319 for (;
x < max_x;
x++)
1321 int decode_pixel_index =
x * channels;
1322 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1323 for (c = 0; c < channels; c++)
1324 decode_buffer[decode_pixel_index + c] = (
float)(((double)((
const unsigned int*)input_data)[input_pixel_index + c]) / 4294967295);
1329 for (;
x < max_x;
x++)
1331 int decode_pixel_index =
x * channels;
1332 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1333 for (c = 0; c < channels; c++)
1334 decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((
float)(((
double)((
const unsigned int*)input_data)[input_pixel_index + c]) / 4294967295));
1337 decode_buffer[decode_pixel_index + alpha_channel] = (float)(((
double)((
const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / 4294967295);
1342 for (;
x < max_x;
x++)
1344 int decode_pixel_index =
x * channels;
1345 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1346 for (c = 0; c < channels; c++)
1347 decode_buffer[decode_pixel_index + c] = ((
const float*)input_data)[input_pixel_index + c];
1352 for (;
x < max_x;
x++)
1354 int decode_pixel_index =
x * channels;
1355 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1356 for (c = 0; c < channels; c++)
1357 decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((
const float*)input_data)[input_pixel_index + c]);
1360 decode_buffer[decode_pixel_index + alpha_channel] = ((
const float*)input_data)[input_pixel_index + alpha_channel];
1366 STBIR__UNIMPLEMENTED(
"Unknown type/colorspace/channels combination.");
1372 for (x = -stbir_info->horizontal_filter_pixel_margin;
x < max_x;
x++)
1374 int decode_pixel_index =
x * channels;
1377 float alpha = decode_buffer[decode_pixel_index + alpha_channel];
1378#ifndef STBIR_NO_ALPHA_EPSILON
1380 alpha += STBIR_ALPHA_EPSILON;
1381 decode_buffer[decode_pixel_index + alpha_channel] = alpha;
1384 for (c = 0; c < channels; c++)
1386 if (c == alpha_channel)
1389 decode_buffer[decode_pixel_index + c] *= alpha;
1396 for (x = -stbir_info->horizontal_filter_pixel_margin;
x < 0;
x++)
1398 for (c = 0; c < channels; c++)
1399 decode_buffer[x * channels + c] = 0;
1401 for (x = input_w;
x < max_x;
x++)
1403 for (c = 0; c < channels; c++)
1404 decode_buffer[x * channels + c] = 0;
1409static float* stbir__get_ring_buffer_entry(
float* ring_buffer,
int index,
int ring_buffer_length)
1411 return &ring_buffer[
index * ring_buffer_length];
1414static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info,
int n)
1416 int ring_buffer_index;
1419 if (stbir_info->ring_buffer_begin_index < 0)
1421 ring_buffer_index = stbir_info->ring_buffer_begin_index = 0;
1422 stbir_info->ring_buffer_first_scanline = n;
1426 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;
1427 STBIR__DEBUG_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
1430 ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes /
sizeof(
float));
1431 memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes);
1433 stbir_info->ring_buffer_last_scanline = n;
1439static void stbir__resample_horizontal_upsample(stbir__info* stbir_info,
int n,
float* output_buffer)
1442 int output_w = stbir_info->output_w;
1443 int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width;
1444 int channels = stbir_info->channels;
1445 float* decode_buffer = stbir__get_decode_buffer(stbir_info);
1446 stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
1447 float* horizontal_coefficients = stbir_info->horizontal_coefficients;
1448 int coefficient_width = stbir_info->horizontal_coefficient_width;
1450 for (x = 0;
x < output_w;
x++)
1452 int n0 = horizontal_contributors[
x].n0;
1453 int n1 = horizontal_contributors[
x].n1;
1455 int out_pixel_index =
x * channels;
1456 int coefficient_group = coefficient_width *
x;
1457 int coefficient_counter = 0;
1459 STBIR__DEBUG_ASSERT(n1 >= n0);
1460 STBIR__DEBUG_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);
1461 STBIR__DEBUG_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);
1462 STBIR__DEBUG_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
1463 STBIR__DEBUG_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
1467 for (k = n0; k <= n1; k++)
1469 int in_pixel_index = k * 1;
1470 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1471 STBIR__DEBUG_ASSERT(coefficient != 0);
1472 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1476 for (k = n0; k <= n1; k++)
1478 int in_pixel_index = k * 2;
1479 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1480 STBIR__DEBUG_ASSERT(coefficient != 0);
1481 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1482 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1486 for (k = n0; k <= n1; k++)
1488 int in_pixel_index = k * 3;
1489 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1490 STBIR__DEBUG_ASSERT(coefficient != 0);
1491 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1492 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1493 output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
1497 for (k = n0; k <= n1; k++)
1499 int in_pixel_index = k * 4;
1500 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1501 STBIR__DEBUG_ASSERT(coefficient != 0);
1502 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1503 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1504 output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
1505 output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
1509 for (k = n0; k <= n1; k++)
1511 int in_pixel_index = k * channels;
1512 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1514 STBIR__DEBUG_ASSERT(coefficient != 0);
1515 for (c = 0; c < channels; c++)
1516 output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
1523static void stbir__resample_horizontal_downsample(stbir__info* stbir_info,
int n,
float* output_buffer)
1526 int input_w = stbir_info->input_w;
1527 int output_w = stbir_info->output_w;
1528 int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width;
1529 int channels = stbir_info->channels;
1530 float* decode_buffer = stbir__get_decode_buffer(stbir_info);
1531 stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
1532 float* horizontal_coefficients = stbir_info->horizontal_coefficients;
1533 int coefficient_width = stbir_info->horizontal_coefficient_width;
1534 int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin;
1535 int max_x = input_w + filter_pixel_margin * 2;
1537 STBIR__DEBUG_ASSERT(!stbir__use_width_upsampling(stbir_info));
1541 for (x = 0;
x < max_x;
x++)
1543 int n0 = horizontal_contributors[
x].n0;
1544 int n1 = horizontal_contributors[
x].n1;
1546 int in_x =
x - filter_pixel_margin;
1547 int in_pixel_index = in_x * 1;
1549 int coefficient_group = coefficient_width *
x;
1551 for (k = n0; k <= max_n; k++)
1553 int out_pixel_index = k * 1;
1554 float coefficient = horizontal_coefficients[coefficient_group + k - n0];
1555 STBIR__DEBUG_ASSERT(coefficient != 0);
1556 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1562 for (x = 0;
x < max_x;
x++)
1564 int n0 = horizontal_contributors[
x].n0;
1565 int n1 = horizontal_contributors[
x].n1;
1567 int in_x =
x - filter_pixel_margin;
1568 int in_pixel_index = in_x * 2;
1570 int coefficient_group = coefficient_width *
x;
1572 for (k = n0; k <= max_n; k++)
1574 int out_pixel_index = k * 2;
1575 float coefficient = horizontal_coefficients[coefficient_group + k - n0];
1576 STBIR__DEBUG_ASSERT(coefficient != 0);
1577 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1578 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1584 for (x = 0;
x < max_x;
x++)
1586 int n0 = horizontal_contributors[
x].n0;
1587 int n1 = horizontal_contributors[
x].n1;
1589 int in_x =
x - filter_pixel_margin;
1590 int in_pixel_index = in_x * 3;
1592 int coefficient_group = coefficient_width *
x;
1594 for (k = n0; k <= max_n; k++)
1596 int out_pixel_index = k * 3;
1597 float coefficient = horizontal_coefficients[coefficient_group + k - n0];
1598 STBIR__DEBUG_ASSERT(coefficient != 0);
1599 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1600 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1601 output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
1607 for (x = 0;
x < max_x;
x++)
1609 int n0 = horizontal_contributors[
x].n0;
1610 int n1 = horizontal_contributors[
x].n1;
1612 int in_x =
x - filter_pixel_margin;
1613 int in_pixel_index = in_x * 4;
1615 int coefficient_group = coefficient_width *
x;
1617 for (k = n0; k <= max_n; k++)
1619 int out_pixel_index = k * 4;
1620 float coefficient = horizontal_coefficients[coefficient_group + k - n0];
1621 STBIR__DEBUG_ASSERT(coefficient != 0);
1622 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1623 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1624 output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
1625 output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
1631 for (x = 0;
x < max_x;
x++)
1633 int n0 = horizontal_contributors[
x].n0;
1634 int n1 = horizontal_contributors[
x].n1;
1636 int in_x =
x - filter_pixel_margin;
1637 int in_pixel_index = in_x * channels;
1639 int coefficient_group = coefficient_width *
x;
1641 for (k = n0; k <= max_n; k++)
1644 int out_pixel_index = k * channels;
1645 float coefficient = horizontal_coefficients[coefficient_group + k - n0];
1646 STBIR__DEBUG_ASSERT(coefficient != 0);
1647 for (c = 0; c < channels; c++)
1648 output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
1655static void stbir__decode_and_resample_upsample(stbir__info* stbir_info,
int n)
1658 stbir__decode_scanline(stbir_info, n);
1661 if (stbir__use_width_upsampling(stbir_info))
1662 stbir__resample_horizontal_upsample(stbir_info, n, stbir__add_empty_ring_buffer_entry(stbir_info, n));
1664 stbir__resample_horizontal_downsample(stbir_info, n, stbir__add_empty_ring_buffer_entry(stbir_info, n));
1669static void stbir__decode_and_resample_downsample(stbir__info* stbir_info,
int n)
1672 stbir__decode_scanline(stbir_info, n);
1674 memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels *
sizeof(
float));
1677 if (stbir__use_width_upsampling(stbir_info))
1678 stbir__resample_horizontal_upsample(stbir_info, n, stbir_info->horizontal_buffer);
1680 stbir__resample_horizontal_downsample(stbir_info, n, stbir_info->horizontal_buffer);
1686static float* stbir__get_ring_buffer_scanline(
int get_scanline,
float* ring_buffer,
int begin_index,
int first_scanline,
int ring_buffer_size,
int ring_buffer_length)
1688 int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_size;
1689 return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length);
1693static void stbir__encode_scanline(stbir__info* stbir_info,
int num_pixels,
void* output_buffer,
float* encode_buffer,
int channels,
int alpha_channel,
int decode)
1702 for (x = 0;
x < num_pixels; ++
x)
1704 int pixel_index =
x * channels;
1706 float alpha = encode_buffer[pixel_index + alpha_channel];
1707 float reciprocal_alpha = alpha ? 1.0f / alpha : 0;
1710 for (n = 0; n < channels; n++)
1711 if (n != alpha_channel)
1712 encode_buffer[pixel_index + n] *= reciprocal_alpha;
1723 for (x = 0, num_nonalpha = 0;
x < channels; ++
x)
1725 nonalpha[num_nonalpha++] =
x;
1727#define STBIR__ROUND_INT(f) ((int) ((f)+0.5))
1728#define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5))
1730#ifdef STBIR__SATURATE_INT
1731#define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * 255 ))
1732#define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * 65535))
1734#define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * 255 )
1735#define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * 65535)
1741 for (
x = 0;
x < num_pixels; ++
x)
1743 int pixel_index =
x * channels;
1745 for (n = 0; n < channels; n++)
1747 int index = pixel_index + n;
1748 ((
unsigned char*)output_buffer)[
index] = STBIR__ENCODE_LINEAR8(encode_buffer[
index]);
1754 for (
x = 0;
x < num_pixels; ++
x)
1756 int pixel_index =
x * channels;
1758 for (n = 0; n < num_nonalpha; n++)
1760 int index = pixel_index + nonalpha[n];
1761 ((
unsigned char*)output_buffer)[
index] = stbir__linear_to_srgb_uchar(encode_buffer[
index]);
1765 ((
unsigned char*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index + alpha_channel]);
1770 for (
x = 0;
x < num_pixels; ++
x)
1772 int pixel_index =
x * channels;
1774 for (n = 0; n < channels; n++)
1776 int index = pixel_index + n;
1777 ((
unsigned short*)output_buffer)[
index] = STBIR__ENCODE_LINEAR16(encode_buffer[
index]);
1783 for (
x = 0;
x < num_pixels; ++
x)
1785 int pixel_index =
x * channels;
1787 for (n = 0; n < num_nonalpha; n++)
1789 int index = pixel_index + nonalpha[n];
1790 ((
unsigned short*)output_buffer)[
index] = (
unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[
index])) * 65535);
1794 ((
unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]);
1800 for (
x = 0;
x < num_pixels; ++
x)
1802 int pixel_index =
x * channels;
1804 for (n = 0; n < channels; n++)
1806 int index = pixel_index + n;
1807 ((
unsigned int*)output_buffer)[
index] = (
unsigned int)STBIR__ROUND_UINT(((
double)stbir__saturate(encode_buffer[
index])) * 4294967295);
1813 for (
x = 0;
x < num_pixels; ++
x)
1815 int pixel_index =
x * channels;
1817 for (n = 0; n < num_nonalpha; n++)
1819 int index = pixel_index + nonalpha[n];
1820 ((
unsigned int*)output_buffer)[
index] = (
unsigned int)STBIR__ROUND_UINT(((
double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[
index]))) * 4294967295);
1824 ((
unsigned int*)output_buffer)[pixel_index + alpha_channel] = (
unsigned int)STBIR__ROUND_INT(((
double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * 4294967295);
1829 for (
x = 0;
x < num_pixels; ++
x)
1831 int pixel_index =
x * channels;
1833 for (n = 0; n < channels; n++)
1835 int index = pixel_index + n;
1836 ((
float*)output_buffer)[
index] = encode_buffer[
index];
1842 for (
x = 0;
x < num_pixels; ++
x)
1844 int pixel_index =
x * channels;
1846 for (n = 0; n < num_nonalpha; n++)
1848 int index = pixel_index + nonalpha[n];
1849 ((
float*)output_buffer)[
index] = stbir__linear_to_srgb(encode_buffer[
index]);
1853 ((
float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel];
1858 STBIR__UNIMPLEMENTED(
"Unknown type/colorspace/channels combination.");
1863static void stbir__resample_vertical_upsample(stbir__info* stbir_info,
int n,
int in_first_scanline,
int in_last_scanline,
float in_center_of_out)
1866 int output_w = stbir_info->output_w;
1867 stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
1868 float* vertical_coefficients = stbir_info->vertical_coefficients;
1869 int channels = stbir_info->channels;
1870 int alpha_channel = stbir_info->alpha_channel;
1871 int type = stbir_info->type;
1872 int colorspace = stbir_info->colorspace;
1873 int kernel_pixel_width = stbir_info->vertical_filter_pixel_width;
1874 void* output_data = stbir_info->output_data;
1875 float* encode_buffer = stbir_info->encode_buffer;
1876 int decode = STBIR__DECODE(type, colorspace);
1877 int coefficient_width = stbir_info->vertical_coefficient_width;
1878 int coefficient_counter;
1879 int contributor = n;
1881 float* ring_buffer = stbir_info->ring_buffer;
1882 int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
1883 int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
1884 int ring_buffer_last_scanline = stbir_info->ring_buffer_last_scanline;
1885 int ring_buffer_length = stbir_info->ring_buffer_length_bytes /
sizeof(float);
1887 int n0, n1, output_row_start;
1888 int coefficient_group = coefficient_width * contributor;
1890 n0 = vertical_contributors[contributor].n0;
1891 n1 = vertical_contributors[contributor].n1;
1893 output_row_start = n * stbir_info->output_stride_bytes;
1895 STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info));
1897 memset(encode_buffer, 0, output_w *
sizeof(
float) * channels);
1902 coefficient_counter = 0;
1905 for (k = n0; k <= n1; k++)
1907 int coefficient_index = coefficient_counter++;
1908 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);
1909 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1910 for (x = 0;
x < output_w; ++
x)
1912 int in_pixel_index =
x * 1;
1913 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1918 for (k = n0; k <= n1; k++)
1920 int coefficient_index = coefficient_counter++;
1921 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);
1922 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1923 for (x = 0;
x < output_w; ++
x)
1925 int in_pixel_index =
x * 2;
1926 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1927 encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
1932 for (k = n0; k <= n1; k++)
1934 int coefficient_index = coefficient_counter++;
1935 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);
1936 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1937 for (x = 0;
x < output_w; ++
x)
1939 int in_pixel_index =
x * 3;
1940 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1941 encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
1942 encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
1947 for (k = n0; k <= n1; k++)
1949 int coefficient_index = coefficient_counter++;
1950 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);
1951 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1952 for (x = 0;
x < output_w; ++
x)
1954 int in_pixel_index =
x * 4;
1955 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1956 encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
1957 encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
1958 encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient;
1963 for (k = n0; k <= n1; k++)
1965 int coefficient_index = coefficient_counter++;
1966 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);
1967 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1968 for (x = 0;
x < output_w; ++
x)
1970 int in_pixel_index =
x * channels;
1972 for (c = 0; c < channels; c++)
1973 encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;
1978 stbir__encode_scanline(stbir_info, output_w, (
char*)output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);
1981static void stbir__resample_vertical_downsample(stbir__info* stbir_info,
int n,
int in_first_scanline,
int in_last_scanline,
float in_center_of_out)
1984 int output_w = stbir_info->output_w;
1985 int output_h = stbir_info->output_h;
1986 stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
1987 float* vertical_coefficients = stbir_info->vertical_coefficients;
1988 int channels = stbir_info->channels;
1989 int kernel_pixel_width = stbir_info->vertical_filter_pixel_width;
1990 void* output_data = stbir_info->output_data;
1991 float* horizontal_buffer = stbir_info->horizontal_buffer;
1992 int coefficient_width = stbir_info->vertical_coefficient_width;
1993 int contributor = n + stbir_info->vertical_filter_pixel_margin;
1995 float* ring_buffer = stbir_info->ring_buffer;
1996 int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
1997 int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
1998 int ring_buffer_last_scanline = stbir_info->ring_buffer_last_scanline;
1999 int ring_buffer_length = stbir_info->ring_buffer_length_bytes /
sizeof(float);
2002 n0 = vertical_contributors[contributor].n0;
2003 n1 = vertical_contributors[contributor].n1;
2005 STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info));
2007 for (k = n0; k <= n1; k++)
2009 int coefficient_index = k - n0;
2010 int coefficient_group = coefficient_width * contributor;
2011 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
2013 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);
2017 for (x = 0;
x < output_w;
x++)
2019 int in_pixel_index =
x * 1;
2020 ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
2024 for (x = 0;
x < output_w;
x++)
2026 int in_pixel_index =
x * 2;
2027 ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
2028 ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
2032 for (x = 0;
x < output_w;
x++)
2034 int in_pixel_index =
x * 3;
2035 ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
2036 ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
2037 ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
2041 for (x = 0;
x < output_w;
x++)
2043 int in_pixel_index =
x * 4;
2044 ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient;
2045 ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient;
2046 ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient;
2047 ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient;
2051 for (x = 0;
x < output_w;
x++)
2053 int in_pixel_index =
x * channels;
2056 for (c = 0; c < channels; c++)
2057 ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient;
2064static void stbir__buffer_loop_upsample(stbir__info* stbir_info)
2067 float scale_ratio = stbir_info->vertical_scale;
2068 float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1 / scale_ratio) * scale_ratio;
2070 STBIR__DEBUG_ASSERT(stbir__use_height_upsampling(stbir_info));
2072 for (y = 0; y < stbir_info->output_h; y++)
2074 float in_center_of_out = 0;
2075 int in_first_scanline = 0, in_last_scanline = 0;
2077 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);
2079 STBIR__DEBUG_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width);
2081 if (stbir_info->ring_buffer_begin_index >= 0)
2084 while (in_first_scanline > stbir_info->ring_buffer_first_scanline)
2086 if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)
2090 stbir_info->ring_buffer_begin_index = -1;
2091 stbir_info->ring_buffer_first_scanline = 0;
2092 stbir_info->ring_buffer_last_scanline = 0;
2097 stbir_info->ring_buffer_first_scanline++;
2098 stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width;
2104 if (stbir_info->ring_buffer_begin_index < 0)
2105 stbir__decode_and_resample_upsample(stbir_info, in_first_scanline);
2107 while (in_last_scanline > stbir_info->ring_buffer_last_scanline)
2108 stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1);
2111 stbir__resample_vertical_upsample(stbir_info, y, in_first_scanline, in_last_scanline, in_center_of_out);
2113 STBIR_PROGRESS_REPORT((
float)y / stbir_info->output_h);
2117static void stbir__empty_ring_buffer(stbir__info* stbir_info,
int first_necessary_scanline)
2119 int output_stride_bytes = stbir_info->output_stride_bytes;
2120 int channels = stbir_info->channels;
2121 int alpha_channel = stbir_info->alpha_channel;
2122 int type = stbir_info->type;
2123 int colorspace = stbir_info->colorspace;
2124 int output_w = stbir_info->output_w;
2125 void* output_data = stbir_info->output_data;
2126 int decode = STBIR__DECODE(type, colorspace);
2128 float* ring_buffer = stbir_info->ring_buffer;
2129 int ring_buffer_length = stbir_info->ring_buffer_length_bytes /
sizeof(float);
2131 if (stbir_info->ring_buffer_begin_index >= 0)
2134 while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline)
2136 if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h)
2138 int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes;
2139 float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length);
2140 stbir__encode_scanline(stbir_info, output_w, (
char*)output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode);
2141 STBIR_PROGRESS_REPORT((
float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h);
2144 if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline)
2148 stbir_info->ring_buffer_begin_index = -1;
2149 stbir_info->ring_buffer_first_scanline = 0;
2150 stbir_info->ring_buffer_last_scanline = 0;
2155 stbir_info->ring_buffer_first_scanline++;
2156 stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width;
2162static void stbir__buffer_loop_downsample(stbir__info* stbir_info)
2165 float scale_ratio = stbir_info->vertical_scale;
2166 int output_h = stbir_info->output_h;
2167 float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio;
2168 int pixel_margin = stbir_info->vertical_filter_pixel_margin;
2169 int max_y = stbir_info->input_h + pixel_margin;
2171 STBIR__DEBUG_ASSERT(!stbir__use_height_upsampling(stbir_info));
2173 for (y = -pixel_margin; y < max_y; y++)
2175 float out_center_of_in;
2176 int out_first_scanline, out_last_scanline;
2178 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);
2180 STBIR__DEBUG_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width);
2182 if (out_last_scanline < 0 || out_first_scanline >= output_h)
2185 stbir__empty_ring_buffer(stbir_info, out_first_scanline);
2187 stbir__decode_and_resample_downsample(stbir_info, y);
2190 if (stbir_info->ring_buffer_begin_index < 0)
2191 stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline);
2193 while (out_last_scanline > stbir_info->ring_buffer_last_scanline)
2194 stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1);
2197 stbir__resample_vertical_downsample(stbir_info, y, out_first_scanline, out_last_scanline, out_center_of_in);
2200 stbir__empty_ring_buffer(stbir_info, stbir_info->output_h);
2203static void stbir__setup(stbir__info* info,
int input_w,
int input_h,
int output_w,
int output_h,
int channels)
2205 info->input_w = input_w;
2206 info->input_h = input_h;
2207 info->output_w = output_w;
2208 info->output_h = output_h;
2209 info->channels = channels;
2212static void stbir__calculate_transform(stbir__info* info,
float s0,
float t0,
float s1,
float t1,
float* transform)
2221 info->horizontal_scale = transform[0];
2222 info->vertical_scale = transform[1];
2223 info->horizontal_shift = transform[2];
2224 info->vertical_shift = transform[3];
2228 info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0);
2229 info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0);
2231 info->horizontal_shift = s0 * info->input_w / (s1 - s0);
2232 info->vertical_shift = t0 * info->input_h / (t1 - t0);
2239 h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;
2241 v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE;
2242 info->horizontal_filter = h_filter;
2243 info->vertical_filter = v_filter;
2246static stbir_uint32 stbir__calculate_memory(stbir__info* info)
2248 int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
2249 int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);
2251 info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w);
2252 info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale, info->vertical_filter, info->input_h, info->output_h);
2254 info->horizontal_contributors_size = info->horizontal_num_contributors *
sizeof(stbir__contributors);
2255 info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) *
sizeof(float);
2256 info->vertical_contributors_size = info->vertical_num_contributors *
sizeof(stbir__contributors);
2257 info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) *
sizeof(float);
2258 info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels *
sizeof(
float);
2259 info->horizontal_buffer_size = info->output_w * info->channels *
sizeof(float);
2260 info->ring_buffer_size = info->output_w * info->channels * filter_height *
sizeof(float);
2261 info->encode_buffer_size = info->output_w * info->channels *
sizeof(float);
2263 STBIR_ASSERT(info->horizontal_filter != 0);
2264 STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2265 STBIR_ASSERT(info->vertical_filter != 0);
2266 STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2268 if (stbir__use_height_upsampling(info))
2272 info->horizontal_buffer_size = 0;
2276 info->encode_buffer_size = 0;
2278 return info->horizontal_contributors_size + info->horizontal_coefficients_size
2279 + info->vertical_contributors_size + info->vertical_coefficients_size
2280 + info->decode_buffer_size + info->horizontal_buffer_size
2281 + info->ring_buffer_size + info->encode_buffer_size;
2284static int stbir__resize_allocated(stbir__info* info,
2285 const void* input_data,
int input_stride_in_bytes,
2286 void* output_data,
int output_stride_in_bytes,
2289 void* tempmem,
size_t tempmem_size_in_bytes)
2291 size_t memory_required = stbir__calculate_memory(info);
2293 int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type];
2294 int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type];
2296#ifdef STBIR_DEBUG_OVERWRITE_TEST
2297#define OVERWRITE_ARRAY_SIZE 8
2298 unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE];
2299 unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE];
2300 unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE];
2301 unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE];
2303 size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type];
2304 memcpy(overwrite_output_before_pre, &((
unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
2305 memcpy(overwrite_output_after_pre, &((
unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE);
2306 memcpy(overwrite_tempmem_before_pre, &((
unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
2307 memcpy(overwrite_tempmem_after_pre, &((
unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE);
2310 STBIR_ASSERT(info->channels >= 0);
2311 STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS);
2313 if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS)
2316 STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2317 STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2319 if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
2321 if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
2324 if (alpha_channel < 0)
2328 STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels);
2330 if (alpha_channel >= info->channels)
2333 STBIR_ASSERT(tempmem);
2338 STBIR_ASSERT(tempmem_size_in_bytes >= memory_required);
2340 if (tempmem_size_in_bytes < memory_required)
2343 memset(tempmem, 0, tempmem_size_in_bytes);
2345 info->input_data = input_data;
2346 info->input_stride_bytes = width_stride_input;
2348 info->output_data = output_data;
2349 info->output_stride_bytes = width_stride_output;
2351 info->alpha_channel = alpha_channel;
2352 info->flags = flags;
2354 info->edge_horizontal = edge_horizontal;
2355 info->edge_vertical = edge_vertical;
2356 info->colorspace = colorspace;
2358 info->horizontal_coefficient_width = stbir__get_coefficient_width(info->horizontal_filter, info->horizontal_scale);
2359 info->vertical_coefficient_width = stbir__get_coefficient_width(info->vertical_filter, info->vertical_scale);
2360 info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width(info->horizontal_filter, info->horizontal_scale);
2361 info->vertical_filter_pixel_width = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale);
2362 info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
2363 info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter, info->vertical_scale);
2365 info->ring_buffer_length_bytes = info->output_w * info->channels *
sizeof(float);
2366 info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2;
2368#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)
2370 info->horizontal_contributors = (stbir__contributors*)tempmem;
2371 info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors,
float);
2372 info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors);
2373 info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors,
float);
2374 info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients,
float);
2376 if (stbir__use_height_upsampling(info))
2378 info->horizontal_buffer =
NULL;
2379 info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer,
float);
2380 info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer,
float);
2382 STBIR__DEBUG_ASSERT((
size_t)STBIR__NEXT_MEMPTR(info->encode_buffer,
unsigned char) == (
size_t)tempmem + tempmem_size_in_bytes);
2386 info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer,
float);
2387 info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer,
float);
2388 info->encode_buffer =
NULL;
2390 STBIR__DEBUG_ASSERT((
size_t)STBIR__NEXT_MEMPTR(info->ring_buffer,
unsigned char) == (
size_t)tempmem + tempmem_size_in_bytes);
2393#undef STBIR__NEXT_MEMPTR
2396 info->ring_buffer_begin_index = -1;
2398 stbir__calculate_filters(info, info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w);
2399 stbir__calculate_filters(info, info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h);
2401 STBIR_PROGRESS_REPORT(0);
2403 if (stbir__use_height_upsampling(info))
2404 stbir__buffer_loop_upsample(info);
2406 stbir__buffer_loop_downsample(info);
2408 STBIR_PROGRESS_REPORT(1);
2410#ifdef STBIR_DEBUG_OVERWRITE_TEST
2411 STBIR__DEBUG_ASSERT(
memcmp(overwrite_output_before_pre, &((
unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
2412 STBIR__DEBUG_ASSERT(
memcmp(overwrite_output_after_pre, &((
unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0);
2413 STBIR__DEBUG_ASSERT(
memcmp(overwrite_tempmem_before_pre, &((
unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
2414 STBIR__DEBUG_ASSERT(
memcmp(overwrite_tempmem_after_pre, &((
unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0);
2421static int stbir__resize_arbitrary(
2422 void* alloc_context,
2423 const void* input_data,
int input_w,
int input_h,
int input_stride_in_bytes,
2424 void* output_data,
int output_w,
int output_h,
int output_stride_in_bytes,
2425 float s0,
float t0,
float s1,
float t1,
float* transform,
2432 size_t memory_required;
2435 stbir__setup(&info, input_w, input_h, output_w, output_h, channels);
2436 stbir__calculate_transform(&info, s0, t0, s1, t1, transform);
2437 stbir__choose_filter(&info, h_filter, v_filter);
2438 memory_required = stbir__calculate_memory(&info);
2439 extra_memory = STBIR_MALLOC(memory_required, alloc_context);
2444 result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes,
2445 output_data, output_stride_in_bytes,
2446 alpha_channel, flags, type,
2447 edge_horizontal, edge_vertical,
2448 colorspace, extra_memory, memory_required);
2450 STBIR_FREE(extra_memory, alloc_context);
2456 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2459 return stbir__resize_arbitrary(
NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2460 output_pixels, output_w, output_h, output_stride_in_bytes,
2461 0, 0, 1, 1,
NULL, num_channels, -1, 0,
STBIR_TYPE_UINT8,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2466 float* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2469 return stbir__resize_arbitrary(
NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2470 output_pixels, output_w, output_h, output_stride_in_bytes,
2471 0, 0, 1, 1,
NULL, num_channels, -1, 0,
STBIR_TYPE_FLOAT,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2476 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2477 int num_channels,
int alpha_channel,
int flags)
2479 return stbir__resize_arbitrary(
NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2480 output_pixels, output_w, output_h, output_stride_in_bytes,
2481 0, 0, 1, 1,
NULL, num_channels, alpha_channel, flags,
STBIR_TYPE_UINT8,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2486 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2487 int num_channels,
int alpha_channel,
int flags,
2490 return stbir__resize_arbitrary(
NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2491 output_pixels, output_w, output_h, output_stride_in_bytes,
2492 0, 0, 1, 1,
NULL, num_channels, alpha_channel, flags,
STBIR_TYPE_UINT8,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2497 unsigned char* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2498 int num_channels,
int alpha_channel,
int flags,
2500 void* alloc_context)
2502 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2503 output_pixels, output_w, output_h, output_stride_in_bytes,
2504 0, 0, 1, 1,
NULL, num_channels, alpha_channel, flags,
STBIR_TYPE_UINT8, filter, filter,
2505 edge_wrap_mode, edge_wrap_mode, space);
2509 stbir_uint16* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2510 int num_channels,
int alpha_channel,
int flags,
2512 void* alloc_context)
2514 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2515 output_pixels, output_w, output_h, output_stride_in_bytes,
2516 0, 0, 1, 1,
NULL, num_channels, alpha_channel, flags,
STBIR_TYPE_UINT16, filter, filter,
2517 edge_wrap_mode, edge_wrap_mode, space);
2522 float* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2523 int num_channels,
int alpha_channel,
int flags,
2525 void* alloc_context)
2527 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2528 output_pixels, output_w, output_h, output_stride_in_bytes,
2529 0, 0, 1, 1,
NULL, num_channels, alpha_channel, flags,
STBIR_TYPE_FLOAT, filter, filter,
2530 edge_wrap_mode, edge_wrap_mode, space);
2534STBIRDEF int stbir_resize(
const void* input_pixels,
int input_w,
int input_h,
int input_stride_in_bytes,
2535 void* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2537 int num_channels,
int alpha_channel,
int flags,
2542 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2543 output_pixels, output_w, output_h, output_stride_in_bytes,
2544 0, 0, 1, 1,
NULL, num_channels, alpha_channel, flags, datatype, filter_horizontal, filter_vertical,
2545 edge_mode_horizontal, edge_mode_vertical, space);
2550 void* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2552 int num_channels,
int alpha_channel,
int flags,
2556 float x_scale,
float y_scale,
2557 float x_offset,
float y_offset)
2560 transform[0] = x_scale;
2561 transform[1] = y_scale;
2562 transform[2] = x_offset;
2563 transform[3] = y_offset;
2564 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2565 output_pixels, output_w, output_h, output_stride_in_bytes,
2566 0, 0, 1, 1, transform, num_channels, alpha_channel, flags, datatype, filter_horizontal, filter_vertical,
2567 edge_mode_horizontal, edge_mode_vertical, space);
2571 void* output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2573 int num_channels,
int alpha_channel,
int flags,
2577 float s0,
float t0,
float s1,
float t1)
2579 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2580 output_pixels, output_w, output_h, output_stride_in_bytes,
2581 s0, t0, s1, t1,
NULL, num_channels, alpha_channel, flags, datatype, filter_horizontal, filter_vertical,
2582 edge_mode_horizontal, edge_mode_vertical, space);
#define index(str, chr)
Definition string.h:66
XETime t
Definition main.cpp:53
void * memcpy(void *Dest, const void *Src, ACPI_SIZE Count)
Definition utclib.c:310
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition utclib.c:222
void * memset(void *Dest, int Value, ACPI_SIZE Count)
Definition utclib.c:346
unsigned int uint32_t
Definition acefiex.h:163
unsigned char uint8_t
Definition acefiex.h:161
unsigned short int uint16_t
Definition acefiex.h:162
#define NULL
Definition actypes.h:561
XE_LIB double pow(double, double)
Definition math.cpp:173
XE_LIB double floor(double)
Definition math.cpp:134
XE_LIB double fabs(double)
Definition math.cpp:120
XE_LIB double ceil(double)
Definition math.cpp:42
STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels, int input_w, int input_h, int input_stride_in_bytes, stbir_uint16 *output_pixels, int output_w, int output_h, int output_stride_in_bytes, int num_channels, int alpha_channel, int flags, stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, void *alloc_context)
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, stbir_datatype datatype, int num_channels, int alpha_channel, int flags, stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, stbir_filter filter_horizontal, stbir_filter filter_vertical, stbir_colorspace space, void *alloc_context, float s0, float t0, float s1, float t1)
STBIRDEF int stbir_resize_float_generic(const float *input_pixels, int input_w, int input_h, int input_stride_in_bytes, float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, int num_channels, int alpha_channel, int flags, stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, void *alloc_context)
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, int num_channels)
STBIRDEF int stbir_resize_uint8_srgb_edgemode(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, int num_channels, int alpha_channel, int flags, stbir_edge edge_wrap_mode)
stbir_filter
Definition stb_image_resize.h:279
@ STBIR_FILTER_DEFAULT
Definition stb_image_resize.h:280
@ STBIR_FILTER_MITCHELL
Definition stb_image_resize.h:285
@ STBIR_FILTER_BOX
Definition stb_image_resize.h:281
@ STBIR_FILTER_TRIANGLE
Definition stb_image_resize.h:282
@ STBIR_FILTER_CATMULLROM
Definition stb_image_resize.h:284
@ STBIR_FILTER_CUBICBSPLINE
Definition stb_image_resize.h:283
uint8_t stbir_uint8
Definition stb_image_resize.h:185
stbir_edge
Definition stb_image_resize.h:250
@ STBIR_EDGE_WRAP
Definition stb_image_resize.h:253
@ STBIR_EDGE_CLAMP
Definition stb_image_resize.h:251
@ STBIR_EDGE_ZERO
Definition stb_image_resize.h:254
@ STBIR_EDGE_REFLECT
Definition stb_image_resize.h:252
uint16_t stbir_uint16
Definition stb_image_resize.h:186
#define STBIR_FLAG_ALPHA_USES_COLORSPACE
Definition stb_image_resize.h:242
STBIRDEF int stbir_resize_uint8_generic(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, int num_channels, int alpha_channel, int flags, stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, void *alloc_context)
uint32_t stbir_uint32
Definition stb_image_resize.h:187
STBIRDEF int stbir_resize_uint8_srgb(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, int num_channels, int alpha_channel, int flags)
STBIRDEF int stbir_resize(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, stbir_datatype datatype, int num_channels, int alpha_channel, int flags, stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, stbir_filter filter_horizontal, stbir_filter filter_vertical, stbir_colorspace space, void *alloc_context)
#define STBIRDEF
Definition stb_image_resize.h:196
stbir_datatype
Definition stb_image_resize.h:332
@ STBIR_TYPE_UINT32
Definition stb_image_resize.h:335
@ STBIR_TYPE_UINT16
Definition stb_image_resize.h:334
@ STBIR_TYPE_UINT8
Definition stb_image_resize.h:333
@ STBIR_MAX_TYPES
Definition stb_image_resize.h:338
@ STBIR_TYPE_FLOAT
Definition stb_image_resize.h:336
STBIRDEF int stbir_resize_subpixel(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, stbir_datatype datatype, int num_channels, int alpha_channel, int flags, stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, stbir_filter filter_horizontal, stbir_filter filter_vertical, stbir_colorspace space, void *alloc_context, float x_scale, float y_scale, float x_offset, float y_offset)
#define STBIR_FLAG_ALPHA_PREMULTIPLIED
Definition stb_image_resize.h:239
STBIRDEF int stbir_resize_float(const float *input_pixels, int input_w, int input_h, int input_stride_in_bytes, float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, int num_channels)
stbir_colorspace
Definition stb_image_resize.h:289
@ STBIR_COLORSPACE_SRGB
Definition stb_image_resize.h:291
@ STBIR_MAX_COLORSPACES
Definition stb_image_resize.h:293
@ STBIR_COLORSPACE_LINEAR
Definition stb_image_resize.h:290
#define max(a, b)
Definition stdlib.h:44
int x
Definition term.cpp:49