提交 22fa9a46 编写于 作者: S Sean Barrett

rewrite HDR rle logic

上级 80d5c4be
/* 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 writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
no warranty implied; use at your own risk no warranty implied; use at your own risk
...@@ -229,18 +229,18 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) ...@@ -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); unsigned char lengthbyte = (unsigned char) (length+128);
assert(length <= 0x7f); assert(length+128 <= 255);
fwrite(&lengthbyte, 1, 1, f); fwrite(&lengthbyte, 1, 1, f);
fwrite(&databyte, 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); 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(&lengthbyte, 1, 1, f);
fwrite(data, length, 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 ...@@ -272,6 +272,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
fwrite(rgbe, 4, 1, f); fwrite(rgbe, 4, 1, f);
} }
} else { } else {
int c,r;
/* encode into scratch buffer */ /* encode into scratch buffer */
for (x=0; x < width; x++) { for (x=0; x < width; x++) {
switch(comp) { switch(comp) {
...@@ -294,50 +295,42 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra ...@@ -294,50 +295,42 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra
fwrite(scanlineheader, 4, 1, f); fwrite(scanlineheader, 4, 1, f);
/* RLE each component separately */ /* RLE each component separately */
for (x=0; x < 4; x++) { for (c=0; c < 4; c++) {
unsigned char *comp = &scratch[width*x]; unsigned char *comp = &scratch[width*c];
int runstart = 0, head = 0, rlerun = 0; int runstart = 0, head = 0, rlerun = 0;
while (head < width) { x = 0;
head++; while (x < width) {
// find first run
if (head - runstart == 127 && rlerun == 1) { r = x;
// max length RLE run while (r+2 < width) {
stbiw__write_rle_data(f, head - runstart, comp[runstart]); if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
rlerun = 0; break;
runstart = head; ++r;
} else if (head - runstart == 128 && rlerun == 0) { }
// max length non-RLE run if (r+2 >= width)
stbiw__write_nonrle_data(f, head - runstart, comp+runstart); r = width;
rlerun = 0; // dump up to first run
runstart = head; while (x < r) {
} else if (comp[head] != comp[head-1] && rlerun == 1) { int len = r-x;
// end of RLE run if (len > 128) len = 128;
stbiw__write_rle_data(f, head - runstart, comp[runstart]); stbiw__write_dump_data(f, len, &comp[x]);
rlerun = 0; x += len;
runstart = head; }
} else { // if there's a run, output it
// continue accumulating RLE run if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
if (rlerun == 1) continue; // find next byte after run
while (r < width && comp[r] == comp[x])
// see if we can start an RLE run, at least 3 bytes same ++r;
if (rlerun == 0 && head - runstart >= 2 // output run up to r
&& comp[head] == comp[head-1] while (x < r) {
&& comp[head] == comp[head-2]) { int len = r-x;
// found a run. Flush non-run (if there is anything) and then start an RLE run if (len > 127) len = 127;
if (head - runstart > 2) { stbiw__write_run_data(f, len, comp[x]);
stbiw__write_nonrle_data(f, head-2 - runstart, comp+runstart); x += len;
}
rlerun = 1;
runstart = head-2;
} }
} }
} }
// 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 ...@@ -686,6 +679,8 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat
/* Revision history /* Revision history
0.97 (2015-01-18)
fixed HDR asserts, rewrote HDR rle logic
0.96 (2015-01-17) 0.96 (2015-01-17)
add HDR output add HDR output
fix monochrome BMP fix monochrome BMP
......
...@@ -51,10 +51,24 @@ void test_ycbcr(void) ...@@ -51,10 +51,24 @@ void test_ycbcr(void)
} }
#endif #endif
float hdr_data[200][200][3];
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int w,h; int w,h;
//test_ycbcr(); //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) { if (argc > 1) {
int i, n; int i, n;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册