Update documentation and add helper functions.
This commit is contained in:
parent
5b40906271
commit
68f93b72d5
207
stb_resample.h
207
stb_resample.h
@ -1,29 +1,65 @@
|
|||||||
/* stb_resample - v0.1 - public domain image resampling
|
/* stb_resample - v0.50 - public domain image resampling
|
||||||
no warranty implied; use at your own risk
|
no warranty implied; use at your own risk
|
||||||
|
|
||||||
Do this:
|
Do this:
|
||||||
#define STB_RESAMPLE_IMPLEMENTATION
|
#define STB_RESAMPLE_IMPLEMENTATION
|
||||||
before you include this file in *one* C or C++ file to create the 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.
|
#define STBR_ASSERT(x) to avoid using assert.h.
|
||||||
|
|
||||||
Latest revisions:
|
#define STBR_NO_MALLOC to avoid using stdlib.h and malloc. This will remove
|
||||||
|
all resize functions except stbr_resize_arbitrary() from the API.
|
||||||
|
|
||||||
See end of file for full revision history.
|
QUICK NOTES:
|
||||||
|
Written with emphasis on usage and speed. Only the resize operation is
|
||||||
|
currently supported, no rotations or translations.
|
||||||
|
|
||||||
Initial implementation by Jorge L Rodriguez
|
Supports arbitrary resize for separable filters. For a list of
|
||||||
|
supported filters see the stbr_filter enum. To add a new filter,
|
||||||
|
write a filter function and add it to stbr__filter_info_table.
|
||||||
|
|
||||||
|
Latest revisions:
|
||||||
|
0.50 (2014-07-29) first released version
|
||||||
|
|
||||||
|
See end of file for full revision history.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
Installable filters
|
||||||
|
Specify with (s0, t0) X (s1, t1) what area of the source image to use,
|
||||||
|
at sub-pixel level
|
||||||
|
Specify wrap and filter modes independently for each axis
|
||||||
|
Resize that respects alpha test coverage
|
||||||
|
(Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage:
|
||||||
|
https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp )
|
||||||
|
|
||||||
|
Initial implementation by Jorge L Rodriguez, @VinoBS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef STBR_INCLUDE_STB_RESAMPLE_H
|
#ifndef STBR_INCLUDE_STB_RESAMPLE_H
|
||||||
#define STBR_INCLUDE_STB_RESAMPLE_H
|
#define STBR_INCLUDE_STB_RESAMPLE_H
|
||||||
|
|
||||||
// Basic usage:
|
// Basic usage:
|
||||||
// result = stbr_resize(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, channels, alpha_channel, STBR_TYPE_UINT8, STBR_FILTER_BILINEAR, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB);
|
// result = stbr_resize_srgb_uint8(input_data, input_w, input_h, output_data, output_w, output_h, channels, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP);
|
||||||
//
|
//
|
||||||
// input_data is your supplied texels.
|
// input_data is your supplied texels.
|
||||||
// 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.)
|
// output_data will be the resized texels. It should be of size output_w * output_h * channels
|
||||||
// If input_stride or output_stride is 0 (as in this example) the stride will be automatically calculated as width*components.
|
// Returned result is 1 for success or 0 in case of an error. Currently the only error is failure to allocate memory.
|
||||||
// Returned result is 1 for success or 0 in case of an error.
|
// If you're unsure of which filter to use, Catmull-Rom is a good upsampling filter and Mitchell is a good downsampling filter.
|
||||||
|
|
||||||
|
|
||||||
|
// Advanced usage:
|
||||||
|
// size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, channels, STBR_FILTER_CATMULLROM);
|
||||||
|
// void* extra_memory = malloc(memory_required); // Any memory allocation method of your choosing
|
||||||
|
// result = stbr_resize_arbitrary(input_data, input_w, input_h, input_stride_in_bytes,
|
||||||
|
// output_data, output_w, output_h, output_stride_in_bytes,
|
||||||
|
// channels, STBR_TYPE_UINT8, STBR_FILTER_CATMULLROM, STBR_EDGE_CLAMP, STBR_COLORSPACE_SRGB,
|
||||||
|
// extra_memory, memory_required);
|
||||||
|
// free(extra_memory);
|
||||||
|
//
|
||||||
|
// input_stride_in_bytes and output_stride_in_bytes can be 0. If so they will be automatically calculated as width * channels.
|
||||||
|
// Returned result is 1 for success or 0 in case of an error. Currently the only error is that the memory passed in is insufficient.
|
||||||
|
// stbr_resize_arbitrary() will not allocate any memory, it will use the memory you pass in to do its work.
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@ -61,7 +97,17 @@ typedef enum
|
|||||||
|
|
||||||
#define STBR_MAX_TYPES 4
|
#define STBR_MAX_TYPES 4
|
||||||
|
|
||||||
typedef unsigned char stbr_uc;
|
typedef unsigned char stbr_uint8;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef unsigned short stbr_uint16;
|
||||||
|
typedef unsigned int stbr_uint32;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef uint16_t stbr_uint16;
|
||||||
|
typedef uint32_t stbr_uint32;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef unsigned int stbr_size_t; // to avoid including a header for size_t
|
typedef unsigned int stbr_size_t; // to avoid including a header for size_t
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -74,18 +120,40 @@ extern "C" {
|
|||||||
#define STBRDEF extern
|
#define STBRDEF extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBR_NO_MALLOC
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// PRIMARY API - resize an image
|
// PRIMARY API - sRGB type-safe image resizing.
|
||||||
//
|
//
|
||||||
|
|
||||||
STBRDEF stbr_size_t stbr_calculate_memory(int input_w, int input_h, int input_stride_in_bytes,
|
STBRDEF int stbr_resize_srgb_uint8(const stbr_uint8* input_data, int input_w, int input_h,
|
||||||
int output_w, int output_h, int output_stride_in_bytes,
|
stbr_uint8* output_data, int output_w, int output_h,
|
||||||
int channels, stbr_filter filter);
|
int channels, stbr_filter filter, stbr_edge edge);
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_uint16(const stbr_uint16* input_data, int input_w, int input_h,
|
||||||
|
stbr_uint16* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge);
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_uint32(const stbr_uint32* input_data, int input_w, int input_h,
|
||||||
|
stbr_uint32* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge);
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_float(const float* input_data, int input_w, int input_h,
|
||||||
|
float* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge);
|
||||||
|
|
||||||
|
#endif // STBR_NO_MALLOC
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ADVANCED API
|
||||||
|
//
|
||||||
|
|
||||||
|
STBRDEF stbr_size_t stbr_calculate_memory(int input_w, int input_h, int output_w, int output_h, int channels, stbr_filter filter);
|
||||||
|
|
||||||
STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input_h, int input_stride_in_bytes,
|
STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input_h, int input_stride_in_bytes,
|
||||||
void* output_data, int output_w, int output_h, int output_stride_in_bytes,
|
void* output_data, int output_w, int output_h, int output_stride_in_bytes,
|
||||||
//int channels, int alpha_channel, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace,
|
|
||||||
int channels, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace,
|
int channels, stbr_type type, stbr_filter filter, stbr_edge edge, stbr_colorspace colorspace,
|
||||||
void* tempmem, stbr_size_t tempmem_size_in_bytes);
|
void* tempmem, stbr_size_t tempmem_size_in_bytes);
|
||||||
|
|
||||||
@ -119,9 +187,12 @@ extern "C" {
|
|||||||
// For memset
|
// For memset
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#ifndef STBR_NO_MALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -134,21 +205,8 @@ extern "C" {
|
|||||||
#endif
|
#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
|
// should produce compiler error if size is wrong
|
||||||
typedef unsigned char stbr__validate_uint32[sizeof(stbr__uint32) == 4 ? 1 : -1];
|
typedef unsigned char stbr__validate_uint32[sizeof(stbr_uint32) == 4 ? 1 : -1];
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define STBR_NOTUSED(v) (void)(v)
|
#define STBR_NOTUSED(v) (void)(v)
|
||||||
@ -1142,7 +1200,7 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input
|
|||||||
if (!tempmem)
|
if (!tempmem)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (tempmem_size_in_bytes < stbr_calculate_memory(input_w, input_h, input_stride_in_bytes, output_w, output_h, output_stride_in_bytes, channels, STBR_FILTER_NEAREST))
|
if (tempmem_size_in_bytes < stbr_calculate_memory(input_w, input_h, output_w, output_h, channels, filter))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
memset(tempmem, 0, tempmem_size_in_bytes);
|
memset(tempmem, 0, tempmem_size_in_bytes);
|
||||||
@ -1213,9 +1271,7 @@ STBRDEF int stbr_resize_arbitrary(const void* input_data, int input_w, int input
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STBRDEF stbr_size_t stbr_calculate_memory(int input_w, int input_h, int input_stride_in_bytes,
|
STBRDEF stbr_size_t stbr_calculate_memory(int input_w, int input_h, int output_w, int output_h, int channels, stbr_filter filter)
|
||||||
int output_w, int output_h, int output_stride_in_bytes,
|
|
||||||
int channels, stbr_filter filter)
|
|
||||||
{
|
{
|
||||||
STBR_ASSERT(filter != 0);
|
STBR_ASSERT(filter != 0);
|
||||||
STBR_ASSERT(filter < STBR_ARRAY_SIZE(stbr__filter_info_table));
|
STBR_ASSERT(filter < STBR_ARRAY_SIZE(stbr__filter_info_table));
|
||||||
@ -1244,8 +1300,83 @@ STBRDEF stbr_size_t stbr_calculate_memory(int input_w, int input_h, int input_st
|
|||||||
return info_size + contributors_size + horizontal_coefficients_size + vertical_coefficients_size + decode_buffer_size + horizontal_buffer_size + ring_buffer_size + encode_buffer_size;
|
return info_size + contributors_size + horizontal_coefficients_size + vertical_coefficients_size + decode_buffer_size + horizontal_buffer_size + ring_buffer_size + encode_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef STBR_NO_MALLOC
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_uint8(const stbr_uint8* input_data, int input_w, int input_h,
|
||||||
|
stbr_uint8* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge)
|
||||||
|
{
|
||||||
|
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, channels, filter);
|
||||||
|
void* extra_memory = malloc(memory_required);
|
||||||
|
|
||||||
|
if (!extra_memory)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int result = stbr_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, channels, STBR_TYPE_UINT8, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
|
||||||
|
|
||||||
|
free(extra_memory);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_uint16(const stbr_uint16* input_data, int input_w, int input_h,
|
||||||
|
stbr_uint16* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge)
|
||||||
|
{
|
||||||
|
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, channels, filter);
|
||||||
|
void* extra_memory = malloc(memory_required);
|
||||||
|
|
||||||
|
if (!extra_memory)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int result = stbr_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, channels, STBR_TYPE_UINT16, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
|
||||||
|
|
||||||
|
free(extra_memory);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_uint32(const stbr_uint32* input_data, int input_w, int input_h,
|
||||||
|
stbr_uint32* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge)
|
||||||
|
{
|
||||||
|
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, channels, filter);
|
||||||
|
void* extra_memory = malloc(memory_required);
|
||||||
|
|
||||||
|
if (!extra_memory)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int result = stbr_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, channels, STBR_TYPE_UINT32, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
|
||||||
|
|
||||||
|
free(extra_memory);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
STBRDEF int stbr_resize_srgb_float(const float* input_data, int input_w, int input_h,
|
||||||
|
float* output_data, int output_w, int output_h,
|
||||||
|
int channels, stbr_filter filter, stbr_edge edge)
|
||||||
|
{
|
||||||
|
size_t memory_required = stbr_calculate_memory(input_w, input_h, output_w, output_h, channels, filter);
|
||||||
|
void* extra_memory = malloc(memory_required);
|
||||||
|
|
||||||
|
if (!extra_memory)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int result = stbr_resize_arbitrary(input_data, input_w, input_h, 0, output_data, output_w, output_h, 0, channels, STBR_TYPE_FLOAT, filter, edge, STBR_COLORSPACE_SRGB, extra_memory, memory_required);
|
||||||
|
|
||||||
|
free(extra_memory);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STBR_NO_MALLOC
|
||||||
|
|
||||||
|
|
||||||
#endif // STB_RESAMPLE_IMPLEMENTATION
|
#endif // STB_RESAMPLE_IMPLEMENTATION
|
||||||
|
|
||||||
/*
|
/*
|
||||||
revision history:
|
revision history:
|
||||||
|
0.50 (2014-07-29)
|
||||||
|
first released version
|
||||||
*/
|
*/
|
||||||
|
@ -48,7 +48,7 @@ int main(int argc, char** argv)
|
|||||||
int in_w = 512;
|
int in_w = 512;
|
||||||
int in_h = 512;
|
int in_h = 512;
|
||||||
|
|
||||||
size_t memory_required = stbr_calculate_memory(in_w, in_h, w*n, out_w, out_h, out_stride, n, STBR_FILTER_CATMULLROM);
|
size_t memory_required = stbr_calculate_memory(in_w, in_h, out_w, out_h, n, STBR_FILTER_CATMULLROM);
|
||||||
void* extra_memory = malloc(memory_required);
|
void* extra_memory = malloc(memory_required);
|
||||||
|
|
||||||
// Cut out the outside 64 pixels all around to test the stride.
|
// Cut out the outside 64 pixels all around to test the stride.
|
||||||
|
Loading…
Reference in New Issue
Block a user