184#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H
185#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H
199#ifdef STB_IMAGE_RESIZE_STATIC
200#define STBIRDEF static
203#define STBIRDEF extern "C"
205#define STBIRDEF extern
229 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
233 float *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
243#define STBIR_ALPHA_CHANNEL_NONE -1
248#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0)
251#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1)
254 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
255 int num_channels,
int alpha_channel,
int flags);
268 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
269 int num_channels,
int alpha_channel,
int flags,
308 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
309 int num_channels,
int alpha_channel,
int flags,
311 void *alloc_context);
314 stbir_uint16 *output_pixels ,
int output_w,
int output_h,
int output_stride_in_bytes,
315 int num_channels,
int alpha_channel,
int flags,
317 void *alloc_context);
320 float *output_pixels ,
int output_w,
int output_h,
int output_stride_in_bytes,
321 int num_channels,
int alpha_channel,
int flags,
323 void *alloc_context);
351 void *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
353 int num_channels,
int alpha_channel,
int flags,
359 void *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
361 int num_channels,
int alpha_channel,
int flags,
365 float x_scale,
float y_scale,
366 float x_offset,
float y_offset);
369 void *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
371 int num_channels,
int alpha_channel,
int flags,
375 float s0,
float t0,
float s1,
float t1);
387#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION
391#define STBIR_ASSERT(x) assert(x)
402#define STBIR_MALLOC(size,c) ((void)(c), malloc(size))
403#define STBIR_FREE(ptr,c) ((void)(c), free(ptr))
408#define stbir__inline inline
413#define stbir__inline __forceinline
418typedef unsigned char stbir__validate_uint32[
sizeof(
stbir_uint32) == 4 ? 1 : -1];
421#define STBIR__NOTUSED(v) (void)(v)
423#define STBIR__NOTUSED(v) (void)sizeof(v)
426#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))
428#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE
429#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM
432#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE
433#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL
436#ifndef STBIR_PROGRESS_REPORT
437#define STBIR_PROGRESS_REPORT(float_0_to_1)
440#ifndef STBIR_MAX_CHANNELS
441#define STBIR_MAX_CHANNELS 64
444#if STBIR_MAX_CHANNELS > 65536
445#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536."
454#ifndef STBIR_ALPHA_EPSILON
455#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20))
461#define STBIR__UNUSED_PARAM(v) (void)(v)
463#define STBIR__UNUSED_PARAM(v) (void)sizeof(v)
467static unsigned char stbir__type_size[] = {
475typedef float (stbir__kernel_fn)(
float x,
float scale);
476typedef float (stbir__support_fn)(
float scale);
480 stbir__kernel_fn* kernel;
481 stbir__support_fn* support;
490} stbir__contributors;
494 const void* input_data;
497 int input_stride_bytes;
502 int output_stride_bytes;
504 float s0, t0, s1, t1;
506 float horizontal_shift;
507 float vertical_shift;
508 float horizontal_scale;
509 float vertical_scale;
521 stbir__contributors* horizontal_contributors;
522 float* horizontal_coefficients;
524 stbir__contributors* vertical_contributors;
525 float* vertical_coefficients;
527 int decode_buffer_pixels;
528 float* decode_buffer;
530 float* horizontal_buffer;
533 int horizontal_coefficient_width;
534 int vertical_coefficient_width;
535 int horizontal_filter_pixel_width;
536 int vertical_filter_pixel_width;
537 int horizontal_filter_pixel_margin;
538 int vertical_filter_pixel_margin;
539 int horizontal_num_contributors;
540 int vertical_num_contributors;
542 int ring_buffer_length_bytes;
543 int ring_buffer_num_entries;
544 int ring_buffer_first_scanline;
545 int ring_buffer_last_scanline;
546 int ring_buffer_begin_index;
549 float* encode_buffer;
551 int horizontal_contributors_size;
552 int horizontal_coefficients_size;
553 int vertical_contributors_size;
554 int vertical_coefficients_size;
555 int decode_buffer_size;
556 int horizontal_buffer_size;
557 int ring_buffer_size;
558 int encode_buffer_size;
562static const float stbir__max_uint8_as_float = 255.0f;
563static const float stbir__max_uint16_as_float = 65535.0f;
564static const double stbir__max_uint32_as_float = 4294967295.0;
567static stbir__inline
int stbir__min(
int a,
int b)
569 return a <
b ? a :
b;
572static stbir__inline
float stbir__saturate(
float x)
583#ifdef STBIR_SATURATE_INT
584static stbir__inline
stbir_uint8 stbir__saturate8(
int x)
586 if ((
unsigned int) x <= 255)
595static stbir__inline
stbir_uint16 stbir__saturate16(
int x)
597 if ((
unsigned int) x <= 65535)
607static float stbir__srgb_uchar_to_linear_float[256] = {
608 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f,
609 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f,
610 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f,
611 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f,
612 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f,
613 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f,
614 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f,
615 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f,
616 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,
617 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f,
618 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f,
619 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f,
620 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f,
621 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f,
622 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f,
623 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f,
624 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f,
625 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,
626 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f,
627 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f,
628 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f,
629 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f,
630 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f,
631 0.982251f, 0.991102f, 1.0f
634static float stbir__srgb_to_linear(
float f)
639 return (
float)pow((f + 0.055f) / 1.055f, 2.4f);
642static float stbir__linear_to_srgb(
float f)
647 return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f;
650#ifndef STBIR_NON_IEEE_FLOAT
660 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,
661 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,
662 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,
663 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,
664 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,
665 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,
666 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,
667 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,
668 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,
669 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,
670 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,
671 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,
672 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,
675static stbir_uint8 stbir__linear_to_srgb_uchar(
float in)
677 static const stbir__FP32 almostone = { 0x3f7fffff };
678 static const stbir__FP32 minval = { (127-13) << 23 };
685 if (!(in > minval.f))
687 if (in > almostone.f)
692 tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20];
693 bias = (tab >> 16) << 9;
694 scale = tab & 0xffff;
697 t = (f.u >> 12) & 0xff;
698 return (
unsigned char) ((bias + scale*t) >> 16);
703static int stbir__srgb_offset_to_linear_scaled[256] =
705 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603,
706 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926,
707 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148,
708 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856,
709 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731,
710 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369,
711 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021,
712 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073,
713 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389,
714 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552,
715 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066,
716 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490,
717 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568,
718 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316,
719 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096,
720 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700,
721 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376,
722 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912,
723 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648,
724 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512,
725 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072,
726 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544,
727 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832,
728 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528,
729 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968,
730 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184,
731 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992,
732 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968,
733 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480,
734 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656,
735 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464,
736 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664,
739static stbir_uint8 stbir__linear_to_srgb_uchar(
float f)
741 int x = (int) (f * (1 << 28));
746 i = v + 128;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
747 i = v + 64;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
748 i = v + 32;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
749 i = v + 16;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
750 i = v + 8;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
751 i = v + 4;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
752 i = v + 2;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
753 i = v + 1;
if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i;
759static float stbir__filter_trapezoid(
float x,
float scale)
761 float halfscale = scale / 2;
762 float t = 0.5f + halfscale;
763 STBIR_ASSERT(scale <= 1);
771 float r = 0.5f - halfscale;
775 return (t - x) / scale;
779static float stbir__support_trapezoid(
float scale)
781 STBIR_ASSERT(scale <= 1);
782 return 0.5f + scale / 2;
785static float stbir__filter_triangle(
float x,
float s)
787 STBIR__UNUSED_PARAM(s);
797static float stbir__filter_cubic(
float x,
float s)
799 STBIR__UNUSED_PARAM(s);
804 return (4 + x*x*(3*x - 6))/6;
806 return (8 + x*(-12 + x*(6 - x)))/6;
811static float stbir__filter_catmullrom(
float x,
float s)
813 STBIR__UNUSED_PARAM(s);
818 return 1 - x*x*(2.5f - 1.5f*x);
820 return 2 - x*(4 + x*(0.5f*x - 2.5f));
825static float stbir__filter_mitchell(
float x,
float s)
827 STBIR__UNUSED_PARAM(s);
832 return (16 + x*x*(21 * x - 36))/18;
834 return (32 + x*(-60 + x*(36 - 7*x)))/18;
839static float stbir__support_zero(
float s)
841 STBIR__UNUSED_PARAM(s);
845static float stbir__support_one(
float s)
847 STBIR__UNUSED_PARAM(s);
851static float stbir__support_two(
float s)
853 STBIR__UNUSED_PARAM(s);
857static stbir__filter_info stbir__filter_info_table[] = {
858 { NULL, stbir__support_zero },
859 { stbir__filter_trapezoid, stbir__support_trapezoid },
860 { stbir__filter_triangle, stbir__support_one },
861 { stbir__filter_cubic, stbir__support_two },
862 { stbir__filter_catmullrom, stbir__support_two },
863 { stbir__filter_mitchell, stbir__support_two },
866stbir__inline
static int stbir__use_upsampling(
float ratio)
871stbir__inline
static int stbir__use_width_upsampling(stbir__info* stbir_info)
873 return stbir__use_upsampling(stbir_info->horizontal_scale);
876stbir__inline
static int stbir__use_height_upsampling(stbir__info* stbir_info)
878 return stbir__use_upsampling(stbir_info->vertical_scale);
883static int stbir__get_filter_pixel_width(
stbir_filter filter,
float scale)
885 STBIR_ASSERT(filter != 0);
886 STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
888 if (stbir__use_upsampling(scale))
889 return (
int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2);
891 return (
int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale);
896static int stbir__get_filter_pixel_margin(
stbir_filter filter,
float scale)
898 return stbir__get_filter_pixel_width(filter, scale) / 2;
901static int stbir__get_coefficient_width(
stbir_filter filter,
float scale)
903 if (stbir__use_upsampling(scale))
904 return (
int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2);
906 return (
int)ceil(stbir__filter_info_table[filter].support(scale) * 2);
909static int stbir__get_contributors(
float scale,
stbir_filter filter,
int input_size,
int output_size)
911 if (stbir__use_upsampling(scale))
914 return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2);
917static int stbir__get_total_horizontal_coefficients(stbir__info* info)
919 return info->horizontal_num_contributors
920 * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);
923static int stbir__get_total_vertical_coefficients(stbir__info* info)
925 return info->vertical_num_contributors
926 * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale);
929static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors,
int n)
931 return &contributors[n];
936static float* stbir__get_coefficient(
float* coefficients,
stbir_filter filter,
float scale,
int n,
int c)
938 int width = stbir__get_coefficient_width(filter, scale);
939 return &coefficients[width*n + c];
942static int stbir__edge_wrap_slow(
stbir_edge edge,
int n,
int max)
995 STBIR_ASSERT(!
"Unimplemented edge type");
1000stbir__inline
static int stbir__edge_wrap(
stbir_edge edge,
int n,
int max)
1003 if (n >= 0 && n <
max)
1005 return stbir__edge_wrap_slow(edge, n,
max);
1009static 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)
1011 float out_pixel_center = (float)n + 0.5f;
1012 float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius;
1013 float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius;
1015 float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio;
1016 float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio;
1018 *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio;
1019 *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5));
1020 *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5));
1024static 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)
1026 float in_pixel_center = (float)n + 0.5f;
1027 float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius;
1028 float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius;
1030 float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift;
1031 float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift;
1033 *out_center_of_in = in_pixel_center * scale_ratio - out_shift;
1034 *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5));
1035 *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5));
1038static void stbir__calculate_coefficients_upsample(
stbir_filter filter,
float scale,
int in_first_pixel,
int in_last_pixel,
float in_center_of_out, stbir__contributors* contributor,
float* coefficient_group)
1041 float total_filter = 0;
1044 STBIR_ASSERT(in_last_pixel - in_first_pixel <= (
int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2));
1046 contributor->n0 = in_first_pixel;
1047 contributor->n1 = in_last_pixel;
1049 STBIR_ASSERT(contributor->n1 >= contributor->n0);
1051 for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
1053 float in_pixel_center = (float)(i + in_first_pixel) + 0.5f;
1054 coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale);
1057 if (i == 0 && !coefficient_group[i])
1059 contributor->n0 = ++in_first_pixel;
1064 total_filter += coefficient_group[i];
1067 STBIR_ASSERT(stbir__filter_info_table[filter].kernel((
float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0);
1069 STBIR_ASSERT(total_filter > 0.9);
1070 STBIR_ASSERT(total_filter < 1.1f);
1073 filter_scale = 1 / total_filter;
1075 for (i = 0; i <= in_last_pixel - in_first_pixel; i++)
1076 coefficient_group[i] *= filter_scale;
1078 for (i = in_last_pixel - in_first_pixel; i >= 0; i--)
1080 if (coefficient_group[i])
1084 contributor->n1 = contributor->n0 + i - 1;
1088static void stbir__calculate_coefficients_downsample(
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)
1092 STBIR_ASSERT(out_last_pixel - out_first_pixel <= (
int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2));
1094 contributor->n0 = out_first_pixel;
1095 contributor->n1 = out_last_pixel;
1097 STBIR_ASSERT(contributor->n1 >= contributor->n0);
1099 for (i = 0; i <= out_last_pixel - out_first_pixel; i++)
1101 float out_pixel_center = (float)(i + out_first_pixel) + 0.5f;
1102 float x = out_pixel_center - out_center_of_in;
1103 coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio;
1106 STBIR_ASSERT(stbir__filter_info_table[filter].kernel((
float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0);
1108 for (i = out_last_pixel - out_first_pixel; i >= 0; i--)
1110 if (coefficient_group[i])
1114 contributor->n1 = contributor->n0 + i - 1;
1118static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors,
float* coefficients,
stbir_filter filter,
float scale_ratio,
int input_size,
int output_size)
1120 int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
1121 int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio);
1125 for (i = 0; i < output_size; i++)
1130 for (j = 0; j < num_contributors; j++)
1132 if (i >= contributors[j].n0 && i <= contributors[j].n1)
1134 float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0);
1135 total += coefficient;
1137 else if (i < contributors[j].n0)
1141 STBIR_ASSERT(total > 0.9f);
1142 STBIR_ASSERT(total < 1.1f);
1146 for (j = 0; j < num_contributors; j++)
1148 if (i >= contributors[j].n0 && i <= contributors[j].n1)
1149 *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale;
1150 else if (i < contributors[j].n0)
1157 for (j = 0; j < num_contributors; j++)
1159 int range,
max, width;
1162 while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0)
1165 contributors[j].n0 += skip;
1167 while (contributors[j].n0 < 0)
1169 contributors[j].n0++;
1173 range = contributors[j].n1 - contributors[j].n0 + 1;
1174 max = stbir__min(num_coefficients, range);
1176 width = stbir__get_coefficient_width(filter, scale_ratio);
1177 for (i = 0; i <
max; i++)
1179 if (i + skip >= width)
1182 *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip);
1189 for (i = 0; i < num_contributors; i++)
1190 contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1);
1195static void stbir__calculate_filters(stbir__contributors* contributors,
float* coefficients,
stbir_filter filter,
float scale_ratio,
float shift,
int input_size,
int output_size)
1198 int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size);
1200 if (stbir__use_upsampling(scale_ratio))
1202 float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio;
1205 for (n = 0; n < total_contributors; n++)
1207 float in_center_of_out;
1208 int in_first_pixel, in_last_pixel;
1210 stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out);
1212 stbir__calculate_coefficients_upsample(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));
1217 float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio;
1220 for (n = 0; n < total_contributors; n++)
1222 float out_center_of_in;
1223 int out_first_pixel, out_last_pixel;
1224 int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio);
1226 stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in);
1228 stbir__calculate_coefficients_downsample(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));
1231 stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size);
1235static float* stbir__get_decode_buffer(stbir__info* stbir_info)
1239 return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels];
1242#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace))
1244static void stbir__decode_scanline(stbir__info* stbir_info,
int n)
1247 int channels = stbir_info->channels;
1248 int alpha_channel = stbir_info->alpha_channel;
1249 int type = stbir_info->type;
1250 int colorspace = stbir_info->colorspace;
1251 int input_w = stbir_info->input_w;
1252 size_t input_stride_bytes = stbir_info->input_stride_bytes;
1253 float* decode_buffer = stbir__get_decode_buffer(stbir_info);
1254 stbir_edge edge_horizontal = stbir_info->edge_horizontal;
1255 stbir_edge edge_vertical = stbir_info->edge_vertical;
1256 size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes;
1257 const void* input_data = (
char *) stbir_info->input_data + in_buffer_row_offset;
1258 int max_x = input_w + stbir_info->horizontal_filter_pixel_margin;
1259 int decode = STBIR__DECODE(type, colorspace);
1261 int x = -stbir_info->horizontal_filter_pixel_margin;
1265 if (edge_vertical ==
STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h))
1267 for (; x < max_x; x++)
1268 for (c = 0; c < channels; c++)
1269 decode_buffer[x*channels + c] = 0;
1276 for (; x < max_x; x++)
1278 int decode_pixel_index = x * channels;
1279 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1280 for (c = 0; c < channels; c++)
1281 decode_buffer[decode_pixel_index + c] = ((
float)((
const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float;
1286 for (; x < max_x; x++)
1288 int decode_pixel_index = x * channels;
1289 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1290 for (c = 0; c < channels; c++)
1291 decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((
const unsigned char*)input_data)[input_pixel_index + c]];
1294 decode_buffer[decode_pixel_index + alpha_channel] = ((float)((
const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float;
1299 for (; x < max_x; x++)
1301 int decode_pixel_index = x * channels;
1302 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1303 for (c = 0; c < channels; c++)
1304 decode_buffer[decode_pixel_index + c] = ((
float)((
const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float;
1309 for (; x < max_x; x++)
1311 int decode_pixel_index = x * channels;
1312 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1313 for (c = 0; c < channels; c++)
1314 decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((
float)((
const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float);
1317 decode_buffer[decode_pixel_index + alpha_channel] = ((float)((
const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float;
1322 for (; x < max_x; x++)
1324 int decode_pixel_index = x * channels;
1325 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1326 for (c = 0; c < channels; c++)
1327 decode_buffer[decode_pixel_index + c] = (
float)(((double)((
const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float);
1332 for (; x < max_x; x++)
1334 int decode_pixel_index = x * channels;
1335 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1336 for (c = 0; c < channels; c++)
1337 decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((
float)(((
double)((
const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float));
1340 decode_buffer[decode_pixel_index + alpha_channel] = (float)(((
double)((
const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float);
1345 for (; x < max_x; x++)
1347 int decode_pixel_index = x * channels;
1348 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1349 for (c = 0; c < channels; c++)
1350 decode_buffer[decode_pixel_index + c] = ((
const float*)input_data)[input_pixel_index + c];
1355 for (; x < max_x; x++)
1357 int decode_pixel_index = x * channels;
1358 int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels;
1359 for (c = 0; c < channels; c++)
1360 decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((
const float*)input_data)[input_pixel_index + c]);
1363 decode_buffer[decode_pixel_index + alpha_channel] = ((
const float*)input_data)[input_pixel_index + alpha_channel];
1369 STBIR_ASSERT(!
"Unknown type/colorspace/channels combination.");
1375 for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++)
1377 int decode_pixel_index = x * channels;
1380 float alpha = decode_buffer[decode_pixel_index + alpha_channel];
1381#ifndef STBIR_NO_ALPHA_EPSILON
1383 alpha += STBIR_ALPHA_EPSILON;
1384 decode_buffer[decode_pixel_index + alpha_channel] = alpha;
1387 for (c = 0; c < channels; c++)
1389 if (c == alpha_channel)
1392 decode_buffer[decode_pixel_index + c] *= alpha;
1399 for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++)
1401 for (c = 0; c < channels; c++)
1402 decode_buffer[x*channels + c] = 0;
1404 for (x = input_w; x < max_x; x++)
1406 for (c = 0; c < channels; c++)
1407 decode_buffer[x*channels + c] = 0;
1412static float* stbir__get_ring_buffer_entry(
float* ring_buffer,
int index,
int ring_buffer_length)
1414 return &ring_buffer[
index * ring_buffer_length];
1417static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info,
int n)
1419 int ring_buffer_index;
1422 stbir_info->ring_buffer_last_scanline = n;
1424 if (stbir_info->ring_buffer_begin_index < 0)
1426 ring_buffer_index = stbir_info->ring_buffer_begin_index = 0;
1427 stbir_info->ring_buffer_first_scanline = n;
1431 ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries;
1432 STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index);
1435 ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes /
sizeof(
float));
1436 memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes);
1442static void stbir__resample_horizontal_upsample(stbir__info* stbir_info,
float* output_buffer)
1445 int output_w = stbir_info->output_w;
1446 int channels = stbir_info->channels;
1447 float* decode_buffer = stbir__get_decode_buffer(stbir_info);
1448 stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors;
1449 float* horizontal_coefficients = stbir_info->horizontal_coefficients;
1450 int coefficient_width = stbir_info->horizontal_coefficient_width;
1452 for (x = 0; x < output_w; x++)
1454 int n0 = horizontal_contributors[x].n0;
1455 int n1 = horizontal_contributors[x].n1;
1457 int out_pixel_index = x * channels;
1458 int coefficient_group = coefficient_width * x;
1459 int coefficient_counter = 0;
1461 STBIR_ASSERT(n1 >= n0);
1462 STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin);
1463 STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin);
1464 STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
1465 STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin);
1469 for (k = n0; k <= n1; k++)
1471 int in_pixel_index = k * 1;
1472 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1473 STBIR_ASSERT(coefficient != 0);
1474 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1478 for (k = n0; k <= n1; k++)
1480 int in_pixel_index = k * 2;
1481 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1482 STBIR_ASSERT(coefficient != 0);
1483 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1484 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1488 for (k = n0; k <= n1; k++)
1490 int in_pixel_index = k * 3;
1491 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1492 STBIR_ASSERT(coefficient != 0);
1493 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1494 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1495 output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
1499 for (k = n0; k <= n1; k++)
1501 int in_pixel_index = k * 4;
1502 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1503 STBIR_ASSERT(coefficient != 0);
1504 output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient;
1505 output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient;
1506 output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient;
1507 output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient;
1511 for (k = n0; k <= n1; k++)
1513 int in_pixel_index = k * channels;
1514 float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++];
1516 STBIR_ASSERT(coefficient != 0);
1517 for (c = 0; c < channels; c++)
1518 output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient;
1525static void stbir__resample_horizontal_downsample(stbir__info* stbir_info,
float* output_buffer)
1528 int input_w = stbir_info->input_w;
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_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_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_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_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_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_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, stbir__add_empty_ring_buffer_entry(stbir_info, n));
1664 stbir__resample_horizontal_downsample(stbir_info, 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, stbir_info->horizontal_buffer);
1680 stbir__resample_horizontal_downsample(stbir_info, 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_num_entries,
int ring_buffer_length)
1688 int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries;
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)
1731 #define STBIR__ROUND_INT(f) ((int) ((f)+0.5))
1732 #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5))
1734 #ifdef STBIR__SATURATE_INT
1735 #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float ))
1736 #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float))
1738 #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float )
1739 #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float)
1745 for (x=0; x < num_pixels; ++x)
1747 int pixel_index = x*channels;
1749 for (n = 0; n < channels; n++)
1751 int index = pixel_index + n;
1752 ((
unsigned char*)output_buffer)[
index] = STBIR__ENCODE_LINEAR8(encode_buffer[
index]);
1758 for (x=0; x < num_pixels; ++x)
1760 int pixel_index = x*channels;
1762 for (n = 0; n < num_nonalpha; n++)
1764 int index = pixel_index + nonalpha[n];
1765 ((
unsigned char*)output_buffer)[
index] = stbir__linear_to_srgb_uchar(encode_buffer[
index]);
1769 ((
unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]);
1774 for (x=0; x < num_pixels; ++x)
1776 int pixel_index = x*channels;
1778 for (n = 0; n < channels; n++)
1780 int index = pixel_index + n;
1781 ((
unsigned short*)output_buffer)[
index] = STBIR__ENCODE_LINEAR16(encode_buffer[
index]);
1787 for (x=0; x < num_pixels; ++x)
1789 int pixel_index = x*channels;
1791 for (n = 0; n < num_nonalpha; n++)
1793 int index = pixel_index + nonalpha[n];
1794 ((
unsigned short*)output_buffer)[
index] = (
unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[
index])) * stbir__max_uint16_as_float);
1798 ((
unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]);
1804 for (x=0; x < num_pixels; ++x)
1806 int pixel_index = x*channels;
1808 for (n = 0; n < channels; n++)
1810 int index = pixel_index + n;
1811 ((
unsigned int*)output_buffer)[
index] = (
unsigned int)STBIR__ROUND_UINT(((
double)stbir__saturate(encode_buffer[
index])) * stbir__max_uint32_as_float);
1817 for (x=0; x < num_pixels; ++x)
1819 int pixel_index = x*channels;
1821 for (n = 0; n < num_nonalpha; n++)
1823 int index = pixel_index + nonalpha[n];
1824 ((
unsigned int*)output_buffer)[
index] = (
unsigned int)STBIR__ROUND_UINT(((
double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[
index]))) * stbir__max_uint32_as_float);
1828 ((
unsigned int*)output_buffer)[pixel_index + alpha_channel] = (
unsigned int)STBIR__ROUND_INT(((
double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float);
1833 for (x=0; x < num_pixels; ++x)
1835 int pixel_index = x*channels;
1837 for (n = 0; n < channels; n++)
1839 int index = pixel_index + n;
1840 ((
float*)output_buffer)[
index] = encode_buffer[
index];
1846 for (x=0; x < num_pixels; ++x)
1848 int pixel_index = x*channels;
1850 for (n = 0; n < num_nonalpha; n++)
1852 int index = pixel_index + nonalpha[n];
1853 ((
float*)output_buffer)[
index] = stbir__linear_to_srgb(encode_buffer[
index]);
1857 ((
float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel];
1862 STBIR_ASSERT(!
"Unknown type/colorspace/channels combination.");
1867static void stbir__resample_vertical_upsample(stbir__info* stbir_info,
int n)
1870 int output_w = stbir_info->output_w;
1871 stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
1872 float* vertical_coefficients = stbir_info->vertical_coefficients;
1873 int channels = stbir_info->channels;
1874 int alpha_channel = stbir_info->alpha_channel;
1875 int type = stbir_info->type;
1876 int colorspace = stbir_info->colorspace;
1877 int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
1878 void* output_data = stbir_info->output_data;
1879 float* encode_buffer = stbir_info->encode_buffer;
1880 int decode = STBIR__DECODE(type, colorspace);
1881 int coefficient_width = stbir_info->vertical_coefficient_width;
1882 int coefficient_counter;
1883 int contributor = n;
1885 float* ring_buffer = stbir_info->ring_buffer;
1886 int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
1887 int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline;
1888 int ring_buffer_length = stbir_info->ring_buffer_length_bytes/
sizeof(float);
1890 int n0,n1, output_row_start;
1891 int coefficient_group = coefficient_width * contributor;
1893 n0 = vertical_contributors[contributor].n0;
1894 n1 = vertical_contributors[contributor].n1;
1896 output_row_start = n * stbir_info->output_stride_bytes;
1898 STBIR_ASSERT(stbir__use_height_upsampling(stbir_info));
1900 memset(encode_buffer, 0, output_w *
sizeof(
float) * channels);
1905 coefficient_counter = 0;
1908 for (k = n0; k <= n1; k++)
1910 int coefficient_index = coefficient_counter++;
1911 float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
1912 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1913 for (x = 0; x < output_w; ++x)
1915 int in_pixel_index = x * 1;
1916 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1921 for (k = n0; k <= n1; k++)
1923 int coefficient_index = coefficient_counter++;
1924 float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
1925 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1926 for (x = 0; x < output_w; ++x)
1928 int in_pixel_index = x * 2;
1929 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1930 encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
1935 for (k = n0; k <= n1; k++)
1937 int coefficient_index = coefficient_counter++;
1938 float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
1939 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1940 for (x = 0; x < output_w; ++x)
1942 int in_pixel_index = x * 3;
1943 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1944 encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
1945 encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
1950 for (k = n0; k <= n1; k++)
1952 int coefficient_index = coefficient_counter++;
1953 float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
1954 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1955 for (x = 0; x < output_w; ++x)
1957 int in_pixel_index = x * 4;
1958 encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient;
1959 encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient;
1960 encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient;
1961 encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient;
1966 for (k = n0; k <= n1; k++)
1968 int coefficient_index = coefficient_counter++;
1969 float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length);
1970 float coefficient = vertical_coefficients[coefficient_group + coefficient_index];
1971 for (x = 0; x < output_w; ++x)
1973 int in_pixel_index = x * channels;
1975 for (c = 0; c < channels; c++)
1976 encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient;
1981 stbir__encode_scanline(stbir_info, output_w, (
char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode);
1984static void stbir__resample_vertical_downsample(stbir__info* stbir_info,
int n)
1987 int output_w = stbir_info->output_w;
1988 stbir__contributors* vertical_contributors = stbir_info->vertical_contributors;
1989 float* vertical_coefficients = stbir_info->vertical_coefficients;
1990 int channels = stbir_info->channels;
1991 int ring_buffer_entries = stbir_info->ring_buffer_num_entries;
1992 float* horizontal_buffer = stbir_info->horizontal_buffer;
1993 int coefficient_width = stbir_info->vertical_coefficient_width;
1994 int contributor = n + stbir_info->vertical_filter_pixel_margin;
1996 float* ring_buffer = stbir_info->ring_buffer;
1997 int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index;
1998 int ring_buffer_first_scanline = stbir_info->ring_buffer_first_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_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, ring_buffer_entries, 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_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_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
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->ring_buffer_num_entries;
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);
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->ring_buffer_num_entries;
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_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_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries);
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);
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->output_w / (s1 - s0);
2232 info->vertical_shift = t0 * info->output_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);
2255 info->ring_buffer_num_entries = filter_height + 1;
2257 info->horizontal_contributors_size = info->horizontal_num_contributors *
sizeof(stbir__contributors);
2258 info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) *
sizeof(float);
2259 info->vertical_contributors_size = info->vertical_num_contributors *
sizeof(stbir__contributors);
2260 info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) *
sizeof(float);
2261 info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels *
sizeof(
float);
2262 info->horizontal_buffer_size = info->output_w * info->channels *
sizeof(float);
2263 info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries *
sizeof(float);
2264 info->encode_buffer_size = info->output_w * info->channels *
sizeof(float);
2266 STBIR_ASSERT(info->horizontal_filter != 0);
2267 STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2268 STBIR_ASSERT(info->vertical_filter != 0);
2269 STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2271 if (stbir__use_height_upsampling(info))
2275 info->horizontal_buffer_size = 0;
2279 info->encode_buffer_size = 0;
2281 return info->horizontal_contributors_size + info->horizontal_coefficients_size
2282 + info->vertical_contributors_size + info->vertical_coefficients_size
2283 + info->decode_buffer_size + info->horizontal_buffer_size
2284 + info->ring_buffer_size + info->encode_buffer_size;
2287static int stbir__resize_allocated(stbir__info *info,
2288 const void* input_data,
int input_stride_in_bytes,
2289 void* output_data,
int output_stride_in_bytes,
2292 void* tempmem,
size_t tempmem_size_in_bytes)
2294 size_t memory_required = stbir__calculate_memory(info);
2296 int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type];
2297 int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type];
2299#ifdef STBIR_DEBUG_OVERWRITE_TEST
2300#define OVERWRITE_ARRAY_SIZE 8
2301 unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE];
2302 unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE];
2303 unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE];
2304 unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE];
2306 size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type];
2307 memcpy(overwrite_output_before_pre, &((
unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
2308 memcpy(overwrite_output_after_pre, &((
unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE);
2309 memcpy(overwrite_tempmem_before_pre, &((
unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE);
2310 memcpy(overwrite_tempmem_after_pre, &((
unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE);
2313 STBIR_ASSERT(info->channels >= 0);
2314 STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS);
2316 if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS)
2319 STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2320 STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table));
2322 if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
2324 if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table))
2327 if (alpha_channel < 0)
2331 STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels);
2334 if (alpha_channel >= info->channels)
2337 STBIR_ASSERT(tempmem);
2342 STBIR_ASSERT(tempmem_size_in_bytes >= memory_required);
2344 if (tempmem_size_in_bytes < memory_required)
2347 memset(tempmem, 0, tempmem_size_in_bytes);
2349 info->input_data = input_data;
2350 info->input_stride_bytes = width_stride_input;
2352 info->output_data = output_data;
2353 info->output_stride_bytes = width_stride_output;
2355 info->alpha_channel = alpha_channel;
2356 info->flags = flags;
2358 info->edge_horizontal = edge_horizontal;
2359 info->edge_vertical = edge_vertical;
2360 info->colorspace = colorspace;
2362 info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale);
2363 info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale );
2364 info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale);
2365 info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale );
2366 info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale);
2367 info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale );
2369 info->ring_buffer_length_bytes = info->output_w * info->channels *
sizeof(float);
2370 info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2;
2372#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size)
2374 info->horizontal_contributors = (stbir__contributors *) tempmem;
2375 info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors,
float);
2376 info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors);
2377 info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors,
float);
2378 info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients,
float);
2380 if (stbir__use_height_upsampling(info))
2382 info->horizontal_buffer = NULL;
2383 info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer,
float);
2384 info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer,
float);
2386 STBIR_ASSERT((
size_t)STBIR__NEXT_MEMPTR(info->encode_buffer,
unsigned char) == (
size_t)tempmem + tempmem_size_in_bytes);
2390 info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer,
float);
2391 info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer,
float);
2392 info->encode_buffer = NULL;
2394 STBIR_ASSERT((
size_t)STBIR__NEXT_MEMPTR(info->ring_buffer,
unsigned char) == (
size_t)tempmem + tempmem_size_in_bytes);
2397#undef STBIR__NEXT_MEMPTR
2400 info->ring_buffer_begin_index = -1;
2402 stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w);
2403 stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h);
2405 STBIR_PROGRESS_REPORT(0);
2407 if (stbir__use_height_upsampling(info))
2408 stbir__buffer_loop_upsample(info);
2410 stbir__buffer_loop_downsample(info);
2412 STBIR_PROGRESS_REPORT(1);
2414#ifdef STBIR_DEBUG_OVERWRITE_TEST
2415 STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((
unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
2416 STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((
unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0);
2417 STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((
unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0);
2418 STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((
unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0);
2425static int stbir__resize_arbitrary(
2426 void *alloc_context,
2427 const void* input_data,
int input_w,
int input_h,
int input_stride_in_bytes,
2428 void* output_data,
int output_w,
int output_h,
int output_stride_in_bytes,
2429 float s0,
float t0,
float s1,
float t1,
float *transform,
2436 size_t memory_required;
2439 stbir__setup(&info, input_w, input_h, output_w, output_h, channels);
2440 stbir__calculate_transform(&info, s0,t0,s1,t1,transform);
2441 stbir__choose_filter(&info, h_filter, v_filter);
2442 memory_required = stbir__calculate_memory(&info);
2443 extra_memory = STBIR_MALLOC(memory_required, alloc_context);
2448 result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes,
2449 output_data, output_stride_in_bytes,
2450 alpha_channel, flags, type,
2451 edge_horizontal, edge_vertical,
2452 colorspace, extra_memory, memory_required);
2454 STBIR_FREE(extra_memory, alloc_context);
2460 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2463 return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2464 output_pixels, output_w, output_h, output_stride_in_bytes,
2465 0,0,1,1,NULL,num_channels,-1,0,
STBIR_TYPE_UINT8,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2470 float *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2473 return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2474 output_pixels, output_w, output_h, output_stride_in_bytes,
2475 0,0,1,1,NULL,num_channels,-1,0,
STBIR_TYPE_FLOAT,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2480 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2481 int num_channels,
int alpha_channel,
int flags)
2483 return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2484 output_pixels, output_w, output_h, output_stride_in_bytes,
2485 0,0,1,1,NULL,num_channels,alpha_channel,flags,
STBIR_TYPE_UINT8,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2490 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2491 int num_channels,
int alpha_channel,
int flags,
2494 return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes,
2495 output_pixels, output_w, output_h, output_stride_in_bytes,
2496 0,0,1,1,NULL,num_channels,alpha_channel,flags,
STBIR_TYPE_UINT8,
STBIR_FILTER_DEFAULT,
STBIR_FILTER_DEFAULT,
2501 unsigned char *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2502 int num_channels,
int alpha_channel,
int flags,
2504 void *alloc_context)
2506 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2507 output_pixels, output_w, output_h, output_stride_in_bytes,
2508 0,0,1,1,NULL,num_channels,alpha_channel,flags,
STBIR_TYPE_UINT8, filter, filter,
2509 edge_wrap_mode, edge_wrap_mode, space);
2513 stbir_uint16 *output_pixels ,
int output_w,
int output_h,
int output_stride_in_bytes,
2514 int num_channels,
int alpha_channel,
int flags,
2516 void *alloc_context)
2518 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2519 output_pixels, output_w, output_h, output_stride_in_bytes,
2520 0,0,1,1,NULL,num_channels,alpha_channel,flags,
STBIR_TYPE_UINT16, filter, filter,
2521 edge_wrap_mode, edge_wrap_mode, space);
2526 float *output_pixels ,
int output_w,
int output_h,
int output_stride_in_bytes,
2527 int num_channels,
int alpha_channel,
int flags,
2529 void *alloc_context)
2531 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2532 output_pixels, output_w, output_h, output_stride_in_bytes,
2533 0,0,1,1,NULL,num_channels,alpha_channel,flags,
STBIR_TYPE_FLOAT, filter, filter,
2534 edge_wrap_mode, edge_wrap_mode, space);
2538STBIRDEF int stbir_resize(
const void *input_pixels ,
int input_w ,
int input_h ,
int input_stride_in_bytes,
2539 void *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2541 int num_channels,
int alpha_channel,
int flags,
2546 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2547 output_pixels, output_w, output_h, output_stride_in_bytes,
2548 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
2549 edge_mode_horizontal, edge_mode_vertical, space);
2554 void *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2556 int num_channels,
int alpha_channel,
int flags,
2560 float x_scale,
float y_scale,
2561 float x_offset,
float y_offset)
2564 transform[0] = x_scale;
2565 transform[1] = y_scale;
2566 transform[2] = x_offset;
2567 transform[3] = y_offset;
2568 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2569 output_pixels, output_w, output_h, output_stride_in_bytes,
2570 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
2571 edge_mode_horizontal, edge_mode_vertical, space);
2575 void *output_pixels,
int output_w,
int output_h,
int output_stride_in_bytes,
2577 int num_channels,
int alpha_channel,
int flags,
2581 float s0,
float t0,
float s1,
float t1)
2583 return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
2584 output_pixels, output_w, output_h, output_stride_in_bytes,
2585 s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
2586 edge_mode_horizontal, edge_mode_vertical, space);
const cJSON *const b
Definition cJSON.h:261
int index
Definition cJSON.h:176
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:288
@ STBIR_FILTER_DEFAULT
Definition stb_image_resize.h:289
@ STBIR_FILTER_MITCHELL
Definition stb_image_resize.h:294
@ STBIR_FILTER_BOX
Definition stb_image_resize.h:290
@ STBIR_FILTER_TRIANGLE
Definition stb_image_resize.h:291
@ STBIR_FILTER_CATMULLROM
Definition stb_image_resize.h:293
@ STBIR_FILTER_CUBICBSPLINE
Definition stb_image_resize.h:292
uint8_t stbir_uint8
Definition stb_image_resize.h:193
stbir_edge
Definition stb_image_resize.h:259
@ STBIR_EDGE_WRAP
Definition stb_image_resize.h:262
@ STBIR_EDGE_CLAMP
Definition stb_image_resize.h:260
@ STBIR_EDGE_ZERO
Definition stb_image_resize.h:263
@ STBIR_EDGE_REFLECT
Definition stb_image_resize.h:261
uint16_t stbir_uint16
Definition stb_image_resize.h:194
#define STBIR_FLAG_ALPHA_USES_COLORSPACE
Definition stb_image_resize.h:251
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:195
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:205
stbir_datatype
Definition stb_image_resize.h:341
@ STBIR_TYPE_UINT32
Definition stb_image_resize.h:344
@ STBIR_TYPE_UINT16
Definition stb_image_resize.h:343
@ STBIR_TYPE_UINT8
Definition stb_image_resize.h:342
@ STBIR_MAX_TYPES
Definition stb_image_resize.h:347
@ STBIR_TYPE_FLOAT
Definition stb_image_resize.h:345
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:248
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:298
@ STBIR_COLORSPACE_SRGB
Definition stb_image_resize.h:300
@ STBIR_MAX_COLORSPACES
Definition stb_image_resize.h:302
@ STBIR_COLORSPACE_LINEAR
Definition stb_image_resize.h:299