00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <cstdio>
00011 #include <celutil/debug.h>
00012 #include "../celengine/gl.h"
00013 #include <celengine/celestia.h>
00014 #include "imagecapture.h"
00015
00016 extern "C" {
00017 #ifdef _WIN32
00018 #include "jpeglib.h"
00019 #else
00020 #ifdef MACOSX
00021 #include "../celestia/Celestia.app.skel/Contents/Frameworks/Headers/jpeglib.h"
00022 #else
00023 #include <jpeglib.h>
00024 #endif
00025 #endif
00026 }
00027
00028 #ifdef MACOSX
00029 #include "../celestia/Celestia.app.skel/Contents/Frameworks/Headers/png.h"
00030 #else
00031 #include "png.h"
00032 #endif
00033
00034
00035 #ifndef png_jmpbuf
00036 #define png_jmpbuf(png_ptr) png_ptr->jmpbuf
00037 #endif
00038
00039
00040 #if PNG_LIBPNG_VER < 10004
00041 #define png_set_palette_to_rgb(p) png_set_expand(p)
00042 #define png_set_gray_1_2_4_to_8(p) png_set_expand(p)
00043 #define png_set_tRNS_to_alpha(p) png_set_expand(p)
00044 #endif
00045
00046 using namespace std;
00047
00048
00049 bool CaptureGLBufferToJPEG(const string& filename,
00050 int x, int y,
00051 int width, int height)
00052 {
00053 int rowStride = (width * 3 + 3) & ~0x3;
00054 int imageSize = height * rowStride;
00055 unsigned char* pixels = new unsigned char[imageSize];
00056
00057 glReadBuffer(GL_BACK);
00058 glReadPixels(x, y, width, height,
00059 GL_RGB, GL_UNSIGNED_BYTE,
00060 pixels);
00061
00062
00063
00064 FILE* out;
00065 out = fopen(filename.c_str(), "wb");
00066 if (out == NULL)
00067 {
00068 DPRINTF(0, "Can't open screen capture file '%s'\n", filename.c_str());
00069 delete[] pixels;
00070 return false;
00071 }
00072
00073 struct jpeg_compress_struct cinfo;
00074
00075 struct jpeg_error_mgr jerr;
00076 JSAMPROW row[1];
00077
00078 cinfo.err = jpeg_std_error(&jerr);
00079 jpeg_create_compress(&cinfo);
00080
00081 jpeg_stdio_dest(&cinfo, out);
00082
00083 cinfo.image_width = width;
00084 cinfo.image_height = height;
00085 cinfo.input_components = 3;
00086 cinfo.in_color_space = JCS_RGB;
00087
00088 jpeg_set_defaults(&cinfo);
00089
00090
00091
00092 jpeg_start_compress(&cinfo, TRUE);
00093
00094 while (cinfo.next_scanline < cinfo.image_height)
00095 {
00096 row[0] = &pixels[rowStride * (cinfo.image_height - cinfo.next_scanline - 1)];
00097 (void) jpeg_write_scanlines(&cinfo, row, 1);
00098 }
00099
00100 jpeg_finish_compress(&cinfo);
00101 fclose(out);
00102 jpeg_destroy_compress(&cinfo);
00103
00104 delete[] pixels;
00105
00106 return true;
00107 }
00108
00109
00110 void PNGWriteData(png_structp png_ptr, png_bytep data, png_size_t length)
00111 {
00112 FILE* fp = (FILE*) png_get_io_ptr(png_ptr);
00113 fwrite((void*) data, 1, length, fp);
00114 }
00115
00116
00117 bool CaptureGLBufferToPNG(const string& filename,
00118 int x, int y,
00119 int width, int height)
00120 {
00121 int rowStride = (width * 3 + 3) & ~0x3;
00122 int imageSize = height * rowStride;
00123 unsigned char* pixels = new unsigned char[imageSize];
00124
00125 glReadBuffer(GL_BACK);
00126 glReadPixels(x, y, width, height,
00127 GL_RGB, GL_UNSIGNED_BYTE,
00128 pixels);
00129
00130
00131
00132 FILE* out;
00133 out = fopen(filename.c_str(), "wb");
00134 if (out == NULL)
00135 {
00136 DPRINTF(0, "Can't open screen capture file '%s'\n", filename.c_str());
00137 delete[] pixels;
00138 return false;
00139 }
00140
00141 png_bytep* row_pointers = new png_bytep[height];
00142 for (int i = 0; i < height; i++)
00143 row_pointers[i] = (png_bytep) &pixels[rowStride * (height - i - 1)];
00144
00145 png_structp png_ptr;
00146 png_infop info_ptr;
00147
00148 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
00149 NULL, NULL, NULL);
00150
00151 if (png_ptr == NULL)
00152 {
00153 DPRINTF(0, "Screen capture: error allocating png_ptr\n");
00154 fclose(out);
00155 delete[] pixels;
00156 delete[] row_pointers;
00157 return false;
00158 }
00159
00160 info_ptr = png_create_info_struct(png_ptr);
00161 if (info_ptr == NULL)
00162 {
00163 DPRINTF(0, "Screen capture: error allocating info_ptr\n");
00164 fclose(out);
00165 delete[] pixels;
00166 delete[] row_pointers;
00167 png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
00168 return false;
00169 }
00170
00171 if (setjmp(png_jmpbuf(png_ptr)))
00172 {
00173 DPRINTF(0, "Error writing PNG file '%s'\n", filename.c_str());
00174 fclose(out);
00175 delete[] pixels;
00176 delete[] row_pointers;
00177 png_destroy_write_struct(&png_ptr, &info_ptr);
00178 return false;
00179 }
00180
00181
00182 png_set_write_fn(png_ptr, (void*) out, PNGWriteData, NULL);
00183
00184 png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
00185 png_set_IHDR(png_ptr, info_ptr,
00186 width, height,
00187 8,
00188 PNG_COLOR_TYPE_RGB,
00189 PNG_INTERLACE_NONE,
00190 PNG_COMPRESSION_TYPE_DEFAULT,
00191 PNG_FILTER_TYPE_DEFAULT);
00192
00193 png_write_info(png_ptr, info_ptr);
00194 png_write_image(png_ptr, row_pointers);
00195 png_write_end(png_ptr, info_ptr);
00196
00197
00198 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
00199 delete[] row_pointers;
00200 delete[] pixels;
00201 fclose(out);
00202
00203 return true;
00204 }
00205
00206