2014-07-21 15:16:03 +08:00
/* stb_resample - v0.1 - public domain image resampling
no warranty implied ; use at your own risk
Do this :
# define STB_RESAMPLE_IMPLEMENTATION
before you include this file in * one * C or C + + file to create the implementation .
# define STBR_ASSERT(x) to avoid using assert.h.
Latest revisions :
See end of file for full revision history .
Initial implementation by Jorge L Rodriguez
*/
# ifndef STBR_INCLUDE_STB_RESAMPLE_H
# define STBR_INCLUDE_STB_RESAMPLE_H
// Basic usage:
2014-07-22 10:51:11 +08:00
// result = stbr_resize(input_data, input_w, input_h, input_components, 0, output_data, output_w, output_h, 0, STBR_FILTER_NEAREST, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB);
2014-07-21 15:16:03 +08:00
//
// input_data is your supplied texels.
2014-07-22 09:01:05 +08:00
// output_data will be the resized texels. It should be of size output_w * output_h * input_components (or output_h * output_stride if you provided a stride.)
// If input_stride or output_stride is 0 (as in this example) the stride will be automatically calculated as width*components.
2014-07-22 06:36:43 +08:00
// Returned result is 1 for success or 0 in case of an error.
2014-07-21 15:16:03 +08:00
typedef enum
{
STBR_FILTER_NEAREST = 1 ,
} stbr_filter ;
2014-07-22 07:14:32 +08:00
typedef enum
{
STBR_EDGE_CLAMP = 1 ,
} stbr_edge ;
2014-07-22 10:51:11 +08:00
typedef enum
{
STBR_COLORSPACE_LINEAR = 1 ,
STBR_COLORSPACE_SRGB = 1 ,
} stbr_colorspace ;
2014-07-21 15:16:03 +08:00
typedef unsigned char stbr_uc ;
# ifdef __cplusplus
extern " C " {
# endif
# ifdef STB_RESAMPLE_STATIC
# define STBRDEF static
# else
# define STBRDEF extern
# endif
//////////////////////////////////////////////////////////////////////////////
//
// PRIMARY API - resize an image
//
2014-07-22 10:51:11 +08:00
STBRDEF int stbr_resize ( const stbr_uc * input_data , int input_w , int input_h , int input_components , int input_stride , stbr_uc * output_data , int output_w , int output_h , int output_stride , stbr_filter filter , stbr_edge edge , stbr_colorspace colorspace ) ;
2014-07-21 15:16:03 +08:00
# ifdef __cplusplus
}
# endif
//
//
//// end header file /////////////////////////////////////////////////////
# endif // STBR_INCLUDE_STB_RESAMPLE_H
# ifdef STB_RESIZE_IMPLEMENTATION
# ifndef STBR_ASSERT
# include <assert.h>
# define STBR_ASSERT(x) assert(x)
# endif
# ifdef STBR_DEBUG_OVERWRITE_TEST
# include <string.h>
# endif
// For size_t
# include <stdlib.h>
# ifndef _MSC_VER
# ifdef __cplusplus
# define stbr_inline inline
# else
# define stbr_inline
# endif
# else
# define stbr_inline __forceinline
# endif
# ifdef _MSC_VER
typedef unsigned short stbr__uint16 ;
typedef signed short stbr__int16 ;
typedef unsigned int stbr__uint32 ;
typedef signed int stbr__int32 ;
# else
# include <stdint.h>
typedef uint16_t stbr__uint16 ;
typedef int16_t stbr__int16 ;
typedef uint32_t stbr__uint32 ;
typedef int32_t stbr__int32 ;
# endif
// should produce compiler error if size is wrong
typedef unsigned char stbr__validate_uint32 [ sizeof ( stbr__uint32 ) = = 4 ? 1 : - 1 ] ;
# ifdef _MSC_VER
# define STBR_NOTUSED(v) (void)(v)
# else
# define STBR_NOTUSED(v) (void)sizeof(v)
# endif
// i0 is a texel in [0, n0-1]
// What's the nearest texel center to i0's center in [0, n1-1] ?
// Remapping [0, n0-1] to [0, n1-1] gives (i0 + 0.5)*n1/n0 but we want to avoid
// floating point math so we rearrange it as (n1*i0 + n1/2)/n0
stbr_inline static int stbr__nearest_texel ( int i0 , int n0 , int n1 )
{
return ( n1 * i0 + n1 / 2 ) / n0 ;
}
stbr_inline static size_t stbr__texel_index ( int x , int y , int c , int width_stride , int num_c , int w , int h )
{
STBR_ASSERT ( x > = 0 & & x < w ) ;
STBR_ASSERT ( y > = 0 & & y < h ) ;
return y * width_stride + x * num_c + c ;
}
static void stbr__filter_nearest_1 ( const stbr_uc * input_data , stbr_uc * output_data , size_t input_texel_index , size_t output_texel_index , size_t n )
{
output_data [ output_texel_index ] = input_data [ input_texel_index ] ;
}
static void stbr__filter_nearest_3 ( const stbr_uc * input_data , stbr_uc * output_data , size_t input_texel_index , size_t output_texel_index , size_t n )
{
output_data [ output_texel_index ] = input_data [ input_texel_index ] ;
output_data [ output_texel_index + 1 ] = input_data [ input_texel_index + 1 ] ;
output_data [ output_texel_index + 2 ] = input_data [ input_texel_index + 2 ] ;
}
static void stbr__filter_nearest_4 ( const stbr_uc * input_data , stbr_uc * output_data , size_t input_texel_index , size_t output_texel_index , size_t n )
{
output_data [ output_texel_index ] = input_data [ input_texel_index ] ;
output_data [ output_texel_index + 1 ] = input_data [ input_texel_index + 1 ] ;
output_data [ output_texel_index + 2 ] = input_data [ input_texel_index + 2 ] ;
output_data [ output_texel_index + 3 ] = input_data [ input_texel_index + 3 ] ;
}
static void stbr__filter_nearest_n ( const stbr_uc * input_data , stbr_uc * output_data , size_t input_texel_index , size_t output_texel_index , size_t n )
{
size_t c ;
for ( c = 0 ; c < n ; c + + )
output_data [ output_texel_index + c ] = input_data [ input_texel_index + c ] ;
}
typedef void ( stbr__filter_fn ) ( const stbr_uc * input_data , stbr_uc * output_data , size_t input_texel_index , size_t output_texel_index , size_t n ) ;
2014-07-22 10:51:11 +08:00
STBRDEF int stbr_resize ( const stbr_uc * input_data , int input_w , int input_h , int input_components , int input_stride , stbr_uc * output_data , int output_w , int output_h , int output_stride , stbr_filter filter , stbr_edge edge , stbr_colorspace colorspace )
2014-07-21 15:16:03 +08:00
{
int x , y ;
2014-07-22 09:01:05 +08:00
int width_stride_input = input_stride ? input_stride : input_components * input_w ;
int width_stride_output = output_stride ? output_stride : input_components * output_w ;
2014-07-21 15:16:03 +08:00
# ifdef STBR_DEBUG_OVERWRITE_TEST
# define OVERWRITE_ARRAY_SIZE 64
unsigned char overwrite_contents_pre [ OVERWRITE_ARRAY_SIZE ] ;
2014-07-22 09:01:05 +08:00
size_t begin_forbidden = width_stride_output * ( output_h - 1 ) + output_w * input_components ;
memcpy ( overwrite_contents_pre , & output_data [ begin_forbidden ] , OVERWRITE_ARRAY_SIZE ) ;
2014-07-21 15:16:03 +08:00
# endif
if ( filter = = STBR_FILTER_NEAREST )
{
stbr__filter_fn * filter_fn ;
filter_fn = & stbr__filter_nearest_n ;
if ( input_components = = 1 )
filter_fn = & stbr__filter_nearest_1 ;
else if ( input_components = = 3 )
filter_fn = & stbr__filter_nearest_3 ;
else if ( input_components = = 4 )
filter_fn = & stbr__filter_nearest_4 ;
for ( y = 0 ; y < output_h ; y + + )
{
int nearest_y = stbr__nearest_texel ( y , output_h , input_h ) ;
for ( x = 0 ; x < output_w ; x + + )
{
int nearest_x = stbr__nearest_texel ( x , output_w , input_w ) ;
size_t input_texel_index = stbr__texel_index ( nearest_x , nearest_y , 0 , width_stride_input , input_components , input_w , input_h ) ;
size_t output_texel_index = stbr__texel_index ( x , y , 0 , width_stride_output , input_components , output_w , output_h ) ;
filter_fn ( input_data , output_data , input_texel_index , output_texel_index , input_components ) ;
}
}
}
else
return 0 ;
# ifdef STBR_DEBUG_OVERWRITE_TEST
2014-07-22 09:01:05 +08:00
STBR_ASSERT ( memcmp ( overwrite_contents_pre , & output_data [ begin_forbidden ] , OVERWRITE_ARRAY_SIZE ) = = 0 ) ;
2014-07-21 15:16:03 +08:00
# endif
2014-07-22 06:36:43 +08:00
return 1 ;
2014-07-21 15:16:03 +08:00
}
# endif // STB_RESAMPLE_IMPLEMENTATION
/*
revision history :
*/