diff options
-rw-r--r-- | src/client/video.cc | 39 | ||||
-rw-r--r-- | src/render/pngfile.cc | 69 |
2 files changed, 101 insertions, 7 deletions
diff --git a/src/client/video.cc b/src/client/video.cc index 2c1fe6b..aed25ae 100644 --- a/src/client/video.cc +++ b/src/client/video.cc @@ -7,11 +7,13 @@ #include <fstream> #include <sstream> +#include "auxiliary/functions.h" #include "client/video.h" #include "client/view.h" #include "render/camera.h" #include "render/render.h" #include "render/tga.h" +#include "render/pngfile.h" #include "core/core.h" #include "filesystem/filesystem.h" #include "sys/sys.h" @@ -30,6 +32,8 @@ int height = 0; int width_prev = 0; int height_prev = 0; +int screenshot_number = 0; + const int width_default = 1024; const int height_default = 768; @@ -39,6 +43,8 @@ core::Cvar *r_width; core::Cvar *r_height; core::Cvar *r_fullscreen; +core::Cvar *screenshotformat; + void reset() { // setup our viewport. @@ -65,6 +71,9 @@ bool init() r_fullscreen = core::Cvar::get("r_fullscreen", "0", core::Cvar::Archive); r_fullscreen->set_info("[bool] enable or disable fullscreen video"); + screenshotformat = core::Cvar::get("screenshotformat", "tga", core::Cvar::Archive); + screenshotformat->set_info("[string] screenshot format: tga png"); + int bpp = 0; int flags = 0; @@ -183,27 +192,39 @@ void shutdown() void screenshot() { - int number = 0; bool available = false; std::string shortname; std::string filename; + const int TYPETGA = 0; + const int TYPEPNG = 1; + int filetype = TYPETGA; // make sure the screenshots folder exists filename.assign(filesystem::writedir()); filename.append("screenshots/"); sys::mkdir(filename); + aux::lowercase(screenshotformat->str()); + + if (screenshotformat->str().compare("png") == 0) { + filetype = TYPEPNG; + } else { + filetype = TYPETGA; + (*screenshotformat) = "tga"; + } + // find the first available screenshotxxx.tga do { std::stringstream nstr; - nstr << number; + nstr << screenshot_number; shortname.assign(nstr.str()); while(shortname.size() < 3) shortname.insert(0, 1, '0'); shortname.insert(0, "screenshots/osirion"); - shortname.append(".tga"); + shortname.append("."); + shortname.append(screenshotformat->str()); filename.assign(filesystem::writedir()); filename.append(shortname); @@ -211,10 +232,10 @@ void screenshot() FILE *handle = fopen(filename.c_str(), "r"); if (handle) { fclose(handle); - number++; } else { - available = true; + available = true; } + screenshot_number++; } while (!available); render::Image image((unsigned int)video::width, (unsigned int)video::height, 3); @@ -222,7 +243,13 @@ void screenshot() glReadPixels(0, 0, (GLsizei) video::width, (GLsizei) video::height, GL_RGB, GL_UNSIGNED_BYTE, (void *) image.data()); - render::TGA::save(filename.c_str(), image); + image.flip(); + + if (filetype == TYPEPNG) { + render::PNG::save(filename.c_str(), image); + } else if (filetype == TYPETGA) { + render::TGA::save(filename.c_str(), image); + } } diff --git a/src/render/pngfile.cc b/src/render/pngfile.cc index 14884f0..27cfd8f 100644 --- a/src/render/pngfile.cc +++ b/src/render/pngfile.cc @@ -116,7 +116,74 @@ Image *PNG::load(const char *filename) void PNG::save(const char *filename, Image & image) { - con_warn << "PNG::save stub" << std::endl; + + FILE *png_file = fopen(filename, "wb"); + if (!png_file) { + con_warn << "Could not write " << filename << std::endl; + return; + } + + /* initialize stuff */ + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) { + fclose(png_file); + con_warn << "Error writing " << filename << ": png_create_write_struct failed!" << std::endl; + return; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fclose(png_file); + con_warn << "Error writing " << filename << ": png_create_info_struct failed!" << std::endl; + return; + } + + if (setjmp(png_jmpbuf(png_ptr))) { + con_warn << "Error reading " << filename << ": error during init_io!" << std::endl; + fclose(png_file); + return; + } + + png_init_io(png_ptr, png_file); + + /* write header */ + if (setjmp(png_jmpbuf(png_ptr))) { + con_warn << "Error writing " << filename << ": error writing header!" << std::endl; + fclose(png_file); + return; + } + + png_set_IHDR(png_ptr, info_ptr, image.width(), image.height(), 8, PNG_COLOR_TYPE_RGB, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_write_info(png_ptr, info_ptr); + + /* write image data */ + if (setjmp(png_jmpbuf(png_ptr))) { + con_warn << "Error writing " << filename << ": error writing header!" << std::endl; + fclose(png_file); + return; + } + + png_bytep row_pointers[image.height()]; + + for (size_t i = 0; i < image.height(); i++) + row_pointers[i] = (png_bytep) image[i * image.width() * image.channels()]; + + png_write_image(png_ptr, row_pointers); + + /* end write */ + if (setjmp(png_jmpbuf(png_ptr))) { + con_warn << "Error writing " << filename << std::endl; + fclose(png_file); + return; + } + + png_write_end(png_ptr, NULL); + + fclose(png_file); + + con_print << "Wrote " << filename << std::endl; } } |