diff --git a/stb_image_write.h b/stb_image_write.h index d40386f3b7495379e50cbf8f72af897bec42cf5a..5a449d9d0da1d9895fe6710f52930dd75b2cec18 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v0.96 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v0.97 - 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 @@ -229,18 +229,18 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) } } -void stbiw__write_rle_data(FILE *f, int length, unsigned char databyte) +void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) { - unsigned char lengthbyte = 0x80 | (unsigned char)(length & 0x7f); - assert(length <= 0x7f); + unsigned char lengthbyte = (unsigned char) (length+128); + assert(length+128 <= 255); fwrite(&lengthbyte, 1, 1, f); fwrite(&databyte, 1, 1, f); } -void stbiw__write_nonrle_data(FILE *f, int length, unsigned char *data) +void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) { unsigned char lengthbyte = (unsigned char )(length & 0xff); - assert(length <= 0x7f); + assert(length <= 128); // inconsistent with spec but consistent with official code fwrite(&lengthbyte, 1, 1, f); fwrite(data, length, 1, f); } @@ -272,6 +272,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra fwrite(rgbe, 4, 1, f); } } else { + int c,r; /* encode into scratch buffer */ for (x=0; x < width; x++) { switch(comp) { @@ -294,50 +295,42 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra fwrite(scanlineheader, 4, 1, f); /* RLE each component separately */ - for (x=0; x < 4; x++) { - unsigned char *comp = &scratch[width*x]; + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; int runstart = 0, head = 0, rlerun = 0; - while (head < width) { - head++; - - if (head - runstart == 127 && rlerun == 1) { - // max length RLE run - stbiw__write_rle_data(f, head - runstart, comp[runstart]); - rlerun = 0; - runstart = head; - } else if (head - runstart == 128 && rlerun == 0) { - // max length non-RLE run - stbiw__write_nonrle_data(f, head - runstart, comp+runstart); - rlerun = 0; - runstart = head; - } else if (comp[head] != comp[head-1] && rlerun == 1) { - // end of RLE run - stbiw__write_rle_data(f, head - runstart, comp[runstart]); - rlerun = 0; - runstart = head; - } else { - // continue accumulating RLE run - if (rlerun == 1) continue; - - // see if we can start an RLE run, at least 3 bytes same - if (rlerun == 0 && head - runstart >= 2 - && comp[head] == comp[head-1] - && comp[head] == comp[head-2]) { - // found a run. Flush non-run (if there is anything) and then start an RLE run - if (head - runstart > 2) { - stbiw__write_nonrle_data(f, head-2 - runstart, comp+runstart); - } - - rlerun = 1; - runstart = head-2; + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(f, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(f, len, comp[x]); + x += len; } } } - - // flush remaining sequence (if any) - if (rlerun == 1) stbiw__write_rle_data(f, head - runstart, comp[runstart]); - else if (head - runstart > 0) stbiw__write_nonrle_data(f, head - runstart, comp+runstart); } } } @@ -686,6 +679,8 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat /* Revision history + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic 0.96 (2015-01-17) add HDR output fix monochrome BMP diff --git a/tests/image_test.c b/tests/image_test.c index 3fab9db3160a35a752ed293709e4ab51c4ac3b41..3cdd01163e60c2532e86c24f7dc1558862e7c30b 100644 --- a/tests/image_test.c +++ b/tests/image_test.c @@ -51,10 +51,24 @@ void test_ycbcr(void) } #endif +float hdr_data[200][200][3]; + int main(int argc, char **argv) { int w,h; //test_ycbcr(); + + #if 0 + // test hdr asserts + for (h=0; h < 100; h += 2) + for (w=0; w < 200; ++w) + hdr_data[h][w][0] = (float) rand(), + hdr_data[h][w][1] = (float) rand(), + hdr_data[h][w][2] = (float) rand(); + + stbi_write_hdr("output/test.hdr", 200,200,3,hdr_data[0][0]); + #endif + if (argc > 1) { int i, n;