From edd5e6700dfe6e409683e2927c2e4bc5c29c87c5 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Sat, 17 Jan 2015 07:46:22 -0800 Subject: [PATCH] tweak baldurk's hdr implementation --- stb_image_write.h | 59 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index f2c42b2..f58cf9f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,16 +1,16 @@ -/* stb_image_write - v0.95 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v0.96 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 no warranty implied; use at your own risk -Before including, + Before #including, - #define STB_IMAGE_WRITE_IMPLEMENTATION + #define STB_IMAGE_WRITE_IMPLEMENTATION -in the file that you want to have the implementation. + in the file that you want to have the implementation. -Will probably not work correctly with strict-aliasing optimizations. + Will probably not work correctly with strict-aliasing optimizations. ABOUT: @@ -56,6 +56,17 @@ USAGE: HDR expects linear float data. Since the format is always 32-bit rgb(e) data, alpha (if provided) is discarded, and for monochrome data it is replicated across all three channels. + +CREDITS: + + PNG/BMP/TGA + Sean Barrett + HDR + Baldur Karlsson + TGA monochrome: + Jean-Sebastien Guay + Bugfixes: + Chribba@github */ #ifndef INCLUDE_STB_IMAGE_WRITE_H @@ -65,10 +76,10 @@ USAGE: extern "C" { #endif -extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); -extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); -extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); -extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data); +extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); #ifdef __cplusplus } @@ -83,6 +94,7 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const vo #include #include #include +#include typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; @@ -193,7 +205,7 @@ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *dat // ************************************************************************************************* // Radiance RGBE HDR writer -// originally by Baldur Karlsson +// by Baldur Karlsson #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) @@ -204,7 +216,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) if (maxcomp < 1e-32) { rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; } else { - maxcomp = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; rgbe[0] = (unsigned char)(linear[0] * maxcomp); rgbe[1] = (unsigned char)(linear[1] * maxcomp); @@ -216,6 +228,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) void stbiw__write_rle_data(FILE *f, int length, unsigned char databyte) { unsigned char lengthbyte = 0x80 | (unsigned char)(length & 0x7f); + assert(length <= 0x7f); fwrite(&lengthbyte, 1, 1, f); fwrite(&databyte, 1, 1, f); } @@ -223,11 +236,12 @@ void stbiw__write_rle_data(FILE *f, int length, unsigned char databyte) void stbiw__write_nonrle_data(FILE *f, int length, unsigned char *data) { unsigned char lengthbyte = (unsigned char )(length & 0xff); + assert(length <= 0x7f); fwrite(&lengthbyte, 1, 1, f); fwrite(data, length, 1, f); } -void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, float *scanline) +void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline) { unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; unsigned char rgbe[4]; @@ -324,26 +338,28 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra } } -int stbi_write_hdr(char const *filename, int x, int y, int comp, const void *data) +int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) { int i; FILE *f; - unsigned char *scratch; - if (y <= 0 || x <= 0) return 0; + if (y <= 0 || x <= 0 || data == NULL) return 0; f = fopen(filename, "wb"); if (f) { - float *scanline = (float *)data; /* Each component is stored separately. Allocate scratch space for full output scanline. */ - scratch = (unsigned char *) malloc(x*4); if (!scanline) { fclose(f); return 0; } - fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"); - fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); - for(i=0; i < y; i++) stbiw__write_hdr_scanline(f, x, comp, scratch, scanline + comp*i*x); + unsigned char *scratch = (unsigned char *) malloc(x*4); + fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ); + fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x); + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); free(scratch); fclose(f); } return f != NULL; } +///////////////////////////////////////////////////////// +// PNG + // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() #define stbiw__sbraw(a) ((int *) (a) - 2) #define stbiw__sbm(a) stbiw__sbraw(a)[0] @@ -666,6 +682,9 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat /* Revision history + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP 0.95 (2014-08-17) add monochrome TGA output 0.94 (2014-05-31)