new quickstart docs;

reformat docs;
new simple uint32 test
This commit is contained in:
Sean Barrett 2014-09-14 14:55:23 -07:00
parent 3c261481a6
commit 9f66b441bd
2 changed files with 163 additions and 117 deletions

View File

@ -1,161 +1,171 @@
/* stb_image_resize - v0.90 - public domain image resizing /* stb_image_resize - v0.90 - public domain image resizing
by Jorge L Rodriguez (@VinoBS) - 2014 by Jorge L Rodriguez (@VinoBS) - 2014
http://github.com/nothings/stb http://github.com/nothings/stb
Written with emphasis on usage and speed. Only scaling is Written with emphasis on usability, portability, and efficiency. (No
currently supported, no rotations or translations. SIMD or threads, so it will not be the fastest implementation around.)
Only scaling is supported, no rotations or translations.
DOCUMENTATION COMPILING & LINKING
In one C/C++ file that #includes this file, do this:
#define STB_IMAGE_RESIZE_IMPLEMENTATION
before the #include. That will create the implementation in that file.
COMPILING & LINKING QUICKSTART
In one C/C++ file that #includes this file, do this: stbir_resize_uint8( input_pixels , in_w , in_h , 0,
#define STB_IMAGE_RESIZE_IMPLEMENTATION output_pixels, out_w, out_h, 0, num_channels)
before the #include. That will create the implementation in that file. stbir_resize_float(...)
stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0,
output_pixels, out_w, out_h, 0,
num_channels , alpha_ chan , 0)
stbir_resize_uint8_srgb_edgemode(
input_pixels , in_w , in_h , 0,
output_pixels, out_w, out_h, 0,
num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP)
WRAP/REFLECT/ZERO
VERY QUICK GUIDE FULL API
A typical resize of a in_w by in_h image to out_w by out_h with 4 channels where channel #3 is the alpha channel might look like: See the "header file" section of the source for API documentation.
int success = stbir_resize_uint8_srgb_edgemode(input_pixels, in_w, in_h, 0, output_pixels, out_w, out_h, 0, 4, 3, 0, STBIR_EDGE_CLAMP);
FULL API ADDITIONAL DOCUMENTATION
See the "header file" section of the source for API documentation.
MEMORY ALLOCATION MEMORY ALLOCATION
The resize functions here perform a single memory allocation using The resize functions here perform a single memory allocation using
malloc. To control the memory allocation, before the #include that malloc. To control the memory allocation, before the #include that
triggers the implementation, do: triggers the implementation, do:
#define STBIR_MALLOC(size,context) ... #define STBIR_MALLOC(size,context) ...
#define STBIR_FREE(ptr,context) ... #define STBIR_FREE(ptr,context) ...
Each resize function makes exactly one call to malloc/free, so to use Each resize function makes exactly one call to malloc/free, so to use
temp memory, store the temp memory in the context and return that. temp memory, store the temp memory in the context and return that.
ASSERT ASSERT
Define STBIR_ASSERT(boolval) to override assert() and not use assert.h Define STBIR_ASSERT(boolval) to override assert() and not use assert.h
DEFAULT FILTERS DEFAULT FILTERS
For functions which don't provide explicit control over what filters For functions which don't provide explicit control over what filters
to use, you can change the compile-time defaults with to use, you can change the compile-time defaults with
#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something
#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something
See stbir_filter in the header-file section for the list of filters. See stbir_filter in the header-file section for the list of filters.
NEW FILTERS NEW FILTERS
A number of 1D filter kernels are used. For a list of A number of 1D filter kernels are used. For a list of
supported filters see the stbir_filter enum. To add a new filter, supported filters see the stbir_filter enum. To add a new filter,
write a filter function and add it to stbir__filter_info_table. write a filter function and add it to stbir__filter_info_table.
PROGRESS PROGRESS
For interactive use with slow resize operations, you can install For interactive use with slow resize operations, you can install
a progress-report callback: a progress-report callback:
#define STBIR_PROGRESS_REPORT(val) some_func(val) #define STBIR_PROGRESS_REPORT(val) some_func(val)
The parameter val is a float which goes from 0 to 1 as progress is made. The parameter val is a float which goes from 0 to 1 as progress is made.
For example: For example:
static void my_progress_report(float progress); static void my_progress_report(float progress);
#define STBIR_PROGRESS_REPORT(val) my_progress_report(val) #define STBIR_PROGRESS_REPORT(val) my_progress_report(val)
#define STB_IMAGE_RESIZE_IMPLEMENTATION #define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h" #include "stb_image_resize.h"
static void my_progress_report(float progress) static void my_progress_report(float progress)
{ {
printf("Progress: %f%%\n", progress*100); printf("Progress: %f%%\n", progress*100);
} }
ALPHA CHANNEL ALPHA CHANNEL
Most of the resizing functions provide the ability to control how Most of the resizing functions provide the ability to control how
the alpha channel of an image is processed. The important things the alpha channel of an image is processed. The important things
to know about this: to know about this:
1. The best mathematically-behaved version of alpha to use is 1. The best mathematically-behaved version of alpha to use is
called "premultiplied alpha", in which the other color channels called "premultiplied alpha", in which the other color channels
have had the alpha value multiplied in. If you use premultiplied have had the alpha value multiplied in. If you use premultiplied
alpha, linear filtering (such as image resampling done by this alpha, linear filtering (such as image resampling done by this
library, or performed in texture units on GPUs) does the "right library, or performed in texture units on GPUs) does the "right
thing". While premultiplied alpha is standard in the movie CGI thing". While premultiplied alpha is standard in the movie CGI
industry, it is still uncommon in the videogame/real-time world. industry, it is still uncommon in the videogame/real-time world.
If you linearly filter non-premultiplied alpha, strange effects If you linearly filter non-premultiplied alpha, strange effects
occur. (For example, the average of 1% opaque bright green occur. (For example, the average of 1% opaque bright green
and 99% opaque black produces 50% transparent dark green when and 99% opaque black produces 50% transparent dark green when
non-premultiplied, whereas premultiplied it produces 50% non-premultiplied, whereas premultiplied it produces 50%
transparent near-black. The former introduces green energy transparent near-black. The former introduces green energy
that doesn't exist in the source image.) that doesn't exist in the source image.)
2. Artists should not edit premultiplied-alpha images; artists 2. Artists should not edit premultiplied-alpha images; artists
want non-premultiplied alpha images. Thus, art tools generally output want non-premultiplied alpha images. Thus, art tools generally output
non-premultiplied alpha images. non-premultiplied alpha images.
3. You will get best results in most cases by converting images 3. You will get best results in most cases by converting images
to premultiplied alpha before processing them mathematically. to premultiplied alpha before processing them mathematically.
4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the
resizer does not do anything special for the alpha channel; resizer does not do anything special for the alpha channel;
it is resampled identically to other channels. This produces it is resampled identically to other channels. This produces
the correct results for premultiplied-alpha images, but produces the correct results for premultiplied-alpha images, but produces
less-than-ideal results for non-premultiplied-alpha images. less-than-ideal results for non-premultiplied-alpha images.
5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED,
then the resizer weights the contribution of input pixels then the resizer weights the contribution of input pixels
based on their alpha values, or, equivalently, it multiplies based on their alpha values, or, equivalently, it multiplies
the alpha value into the color channels, resamples, then divides the alpha value into the color channels, resamples, then divides
by the resultant alpha value. Input pixels which have alpha=0 do by the resultant alpha value. Input pixels which have alpha=0 do
not contribute at all to output pixels unless _all_ of the input not contribute at all to output pixels unless _all_ of the input
pixels affecting that output pixel have alpha=0, in which case pixels affecting that output pixel have alpha=0, in which case
the result for that pixel is the same as it would be without the result for that pixel is the same as it would be without
STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for
input images in integer formats. For input images in float format, input images in integer formats. For input images in float format,
input pixels with alpha=0 have no effect, and output pixels input pixels with alpha=0 have no effect, and output pixels
which have alpha=0 will be 0 in all channels. (For float images, which have alpha=0 will be 0 in all channels. (For float images,
you can manually achieve the same result by adding a tiny epsilon you can manually achieve the same result by adding a tiny epsilon
value to the alpha channel of every image, and then subtracting value to the alpha channel of every image, and then subtracting
or clamping it at the end.) or clamping it at the end.)
6. You can suppress the behavior described in #5 and make 6. You can suppress the behavior described in #5 and make
all-0-alpha pixels have 0 in all channels by #defining all-0-alpha pixels have 0 in all channels by #defining
STBIR_NO_ALPHA_EPSILON. STBIR_NO_ALPHA_EPSILON.
7. You can separately control whether the alpha channel is 7. You can separately control whether the alpha channel is
interpreted as linear or affected by the colorspace. By default interpreted as linear or affected by the colorspace. By default
it is linear; you almost never want to apply the colorspace. it is linear; you almost never want to apply the colorspace.
(For example, graphics hardware does not apply sRGB conversion (For example, graphics hardware does not apply sRGB conversion
to the alpha channel.) to the alpha channel.)
ADDITIONAL CONTRIBUTORS ADDITIONAL CONTRIBUTORS
Sean Barrett: API design, optimizations Sean Barrett: API design, optimizations
REVISIONS REVISIONS
0.90 (2014-??-??) first released version 0.90 (2014-??-??) first released version
LICENSE LICENSE
This software is in the public domain. Where that dedication is not This software is in the public domain. Where that dedication is not
recognized, you are granted a perpetual, irrevocable license to copy recognized, you are granted a perpetual, irrevocable license to copy
and modify this file as you see fit. and modify this file as you see fit.
TODO TODO
Don't decode all of the image data when only processing a partial tile Don't decode all of the image data when only processing a partial tile
Installable filters? Installable filters?
Resize that respects alpha test coverage Resize that respects alpha test coverage
(Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage:
https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp )
*/ */
#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H #ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H
#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H #define STBIR_INCLUDE_STB_IMAGE_RESIZE_H
typedef unsigned char stbir_uint8;
#ifdef _MSC_VER #ifdef _MSC_VER
typedef unsigned char stbir_uint8;
typedef unsigned short stbir_uint16; typedef unsigned short stbir_uint16;
typedef unsigned int stbir_uint32; typedef unsigned int stbir_uint32;
#else #else
#include <stdint.h> #include <stdint.h>
typedef uint8_t stbir_uint8;
typedef uint16_t stbir_uint16; typedef uint16_t stbir_uint16;
typedef uint32_t stbir_uint32; typedef uint32_t stbir_uint32;
#endif #endif
@ -372,7 +382,7 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int
#ifndef STBIR_MALLOC #ifndef STBIR_MALLOC
#include <stdlib.h> #include <stdlib.h>
#define STBIR_MALLOC(size,c) malloc(size) #define STBIR_MALLOC(size,c) malloc(size)
#define STBIR_FREE(ptr,c) free(ptr) #define STBIR_FREE(ptr,c) free(ptr)
#endif #endif
#ifndef _MSC_VER #ifndef _MSC_VER

