From bd6b0c166872c38289375b7acb807ee790e87096 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Tue, 27 Nov 2012 20:50:01 +0000 Subject: [PATCH] image: Make PNG writing an Image method. --- common/image.hpp | 18 +++-- common/image_png.cpp | 141 ++++++++----------------------------- retrace/glstate_images.cpp | 20 +++--- 3 files changed, 52 insertions(+), 127 deletions(-) diff --git a/common/image.hpp b/common/image.hpp index 2f927ce..7dd18c1 100644 --- a/common/image.hpp +++ b/common/image.hpp @@ -94,16 +94,21 @@ public: return true; } - bool writePNG(const char *filename) const; + bool + writePNG(std::ostream &os) const; + + inline bool + writePNG(const char *filename) const { + std::ofstream os(filename, std::ofstream::binary); + if (!os) { + return false; + } + return writePNG(os); + } double compare(Image &ref); }; -bool -writePixelsToBuffer(std::ostream &os, - unsigned char *pixels, - unsigned w, unsigned h, unsigned numChannels, - bool flipped); Image * readPNG(const char *filename); @@ -111,6 +116,7 @@ readPNG(const char *filename); const char * readPNMHeader(const char *buffer, size_t size, unsigned *channels, unsigned *width, unsigned *height); + } /* namespace image */ diff --git a/common/image_png.cpp b/common/image_png.cpp index 41ef176..dba07d4 100644 --- a/common/image_png.cpp +++ b/common/image_png.cpp @@ -43,34 +43,20 @@ namespace image { static const int png_compression_level = Z_BEST_SPEED; +static void +pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) +{ + std::ostream *os = (std::ostream *) png_get_io_ptr(png_ptr); + os->write((const char *)data, length); +} + bool -Image::writePNG(const char *filename) const { - FILE *fp; +Image::writePNG(std::ostream &os) const +{ png_structp png_ptr; png_infop info_ptr; - - fp = fopen(filename, "wb"); - if (!fp) - goto no_fp; - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - goto no_png; - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, NULL); - goto no_png; - } - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, &info_ptr); - goto no_png; - } - - png_init_io(png_ptr, fp); - int color_type; + switch (channels) { case 4: color_type = PNG_COLOR_TYPE_RGB_ALPHA; @@ -86,11 +72,29 @@ Image::writePNG(const char *filename) const { break; default: assert(0); - return false; + goto no_png; + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + goto no_png; + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_write_struct(&png_ptr, NULL); + goto no_png; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_write_struct(&png_ptr, &info_ptr); + goto no_png; } - png_set_IHDR(png_ptr, info_ptr, width, height, 8, color_type, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_write_fn(png_ptr, &os, pngWriteCallback, NULL); + + png_set_IHDR(png_ptr, info_ptr, width, height, 8, + color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); png_set_compression_level(png_ptr, png_compression_level); @@ -112,12 +116,9 @@ Image::writePNG(const char *filename) const { png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); return true; no_png: - fclose(fp); -no_fp: return false; } @@ -201,85 +202,5 @@ no_fp: } -static void -pngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) -{ - std::ostream *os = (std::ostream *) png_get_io_ptr(png_ptr); - os->write((const char *)data, length); -} - -bool -writePixelsToBuffer(std::ostream &os, - unsigned char *pixels, - unsigned width, unsigned height, unsigned numChannels, - bool flipped) -{ - png_structp png_ptr; - png_infop info_ptr; - int type; - - switch (numChannels) { - case 4: - type = PNG_COLOR_TYPE_RGB_ALPHA; - break; - case 3: - type = PNG_COLOR_TYPE_RGB; - break; - case 2: - type = PNG_COLOR_TYPE_GRAY_ALPHA; - break; - case 1: - type = PNG_COLOR_TYPE_GRAY; - break; - default: - goto no_png; - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - goto no_png; - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, NULL); - goto no_png; - } - - if (setjmp(png_jmpbuf(png_ptr))) { - png_destroy_write_struct(&png_ptr, &info_ptr); - goto no_png; - } - - png_set_write_fn(png_ptr, &os, pngWriteCallback, NULL); - - png_set_IHDR(png_ptr, info_ptr, width, height, 8, - type, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - - png_set_compression_level(png_ptr, png_compression_level); - - png_write_info(png_ptr, info_ptr); - - if (!flipped) { - for (unsigned y = 0; y < height; ++y) { - png_bytep row = (png_bytep)(pixels + y*width*numChannels); - png_write_rows(png_ptr, &row, 1); - } - } else { - unsigned y = height; - while (y--) { - png_bytep row = (png_bytep)(pixels + y*width*numChannels); - png_write_rows(png_ptr, &row, 1); - } - } - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - - return true; - -no_png: - return false; -} } /* namespace image */ diff --git a/retrace/glstate_images.cpp b/retrace/glstate_images.cpp index 295ebe8..dc930a8 100644 --- a/retrace/glstate_images.cpp +++ b/retrace/glstate_images.cpp @@ -422,26 +422,26 @@ dumpActiveTextureLevel(JSONWriter &json, Context &context, GLenum target, GLint json.writeBoolMember("__normalized__", true); json.writeIntMember("__channels__", channels); - GLubyte *pixels = new GLubyte[desc.depth*desc.width*desc.height*channels]; + image::Image *image = new image::Image(desc.width, desc.height*desc.depth, channels, true); context.resetPixelPackState(); if (context.ES) { - getTexImageOES(target, level, desc, pixels); + getTexImageOES(target, level, desc, image->pixels); } else { - glGetTexImage(target, level, format, GL_UNSIGNED_BYTE, pixels); + glGetTexImage(target, level, format, GL_UNSIGNED_BYTE, image->pixels); } context.restorePixelPackState(); json.beginMember("__data__"); std::stringstream ss; - image::writePixelsToBuffer(ss, pixels, desc.width, desc.depth * desc.height, channels, true); + image->writePNG(ss); const std::string & s = ss.str(); json.writeBase64(s.data(), s.size()); json.endMember(); // __data__ - delete [] pixels; + delete image; json.endObject(); } @@ -880,25 +880,23 @@ dumpReadBufferImage(JSONWriter &json, GLint width, GLint height, GLenum format, } #endif - GLubyte *pixels = new GLubyte[width*height*channels]; + image::Image *image = new image::Image(width, height, channels, true); // TODO: reset imaging state too context.resetPixelPackState(); - glReadPixels(0, 0, width, height, format, type, pixels); + glReadPixels(0, 0, width, height, format, type, image->pixels); context.restorePixelPackState(); json.beginMember("__data__"); std::stringstream ss; - image::writePixelsToBuffer(ss, pixels, width, height, channels, true); - //std::cerr <<" Before = "<<(width * height * channels * sizeof *pixels) - // <<", after = "<