]> git.cworth.org Git - apitrace/commitdiff
image: Make PNG writing an Image method.
authorJosé Fonseca <jfonseca@vmware.com>
Tue, 27 Nov 2012 20:50:01 +0000 (20:50 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Tue, 27 Nov 2012 20:50:01 +0000 (20:50 +0000)
common/image.hpp
common/image_png.cpp
retrace/glstate_images.cpp

index 2f927ce9a35e5407362c206c4d3738b244b826ed..7dd18c1225e821a0286ea11e0a73989be57acc51 100644 (file)
@@ -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 */
 
 
index 41ef1768499fc4b7ed3db8636b304617ea7db737..dba07d45ea14e4864d451b4896ea2723544a74b8 100644 (file)
@@ -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 */
index 295ebe8797d3396922533154731d8b910c5fef5e..dc930a8039b8c816b785ab363f444c791d80b469 100644 (file)
@@ -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 = "<<pngBufferSize << ", ratio = " << double(width * height * channels * sizeof *pixels)/pngBufferSize;
+    image->writePNG(ss);
     const std::string & s = ss.str();
     json.writeBase64(s.data(), s.size());
     json.endMember(); // __data__
 
-    delete [] pixels;
+    delete image;
     json.endObject();
 }