View File

@ -750,6 +750,40 @@ void test_filters(void)
} }
} }
#define UMAX32 4294967295U
static void write32(char *filename, stbir_uint32 *output, int w, int h)
{
stbir_uint8 *data = (stbir_uint8*) malloc(w*h*3);
for (int i=0; i < w*h*3; ++i)
data[i] = output[i]>>24;
stbi_write_png(filename, w, h, 3, data, 0);
free(data);
}
static void test_32(void)
{
int w=100,h=120,x,y, out_w,out_h;
stbir_uint32 *input = (stbir_uint32*) malloc(4 * 3 * w * h);
stbir_uint32 *output = (stbir_uint32*) malloc(4 * 3 * 3*w * 3*h);
for (y=0; y < h; ++y) {
for (x=0; x < w; ++x) {
input[y*3*w + x*3 + 0] = x * ( UMAX32/w );
input[y*3*w + x*3 + 1] = y * ( UMAX32/h );
input[y*3*w + x*3 + 2] = UMAX32/2;
}
}
out_w = w*33/16;
out_h = h*33/16;
stbir_resize(input,w,h,0,output,out_w,out_h,0,STBIR_TYPE_UINT32,3,-1,0,STBIR_EDGE_CLAMP,STBIR_EDGE_CLAMP,STBIR_FILTER_DEFAULT,STBIR_FILTER_DEFAULT,STBIR_COLORSPACE_LINEAR,NULL);
write32("test-output/seantest_1.png", output,out_w,out_h);
out_w = w*16/33;
out_h = h*16/33;
stbir_resize(input,w,h,0,output,out_w,out_h,0,STBIR_TYPE_UINT32,3,-1,0,STBIR_EDGE_CLAMP,STBIR_EDGE_CLAMP,STBIR_FILTER_DEFAULT,STBIR_FILTER_DEFAULT,STBIR_COLORSPACE_LINEAR,NULL);
write32("test-output/seantest_2.png", output,out_w,out_h);
}
void test_suite(int argc, char **argv) void test_suite(int argc, char **argv)
{ {
@ -758,6 +792,8 @@ void test_suite(int argc, char **argv)
_mkdir("test-output"); _mkdir("test-output");
test_32();
if (argc > 1) if (argc > 1)
barbara = argv[1]; barbara = argv[1];
else else