mirror of https://github.com/nothings/stb-imv
a few dumb features, updated stb_image
This commit is contained in:
parent
6d18e31131
commit
0a3e77f187
56
imv.c
56
imv.c
|
@ -343,6 +343,7 @@ static unsigned char alpha_background[2][3] =
|
||||||
|
|
||||||
// given raw decoded data from stbi_load, make it into a proper Image (e.g. creating a
|
// given raw decoded data from stbi_load, make it into a proper Image (e.g. creating a
|
||||||
// windows-compatible bitmap with 4-byte aligned rows and BGR color order)
|
// windows-compatible bitmap with 4-byte aligned rows and BGR color order)
|
||||||
|
float lmin=0,lmax=1;
|
||||||
void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL image_loaded_as_rgb, int image_n)
|
void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL image_loaded_as_rgb, int image_n)
|
||||||
{
|
{
|
||||||
int i,j,k=0;
|
int i,j,k=0;
|
||||||
|
@ -363,6 +364,14 @@ void make_image(Image *z, int image_x, int image_y, uint8 *image_data, BOOL imag
|
||||||
image_data[k+2] = t;
|
image_data[k+2] = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lmin > 0 || lmax < 1) {
|
||||||
|
int c;
|
||||||
|
for (c=0; c < 3; ++c) {
|
||||||
|
int z = (int) stb_linear_remap(image_data[k+c], lmin*255,lmax*255, 0,255);
|
||||||
|
image_data[k+c] = stb_clamp(z, 0, 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if BPP==4
|
#if BPP==4
|
||||||
// if image had an alpha channel, pre-blend with background
|
// if image had an alpha channel, pre-blend with background
|
||||||
if (image_n == 4) {
|
if (image_n == 4) {
|
||||||
|
@ -1235,7 +1244,7 @@ int StringCompareSort(const void *p, const void *q)
|
||||||
return StringCompare(*(char **) p, *(char **) q);
|
return StringCompare(*(char **) p, *(char **) q);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga\0";
|
char *open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;*.hdr\0";
|
||||||
|
|
||||||
// build a filelist for the current directory
|
// build a filelist for the current directory
|
||||||
void init_filelist(void)
|
void init_filelist(void)
|
||||||
|
@ -1881,6 +1890,27 @@ static void dialog_clampf(int id, float low, float high)
|
||||||
|
|
||||||
extern unsigned char *rom_images[]; // preference images
|
extern unsigned char *rom_images[]; // preference images
|
||||||
|
|
||||||
|
void clear_cache(int had_alpha)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
stb_mutex_begin(cache_mutex);
|
||||||
|
for (i=0; i < MAX_CACHED_IMAGES; ++i) {
|
||||||
|
if (cache[i].status == LOAD_available) {
|
||||||
|
if (had_alpha ? cache[i].image->had_alpha : TRUE) {
|
||||||
|
stb_sdict_remove(file_cache, cache[i].filename, NULL);
|
||||||
|
free(cache[i].filename);
|
||||||
|
imfree(cache[i].image);
|
||||||
|
cache[i].status = LOAD_unused;
|
||||||
|
cache[i].image = NULL;
|
||||||
|
cache[i].filename = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stb_mutex_end(cache_mutex);
|
||||||
|
free(cur_filename);
|
||||||
|
cur_filename = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// preferences dialog windows procedure
|
// preferences dialog windows procedure
|
||||||
BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam)
|
BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam)
|
||||||
{
|
{
|
||||||
|
@ -1977,20 +2007,7 @@ BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT imsg, WPARAM wparam, LPARAM lparam)
|
||||||
|
|
||||||
// if alpha_background changed, clear the cache of any images that used it
|
// if alpha_background changed, clear the cache of any images that used it
|
||||||
if (memcmp(alpha_background, curc, 6)) {
|
if (memcmp(alpha_background, curc, 6)) {
|
||||||
stb_mutex_begin(cache_mutex);
|
clear_cache(1);
|
||||||
for (i=0; i < MAX_CACHED_IMAGES; ++i) {
|
|
||||||
if (cache[i].status == LOAD_available) {
|
|
||||||
if (cache[i].image->had_alpha) {
|
|
||||||
stb_sdict_remove(file_cache, cache[i].filename, NULL);
|
|
||||||
free(cache[i].filename);
|
|
||||||
imfree(cache[i].image);
|
|
||||||
cache[i].status = LOAD_unused;
|
|
||||||
cache[i].image = NULL;
|
|
||||||
cache[i].filename = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stb_mutex_end(cache_mutex);
|
|
||||||
// force a reload of the current image
|
// force a reload of the current image
|
||||||
advance(0);
|
advance(0);
|
||||||
} else if (old_cubic != upsample_cubic) {
|
} else if (old_cubic != upsample_cubic) {
|
||||||
|
@ -2217,6 +2234,11 @@ int WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
KillTimer(win,0);
|
KillTimer(win,0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '[': lmax = stb_clamp(lmax-1.0f/32, 0,1); clear_cache(0); advance(0); break;
|
||||||
|
case ']': lmax = stb_clamp(lmax+1.0f/32, 0,1); clear_cache(0); advance(0); break;
|
||||||
|
case '{': lmin = stb_clamp(lmin-1.0f/32, 0,1); clear_cache(0); advance(0); break;
|
||||||
|
case '}': lmin = stb_clamp(lmin+1.0f/32, 0,1); clear_cache(0); advance(0); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2422,7 +2444,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
#ifdef USE_GDIPLUS
|
#ifdef USE_GDIPLUS
|
||||||
if (LoadGdiplus()) {
|
if (LoadGdiplus()) {
|
||||||
strcat(helptext_center, "\nUsing GDI+");
|
strcat(helptext_center, "\nUsing GDI+");
|
||||||
open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;*.gif;*.ico;*.jng;*.tiff\0";
|
open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.tga;*.hdr;*.gif;*.ico;*.jng;*.tiff\0";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2431,7 +2453,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
#ifdef USE_FREEIMAGE
|
#ifdef USE_FREEIMAGE
|
||||||
if (LoadFreeImage()) {
|
if (LoadFreeImage()) {
|
||||||
strcat(helptext_center, "\nUsing FreeImage.dll: http://freeimage.sourceforge.net");
|
strcat(helptext_center, "\nUsing FreeImage.dll: http://freeimage.sourceforge.net");
|
||||||
open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.dds;*.gif;*.ico;*.jng;*.lbm;*.pcx;*.ppm;*.psd;*.tga;*.tiff\0";
|
open_filter = "Image Files\0*.jpg;*.jpeg;*.png;*.bmp;*.hdr;*.dds;*.gif;*.ico;*.jng;*.lbm;*.pcx;*.ppm;*.psd;*.tga;*.tiff\0";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(helptext_center[sizeof(helptext_center)-1]==0);
|
assert(helptext_center[sizeof(helptext_center)-1]==0);
|
||||||
|
|
492
stb_image.c
492
stb_image.c
|
@ -1,4 +1,4 @@
|
||||||
/* stbi-0.98 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
/* stbi-1.02 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
||||||
when you control the images you're loading
|
when you control the images you're loading
|
||||||
|
|
||||||
QUICK NOTES:
|
QUICK NOTES:
|
||||||
|
@ -8,6 +8,8 @@
|
||||||
JPEG baseline (no JPEG progressive, no oddball channel decimations)
|
JPEG baseline (no JPEG progressive, no oddball channel decimations)
|
||||||
PNG non-interlaced
|
PNG non-interlaced
|
||||||
BMP non-1bpp, non-RLE
|
BMP non-1bpp, non-RLE
|
||||||
|
TGA (not sure what subset, if a subset)
|
||||||
|
HDR (radiance rgbE format)
|
||||||
writes BMP,TGA (define STBI_NO_WRITE to remove code)
|
writes BMP,TGA (define STBI_NO_WRITE to remove code)
|
||||||
decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code)
|
decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code)
|
||||||
|
|
||||||
|
@ -16,7 +18,12 @@
|
||||||
PSD loader
|
PSD loader
|
||||||
|
|
||||||
history:
|
history:
|
||||||
0.98 TGA loader by lonesock; dynamically add loaders
|
1.02 support for (subset of) HDR files, float interface for preferred access to them
|
||||||
|
1.01 fix bug: possible bug in handling right-side up bmps... not sure
|
||||||
|
fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all
|
||||||
|
1.00 interface to zlib that skips zlib header
|
||||||
|
0.99 correct handling of alpha in palette
|
||||||
|
0.98 TGA loader by lonesock; dynamically add loaders (untested)
|
||||||
0.97 jpeg errors on too large a file; also catch another malloc failure
|
0.97 jpeg errors on too large a file; also catch another malloc failure
|
||||||
0.96 fix detection of invalid v value - particleman@mollyrocket forum
|
0.96 fix detection of invalid v value - particleman@mollyrocket forum
|
||||||
0.95 during header scan, seek to markers in case of padding
|
0.95 during header scan, seek to markers in case of padding
|
||||||
|
@ -50,7 +57,7 @@
|
||||||
// - channel subsampling of at most 2 in each dimension (jpeg)
|
// - channel subsampling of at most 2 in each dimension (jpeg)
|
||||||
// - no delayed line count (jpeg) -- IJG doesn't support either
|
// - no delayed line count (jpeg) -- IJG doesn't support either
|
||||||
//
|
//
|
||||||
// Basic usage:
|
// Basic usage (see HDR discussion below):
|
||||||
// int x,y,n;
|
// int x,y,n;
|
||||||
// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
|
// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
|
||||||
// // ... process data if not NULL ...
|
// // ... process data if not NULL ...
|
||||||
|
@ -91,11 +98,54 @@
|
||||||
// more user-friendly ones.
|
// more user-friendly ones.
|
||||||
//
|
//
|
||||||
// Paletted PNG and BMP images are automatically depalettized.
|
// Paletted PNG and BMP images are automatically depalettized.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ===========================================================================
|
||||||
|
//
|
||||||
|
// HDR image support (disable by defining STBI_NO_HDR)
|
||||||
|
//
|
||||||
|
// stb_image now supports loading HDR images in general, and currently
|
||||||
|
// the Radiance .HDR file format, although the support is provided
|
||||||
|
// generically. You can still load any file through the existing interface;
|
||||||
|
// if you attempt to load an HDR file, it will be automatically remapped to
|
||||||
|
// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
|
||||||
|
// both of these constants can be reconfigured through this interface:
|
||||||
|
//
|
||||||
|
// stbi_hdr_to_ldr_gamma(2.2f);
|
||||||
|
// stbi_hdr_to_ldr_scale(1.0f);
|
||||||
|
//
|
||||||
|
// (note, do not use _inverse_ constants; stbi_image will invert them
|
||||||
|
// appropriately).
|
||||||
|
//
|
||||||
|
// Additionally, there is a new, parallel interface for loading files as
|
||||||
|
// (linear) floats to preserve the full dynamic range:
|
||||||
|
//
|
||||||
|
// float *data = stbi_loadf(filename, &x, &y, &n, 0);
|
||||||
|
//
|
||||||
|
// If you load LDR images through this interface, those images will
|
||||||
|
// be promoted to floating point values, run through the inverse of
|
||||||
|
// constants corresponding to the above:
|
||||||
|
//
|
||||||
|
// stbi_ldr_to_hdr_scale(1.0f);
|
||||||
|
// stbi_ldr_to_hdr_gamma(2.2f);
|
||||||
|
//
|
||||||
|
// Finally, given a filename (or an open file or memory block--see header
|
||||||
|
// file for details) containing image data, you can query for the "most
|
||||||
|
// appropriate" interface to use (that is, whether the image is HDR or
|
||||||
|
// not), using:
|
||||||
|
//
|
||||||
|
// stbi_is_hdr(char *filename);
|
||||||
|
|
||||||
|
|
||||||
#ifndef STBI_NO_STDIO
|
#ifndef STBI_NO_STDIO
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
#include <math.h> // ldexp
|
||||||
|
#include <string.h> // strcmp
|
||||||
|
#endif
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
STBI_default = 0, // only used for req_comp
|
STBI_default = 0, // only used for req_comp
|
||||||
|
@ -133,6 +183,21 @@ extern int stbi_info_from_file (FILE *f, int *x, int *y,
|
||||||
extern stbi_uc *stbi_load_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
extern stbi_uc *stbi_load_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
// for stbi_load_from_file, file pointer is left pointing immediately after image
|
// for stbi_load_from_file, file pointer is left pointing immediately after image
|
||||||
|
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern float *stbi_loadf (char *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
extern float *stbi_loadf_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
|
||||||
|
extern void stbi_hdr_to_ldr_gamma(float gamma);
|
||||||
|
extern void stbi_hdr_to_ldr_scale(float scale);
|
||||||
|
|
||||||
|
extern void stbi_ldr_to_hdr_gamma(float gamma);
|
||||||
|
extern void stbi_ldr_to_hdr_scale(float scale);
|
||||||
|
|
||||||
|
#endif // STBI_NO_HDR
|
||||||
|
|
||||||
// get a VERY brief reason for failure
|
// get a VERY brief reason for failure
|
||||||
extern char *stbi_failure_reason (void);
|
extern char *stbi_failure_reason (void);
|
||||||
|
|
||||||
|
@ -141,8 +206,11 @@ extern void stbi_image_free (stbi_uc *retval_from_stbi_load);
|
||||||
|
|
||||||
// get image dimensions & components without fully decoding
|
// get image dimensions & components without fully decoding
|
||||||
extern int stbi_info_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp);
|
extern int stbi_info_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp);
|
||||||
|
extern int stbi_is_hdr_from_memory(stbi_uc *buffer, int len);
|
||||||
#ifndef STBI_NO_STDIO
|
#ifndef STBI_NO_STDIO
|
||||||
extern int stbi_info (char *filename, int *x, int *y, int *comp);
|
extern int stbi_info (char *filename, int *x, int *y, int *comp);
|
||||||
|
extern int stbi_is_hdr (char *filename);
|
||||||
|
extern int stbi_is_hdr_from_file(FILE *f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ZLIB client - used by PNG, available for other purposes
|
// ZLIB client - used by PNG, available for other purposes
|
||||||
|
@ -151,6 +219,9 @@ extern char *stbi_zlib_decode_malloc_guesssize(int initial_size, int *outlen);
|
||||||
extern char *stbi_zlib_decode_malloc(char *buffer, int len, int *outlen);
|
extern char *stbi_zlib_decode_malloc(char *buffer, int len, int *outlen);
|
||||||
extern int stbi_zlib_decode_buffer(char *obuffer, int olen, char *ibuffer, int ilen);
|
extern int stbi_zlib_decode_buffer(char *obuffer, int olen, char *ibuffer, int ilen);
|
||||||
|
|
||||||
|
extern char *stbi_zlib_decode_noheader_malloc(char *buffer, int len, int *outlen);
|
||||||
|
extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, char *ibuffer, int ilen);
|
||||||
|
|
||||||
|
|
||||||
// TYPE-SPECIFIC ACCESS
|
// TYPE-SPECIFIC ACCESS
|
||||||
|
|
||||||
|
@ -203,6 +274,16 @@ extern int stbi_tga_test_file (FILE *f);
|
||||||
extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// is it an hdr?
|
||||||
|
extern int stbi_hdr_test_memory (stbi_uc *buffer, int len);
|
||||||
|
|
||||||
|
extern float * stbi_hdr_load (char *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern float * stbi_hdr_load_from_memory (stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_hdr_test_file (FILE *f);
|
||||||
|
extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
// define new loaders
|
// define new loaders
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -279,7 +360,7 @@ static int e(char *str)
|
||||||
#define e(x,y) e(x)
|
#define e(x,y) e(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ep(x,y) (e(x,y),NULL)
|
#define ep(x,y) (e(x,y)?NULL:NULL)
|
||||||
|
|
||||||
void stbi_image_free(unsigned char *retval_from_stbi_load)
|
void stbi_image_free(unsigned char *retval_from_stbi_load)
|
||||||
{
|
{
|
||||||
|
@ -308,6 +389,11 @@ int stbi_register_loader(stbi_loader *loader)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
|
||||||
|
static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef STBI_NO_STDIO
|
#ifndef STBI_NO_STDIO
|
||||||
unsigned char *stbi_load(char *filename, int *x, int *y, int *comp, int req_comp)
|
unsigned char *stbi_load(char *filename, int *x, int *y, int *comp, int req_comp)
|
||||||
{
|
{
|
||||||
|
@ -328,11 +414,18 @@ unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_c
|
||||||
return stbi_png_load_from_file(f,x,y,comp,req_comp);
|
return stbi_png_load_from_file(f,x,y,comp,req_comp);
|
||||||
if (stbi_bmp_test_file(f))
|
if (stbi_bmp_test_file(f))
|
||||||
return stbi_bmp_load_from_file(f,x,y,comp,req_comp);
|
return stbi_bmp_load_from_file(f,x,y,comp,req_comp);
|
||||||
if (stbi_tga_test_file(f))
|
#ifndef STBI_NO_HDR
|
||||||
return stbi_tga_load_from_file(f,x,y,comp,req_comp);
|
if (stbi_hdr_test_file(f)) {
|
||||||
|
float *hdr = stbi_hdr_load_from_file(f, x,y,comp,req_comp);
|
||||||
|
return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for (i=0; i < max_loaders; ++i)
|
for (i=0; i < max_loaders; ++i)
|
||||||
if (loaders[i]->test_file(f))
|
if (loaders[i]->test_file(f))
|
||||||
return loaders[i]->load_from_file(f,x,y,comp,req_comp);
|
return loaders[i]->load_from_file(f,x,y,comp,req_comp);
|
||||||
|
// test tga last because it's a crappy test!
|
||||||
|
if (stbi_tga_test_file(f))
|
||||||
|
return stbi_tga_load_from_file(f,x,y,comp,req_comp);
|
||||||
return ep("unknown image type", "Image not of any known type, or corrupt");
|
return ep("unknown image type", "Image not of any known type, or corrupt");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -346,19 +439,103 @@ unsigned char *stbi_load_from_memory(stbi_uc *buffer, int len, int *x, int *y, i
|
||||||
return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp);
|
return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp);
|
||||||
if (stbi_bmp_test_memory(buffer,len))
|
if (stbi_bmp_test_memory(buffer,len))
|
||||||
return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp);
|
return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp);
|
||||||
if (stbi_tga_test_memory(buffer,len))
|
#ifndef STBI_NO_HDR
|
||||||
return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp);
|
if (stbi_hdr_test_memory(buffer, len)) {
|
||||||
|
float *hdr = stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp);
|
||||||
|
return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for (i=0; i < max_loaders; ++i)
|
for (i=0; i < max_loaders; ++i)
|
||||||
if (loaders[i]->test_memory(buffer,len))
|
if (loaders[i]->test_memory(buffer,len))
|
||||||
return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp);
|
return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp);
|
||||||
|
// test tga last because it's a crappy test!
|
||||||
|
if (stbi_tga_test_memory(buffer,len))
|
||||||
|
return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp);
|
||||||
return ep("unknown image type", "Image not of any known type, or corrupt");
|
return ep("unknown image type", "Image not of any known type, or corrupt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
float *stbi_loadf(char *filename, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
float *result;
|
||||||
|
if (!f) return ep("can't fopen", "Unable to open file");
|
||||||
|
result = stbi_loadf_from_file(f,x,y,comp,req_comp);
|
||||||
|
fclose(f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
if (stbi_hdr_test_file(f))
|
||||||
|
return stbi_hdr_load_from_file(f,x,y,comp,req_comp);
|
||||||
|
data = stbi_load_from_file(f, x, y, comp, req_comp);
|
||||||
|
if (data)
|
||||||
|
return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
|
||||||
|
return ep("unknown image type", "Image not of any known type, or corrupt");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float *stbi_loadf_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
stbi_uc *data;
|
||||||
|
if (stbi_hdr_test_memory(buffer, len))
|
||||||
|
return stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp);
|
||||||
|
data = stbi_load_from_memory(buffer, len, x, y, comp, req_comp);
|
||||||
|
if (data)
|
||||||
|
return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
|
||||||
|
return ep("unknown image type", "Image not of any known type, or corrupt");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is
|
||||||
|
// defined, for API simplicity; if STBI_NO_HDR is defined, it always
|
||||||
|
// reports false!
|
||||||
|
|
||||||
|
extern int stbi_is_hdr_from_memory(stbi_uc *buffer, int len)
|
||||||
|
{
|
||||||
|
return stbi_hdr_test_memory(buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_is_hdr (char *filename)
|
||||||
|
{
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
int result=0;
|
||||||
|
if (f) {
|
||||||
|
result = stbi_is_hdr_from_file(f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int stbi_is_hdr_from_file(FILE *f)
|
||||||
|
{
|
||||||
|
return stbi_hdr_test_file(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// @TODO: get image dimensions & components without fully decoding
|
// @TODO: get image dimensions & components without fully decoding
|
||||||
extern int stbi_info (char *filename, int *x, int *y, int *comp);
|
extern int stbi_info (char *filename, int *x, int *y, int *comp);
|
||||||
extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
|
extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||||
extern int stbi_info_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp);
|
extern int stbi_info_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp);
|
||||||
|
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f;
|
||||||
|
static float l2h_gamma=2.2f, l2h_scale=1.0f;
|
||||||
|
|
||||||
|
void stbi_hdr_to_ldr_gamma(float gamma) { h2l_gamma_i = 1/gamma; }
|
||||||
|
void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; }
|
||||||
|
|
||||||
|
void stbi_ldr_to_hdr_gamma(float gamma) { l2h_gamma = gamma; }
|
||||||
|
void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Common code used by all image loaders
|
// Common code used by all image loaders
|
||||||
|
@ -376,7 +553,6 @@ enum
|
||||||
};
|
};
|
||||||
|
|
||||||
// An API for reading either from memory or file.
|
// An API for reading either from memory or file.
|
||||||
// It fits on a single screen. No abstract base classes needed.
|
|
||||||
#ifndef STBI_NO_STDIO
|
#ifndef STBI_NO_STDIO
|
||||||
static FILE *img_file;
|
static FILE *img_file;
|
||||||
#endif
|
#endif
|
||||||
|
@ -508,7 +684,8 @@ static unsigned char *convert_format(unsigned char *data, int img_n, int req_com
|
||||||
#define COMBO(a,b) ((a)*8+(b))
|
#define COMBO(a,b) ((a)*8+(b))
|
||||||
#define CASE(a,b) case COMBO(a,b): for(i=0; i < img_x; ++i, src += a, dest += b)
|
#define CASE(a,b) case COMBO(a,b): for(i=0; i < img_x; ++i, src += a, dest += b)
|
||||||
|
|
||||||
// convert source image with img_n components to one with req_comp components
|
// convert source image with img_n components to one with req_comp components;
|
||||||
|
// avoid switch per pixel, so use switch per scanline and massive macros
|
||||||
switch(COMBO(img_n, req_comp)) {
|
switch(COMBO(img_n, req_comp)) {
|
||||||
CASE(1,2) dest[0]=src[0], dest[1]=255; break;
|
CASE(1,2) dest[0]=src[0], dest[1]=255; break;
|
||||||
CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break;
|
CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break;
|
||||||
|
@ -532,6 +709,49 @@ static unsigned char *convert_format(unsigned char *data, int img_n, int req_com
|
||||||
return good;
|
return good;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
|
||||||
|
{
|
||||||
|
int i,k,n;
|
||||||
|
float *output = (float *) malloc(x * y * comp * sizeof(float));
|
||||||
|
if (output == NULL) { free(data); return ep("outofmem", "Out of memory"); }
|
||||||
|
// compute number of non-alpha components
|
||||||
|
if (comp & 1) n = comp; else n = comp-1;
|
||||||
|
for (i=0; i < x*y; ++i) {
|
||||||
|
for (k=0; k < n; ++k) {
|
||||||
|
output[i*comp + k] = (float) pow(data[i*comp+k]/255.0, l2h_gamma) * l2h_scale;
|
||||||
|
}
|
||||||
|
if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f;
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define float2int(x) ((int) (x))
|
||||||
|
static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp)
|
||||||
|
{
|
||||||
|
int i,k,n;
|
||||||
|
stbi_uc *output = (stbi_uc *) malloc(x * y * comp);
|
||||||
|
if (output == NULL) { free(data); return ep("outofmem", "Out of memory"); }
|
||||||
|
// compute number of non-alpha components
|
||||||
|
if (comp & 1) n = comp; else n = comp-1;
|
||||||
|
for (i=0; i < x*y; ++i) {
|
||||||
|
for (k=0; k < n; ++k) {
|
||||||
|
float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f;
|
||||||
|
if (z < 0) z = 0;
|
||||||
|
if (z > 255) z = 255;
|
||||||
|
output[i*comp + k] = float2int(z);
|
||||||
|
}
|
||||||
|
if (k < comp) {
|
||||||
|
float z = data[i*comp+k] * 255 + 0.5f;
|
||||||
|
if (z < 0) z = 0;
|
||||||
|
if (z > 255) z = 255;
|
||||||
|
output[i*comp + k] = float2int(z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation)
|
// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation)
|
||||||
|
@ -1777,10 +1997,11 @@ static void init_defaults(void)
|
||||||
for (i=0; i <= 31; ++i) default_distance[i] = 5;
|
for (i=0; i <= 31; ++i) default_distance[i] = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_zlib(void)
|
static int parse_zlib(int parse_header)
|
||||||
{
|
{
|
||||||
int final, type;
|
int final, type;
|
||||||
if (!parse_zlib_header()) return 0;
|
if (parse_header)
|
||||||
|
if (!parse_zlib_header()) return 0;
|
||||||
num_bits = 0;
|
num_bits = 0;
|
||||||
code_buffer = 0;
|
code_buffer = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -1805,21 +2026,21 @@ static int parse_zlib(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_zlib(char *obuf, int olen, int exp)
|
static int do_zlib(char *obuf, int olen, int exp, int parse_header)
|
||||||
{
|
{
|
||||||
zout_start = obuf;
|
zout_start = obuf;
|
||||||
zout = obuf;
|
zout = obuf;
|
||||||
zout_end = obuf + olen;
|
zout_end = obuf + olen;
|
||||||
z_expandable = exp;
|
z_expandable = exp;
|
||||||
|
|
||||||
return parse_zlib();
|
return parse_zlib(parse_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *stbi_zlib_decode_malloc_guesssize(int initial_size, int *outlen)
|
char *stbi_zlib_decode_malloc_guesssize(int initial_size, int *outlen)
|
||||||
{
|
{
|
||||||
char *p = (char *) malloc(initial_size);
|
char *p = (char *) malloc(initial_size);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
if (do_zlib(p, initial_size, 1)) {
|
if (do_zlib(p, initial_size, 1, 1)) {
|
||||||
*outlen = (int) (zout - zout_start);
|
*outlen = (int) (zout - zout_start);
|
||||||
return zout_start;
|
return zout_start;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1839,11 +2060,37 @@ int stbi_zlib_decode_buffer(char *obuffer, int olen, char *ibuffer, int ilen)
|
||||||
{
|
{
|
||||||
zbuffer = (uint8 *) ibuffer;
|
zbuffer = (uint8 *) ibuffer;
|
||||||
zbuffer_end = (uint8 *) ibuffer + ilen;
|
zbuffer_end = (uint8 *) ibuffer + ilen;
|
||||||
if (do_zlib(obuffer, olen, 0))
|
if (do_zlib(obuffer, olen, 0, 1))
|
||||||
return (int) (zout - zout_start);
|
return (int) (zout - zout_start);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *stbi_zlib_decode_noheader_malloc(char *buffer, int len, int *outlen)
|
||||||
|
{
|
||||||
|
char *p = (char *) malloc(16384);
|
||||||
|
if (p == NULL) return NULL;
|
||||||
|
zbuffer = (uint8 *) buffer;
|
||||||
|
zbuffer_end = (uint8 *) buffer+len;
|
||||||
|
if (do_zlib(p, 16384, 1, 0)) {
|
||||||
|
*outlen = (int) (zout - zout_start);
|
||||||
|
return zout_start;
|
||||||
|
} else {
|
||||||
|
free(zout_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, char *ibuffer, int ilen)
|
||||||
|
{
|
||||||
|
zbuffer = (uint8 *) ibuffer;
|
||||||
|
zbuffer_end = (uint8 *) ibuffer + ilen;
|
||||||
|
if (do_zlib(obuffer, olen, 0, 0))
|
||||||
|
return (int) (zout - zout_start);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18
|
// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18
|
||||||
// simple implementation
|
// simple implementation
|
||||||
// - only 8-bit samples
|
// - only 8-bit samples
|
||||||
|
@ -2093,6 +2340,7 @@ static int parse_png_file(int scan, int req_comp)
|
||||||
if (scan == SCAN_header) { img_n = 4; return 1; }
|
if (scan == SCAN_header) { img_n = 4; return 1; }
|
||||||
if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG");
|
if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG");
|
||||||
if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG");
|
if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG");
|
||||||
|
pal_img_n = 4;
|
||||||
for (i=0; i < c.length; ++i)
|
for (i=0; i < c.length; ++i)
|
||||||
palette[i*4+3] = get8u();
|
palette[i*4+3] = get8u();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2343,8 +2591,8 @@ static stbi_uc *bmp_load(int *x, int *y, int *comp, int req_comp)
|
||||||
if (get16le() != 1) return 0;
|
if (get16le() != 1) return 0;
|
||||||
bpp = get16le();
|
bpp = get16le();
|
||||||
if (bpp == 1) return ep("monochrome", "BMP type not supported: 1-bit");
|
if (bpp == 1) return ep("monochrome", "BMP type not supported: 1-bit");
|
||||||
flip_vertically = img_y > 0;
|
flip_vertically = ((int) img_y) > 0;
|
||||||
img_y = abs(img_y);
|
img_y = abs((int) img_y);
|
||||||
if (hsz == 12) {
|
if (hsz == 12) {
|
||||||
if (bpp < 24)
|
if (bpp < 24)
|
||||||
psize = (offset - 14 - 24) / 3;
|
psize = (offset - 14 - 24) / 3;
|
||||||
|
@ -2518,7 +2766,7 @@ stbi_uc *stbi_bmp_load (char *filename, int *x, int *y, in
|
||||||
stbi_uc *data;
|
stbi_uc *data;
|
||||||
FILE *f = fopen(filename, "rb");
|
FILE *f = fopen(filename, "rb");
|
||||||
if (!f) return NULL;
|
if (!f) return NULL;
|
||||||
data = bmp_load(x,y,comp,req_comp);
|
data = stbi_bmp_load_from_file(f, x,y,comp,req_comp);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -2800,7 +3048,7 @@ stbi_uc *stbi_tga_load (char *filename, int *x, int *y, in
|
||||||
stbi_uc *data;
|
stbi_uc *data;
|
||||||
FILE *f = fopen(filename, "rb");
|
FILE *f = fopen(filename, "rb");
|
||||||
if (!f) return NULL;
|
if (!f) return NULL;
|
||||||
data = tga_load(x,y,comp,req_comp);
|
data = stbi_tga_load_from_file(f, x,y,comp,req_comp);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -2818,6 +3066,210 @@ stbi_uc *stbi_tga_load_from_memory (stbi_uc *buffer, int len, int *x, int *y, in
|
||||||
return tga_load(x,y,comp,req_comp);
|
return tga_load(x,y,comp,req_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *************************************************************************************************
|
||||||
|
// Radiance RGBE HDR loader
|
||||||
|
// originally by Nicolas Schulz
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
static int hdr_test(void)
|
||||||
|
{
|
||||||
|
char *signature = "#?RADIANCE\n";
|
||||||
|
int i;
|
||||||
|
for (i=0; signature[i]; ++i)
|
||||||
|
if (get8() != signature[i])
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int stbi_hdr_test_memory(stbi_uc *buffer, int len)
|
||||||
|
{
|
||||||
|
start_mem(buffer, len);
|
||||||
|
return hdr_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
int stbi_hdr_test_file(FILE *f)
|
||||||
|
{
|
||||||
|
int r,n = ftell(f);
|
||||||
|
start_file(f);
|
||||||
|
r = hdr_test();
|
||||||
|
fseek(f,n,SEEK_SET);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define HDR_BUFLEN 1024
|
||||||
|
static char *hdr_gettoken(char *buffer)
|
||||||
|
{
|
||||||
|
int len=0;
|
||||||
|
char *s = buffer, c = '\0';
|
||||||
|
|
||||||
|
c = get8();
|
||||||
|
|
||||||
|
while (!at_eof() && c != '\n') {
|
||||||
|
buffer[len++] = c;
|
||||||
|
if (len == HDR_BUFLEN-1) {
|
||||||
|
// flush to end of line
|
||||||
|
while (!at_eof() && get8() != '\n')
|
||||||
|
;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = get8();
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[len] = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hdr_convert(float *output, stbi_uc *input, int req_comp)
|
||||||
|
{
|
||||||
|
if( input[3] != 0 ) {
|
||||||
|
float f1;
|
||||||
|
// Exponent
|
||||||
|
f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
|
||||||
|
if (req_comp <= 2)
|
||||||
|
output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
|
||||||
|
else {
|
||||||
|
output[0] = input[0] * f1;
|
||||||
|
output[1] = input[1] * f1;
|
||||||
|
output[2] = input[2] * f1;
|
||||||
|
}
|
||||||
|
if (req_comp == 2) output[1] = 1;
|
||||||
|
if (req_comp == 4) output[3] = 1;
|
||||||
|
} else {
|
||||||
|
switch (req_comp) {
|
||||||
|
case 4: output[3] = 255; /* fallthrough */
|
||||||
|
case 3: output[0] = output[1] = output[2] = 0;
|
||||||
|
break;
|
||||||
|
case 2: output[1] = 255; /* fallthrough */
|
||||||
|
case 1: output[0] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float *hdr_load(int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
char buffer[HDR_BUFLEN];
|
||||||
|
char *token;
|
||||||
|
int valid = 0;
|
||||||
|
int width, height;
|
||||||
|
stbi_uc *scanline;
|
||||||
|
float *hdr_data;
|
||||||
|
int len;
|
||||||
|
unsigned char count, value;
|
||||||
|
int i, j, k, c1,c2, z;
|
||||||
|
|
||||||
|
|
||||||
|
// Check identifier
|
||||||
|
if (strcmp(hdr_gettoken(buffer), "#?RADIANCE") != 0)
|
||||||
|
return ep("not HDR", "Corrupt HDR image");
|
||||||
|
|
||||||
|
// Parse header
|
||||||
|
while(1) {
|
||||||
|
token = hdr_gettoken(buffer);
|
||||||
|
if (token[0] == 0) break;
|
||||||
|
if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid) return ep("unsupported format", "Unsupported HDR format");
|
||||||
|
|
||||||
|
// Parse width and height
|
||||||
|
// can't use sscanf() if we're not using stdio!
|
||||||
|
token = hdr_gettoken(buffer);
|
||||||
|
if (strncmp(token, "-Y ", 3)) return ep("unsupported data layout", "Unsupported HDR format");
|
||||||
|
token += 3;
|
||||||
|
height = strtol(token, &token, 10);
|
||||||
|
while (*token == ' ') ++token;
|
||||||
|
if (strncmp(token, "+X ", 3)) return ep("unsupported data layout", "Unsupported HDR format");
|
||||||
|
token += 3;
|
||||||
|
width = strtol(token, NULL, 10);
|
||||||
|
|
||||||
|
*x = width;
|
||||||
|
*y = height;
|
||||||
|
|
||||||
|
*comp = 3;
|
||||||
|
if (req_comp == 0) req_comp = 3;
|
||||||
|
|
||||||
|
// Read data
|
||||||
|
hdr_data = (float *) malloc(height * width * req_comp * sizeof(float));
|
||||||
|
|
||||||
|
// Load image data
|
||||||
|
// image data is stored as some number of sca
|
||||||
|
if( width < 8 || width >= 32768) {
|
||||||
|
// Read flat data
|
||||||
|
for (j=0; j < height; ++j) {
|
||||||
|
for (i=0; i < width; ++i) {
|
||||||
|
stbi_uc rgbe[4];
|
||||||
|
main_decode_loop:
|
||||||
|
getn(rgbe, 4);
|
||||||
|
hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Read RLE-encoded data
|
||||||
|
scanline = NULL;
|
||||||
|
|
||||||
|
for (j = 0; j < height; ++j) {
|
||||||
|
c1 = get8();
|
||||||
|
c2 = get8();
|
||||||
|
len = get8();
|
||||||
|
if (c1 != 2 || c2 != 2 || (len & 0x80)) {
|
||||||
|
// not run-length encoded, so we have to actually use THIS data as a decoded
|
||||||
|
// pixel (note this can't be a valid pixel--one of RGB must be >= 128)
|
||||||
|
stbi_uc rgbe[4] = { c1,c2,len, get8() };
|
||||||
|
hdr_convert(hdr_data, rgbe, req_comp);
|
||||||
|
i = 1;
|
||||||
|
j = 0;
|
||||||
|
free(scanline);
|
||||||
|
goto main_decode_loop; // yes, this is fucking insane; blame the fucking insane format
|
||||||
|
}
|
||||||
|
len <<= 8;
|
||||||
|
len |= get8();
|
||||||
|
if (len != width) { free(hdr_data); free(scanline); return ep("invalid decoded scanline length", "corrupt HDR"); }
|
||||||
|
if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4);
|
||||||
|
|
||||||
|
for (k = 0; k < 4; ++k) {
|
||||||
|
i = 0;
|
||||||
|
while (i < width) {
|
||||||
|
count = get8();
|
||||||
|
if (count > 128) {
|
||||||
|
// Run
|
||||||
|
value = get8();
|
||||||
|
count -= 128;
|
||||||
|
for (z = 0; z < count; ++z)
|
||||||
|
scanline[i++ * 4 + k] = value;
|
||||||
|
} else {
|
||||||
|
// Dump
|
||||||
|
for (z = 0; z < count; ++z)
|
||||||
|
scanline[i++ * 4 + k] = get8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i=0; i < width; ++i)
|
||||||
|
hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
|
||||||
|
}
|
||||||
|
free(scanline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hdr_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
float *stbi_hdr_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
start_file(f);
|
||||||
|
return hdr_load(x,y,comp,req_comp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float *stbi_hdr_load_from_memory(stbi_uc *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
start_mem(buffer, len);
|
||||||
|
return hdr_load(x,y,comp,req_comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // STBI_NO_HDR
|
||||||
|
|
||||||
/////////////////////// write image ///////////////////////
|
/////////////////////// write image ///////////////////////
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue