From e07b5c7e102020110d4ded59710e1d41c63039ad Mon Sep 17 00:00:00 2001 From: holoeye-photonics Date: Tue, 2 May 2017 11:59:19 +0200 Subject: [PATCH] Added function core::captureWindow() to capture the current screen into a ImageData object. Also added a function overload to save it to a png file. --- oxygine/src/core/gl/oxgl.cpp | 4 +++ oxygine/src/core/gl/oxgl.h | 6 +++- oxygine/src/core/oxygine.cpp | 57 ++++++++++++++++++++++++++++++++++++ oxygine/src/core/oxygine.h | 6 ++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/oxygine/src/core/gl/oxgl.cpp b/oxygine/src/core/gl/oxgl.cpp index 9b00b5590..3fcfee874 100644 --- a/oxygine/src/core/gl/oxgl.cpp +++ b/oxygine/src/core/gl/oxgl.cpp @@ -120,6 +120,8 @@ extern "C" {} GLAPI GLint APIENTRY def_glGetAttribLocation(GLuint program, const GLchar* name) {return 0;} + GLAPI void APIENTRY def_glReadPixels(GLint x​, GLint y​, GLsizei width​, GLsizei height​, GLenum format​, GLenum type​, GLvoid * data​) + {} //!--defgl-end--! //!--_gl-begin--! @@ -171,6 +173,7 @@ extern "C" PFNGLBLENDFUNCSEPARATEPROC _glBlendFuncSeparate = 0; PFNGLBLENDEQUATIONSEPARATEPROC _glBlendEquationSeparate = 0; PFNGLGETATTRIBLOCATIONPROC _glGetAttribLocation = 0; + PFNGLREADPIXELSPROC _glReadPixels = 0; //!--_gl-end--! } @@ -230,6 +233,7 @@ int initGLExtensions(myGetProcAdress func) GETFUNC(_glBlendFuncSeparate, def_glBlendFuncSeparate, PFNGLBLENDFUNCSEPARATEPROC, "glBlendFuncSeparate"); GETFUNC(_glBlendEquationSeparate, def_glBlendEquationSeparate, PFNGLBLENDEQUATIONSEPARATEPROC, "glBlendEquationSeparate"); GETFUNC(_glGetAttribLocation, def_glGetAttribLocation, PFNGLGETATTRIBLOCATIONPROC, "glGetAttribLocation"); + GETFUNC(_glReadPixels, def_glReadPixels, PFNGLREADPIXELSPROC, "glReadPixels"); //!--getfunc-end--! return missing; diff --git a/oxygine/src/core/gl/oxgl.h b/oxygine/src/core/gl/oxgl.h index 4f01870bf..5d2421559 100644 --- a/oxygine/src/core/gl/oxgl.h +++ b/oxygine/src/core/gl/oxgl.h @@ -23,6 +23,8 @@ # define GL_ETC1_RGB8_OES 0x8D64 +typedef void (APIENTRYP PFNGLREADPIXELSPROC) (GLint x​, GLint y​, GLsizei width​, GLsizei height​, GLenum format​, GLenum type​, GLvoid * data​); + extern "C" { //!--pfngl-begin--! @@ -74,6 +76,7 @@ extern "C" extern PFNGLBLENDFUNCSEPARATEPROC _glBlendFuncSeparate; extern PFNGLBLENDEQUATIONSEPARATEPROC _glBlendEquationSeparate; extern PFNGLGETATTRIBLOCATIONPROC _glGetAttribLocation; + extern PFNGLREADPIXELSPROC _glReadPixels; //!--pfngl-end--! } @@ -179,6 +182,7 @@ extern "C" #define oxglBlendFuncSeparate DECLARE_GLEXT(glBlendFuncSeparate) #define oxglBlendEquationSeparate DECLARE_GLEXT(glBlendEquationSeparate) #define oxglGetAttribLocation DECLARE_GLEXT(glGetAttribLocation) +#define oxglReadPixels DECLARE_GLEXT(glReadPixels) //!--oxgl-end--! @@ -191,4 +195,4 @@ namespace oxygine {void checkGLError();} typedef void* (*myGetProcAdress)(const char*); /**returns number of missing functions/extensions*/ -int initGLExtensions(myGetProcAdress); \ No newline at end of file +int initGLExtensions(myGetProcAdress); diff --git a/oxygine/src/core/oxygine.cpp b/oxygine/src/core/oxygine.cpp index 618392264..d0a79b6c5 100644 --- a/oxygine/src/core/oxygine.cpp +++ b/oxygine/src/core/oxygine.cpp @@ -549,6 +549,63 @@ namespace oxygine } #endif + void captureWindow(ImageData &image) + { + Point size = core::getDisplaySize(); + + size_t memsize = size.x * size.y * 4; + + image = ImageData(size.x, size.y, size.y * 4, TF_R8G8B8A8, malloc(memsize)); + + memset(image.data, 0, memsize); + + oxglReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, image.data); + } + +#ifdef OX_HAVE_LIBPNG + bool captureWindow(const char *pngFilename) + { + FILE *fp = fopen(pngFilename, "wb"); + + if(fp == NULL) + return false; + + ImageData data; + + captureWindow(data); + + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_infop info_ptr = png_create_info_struct(png_ptr); + + OX_ASSERT(png_ptr != NULL); + OX_ASSERT(info_ptr != NULL); + + setjmp(png_jmpbuf(png_ptr)); + + png_set_IHDR(png_ptr, info_ptr, data.w, data.h, + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_init_io(png_ptr, fp); + + png_write_info(png_ptr, info_ptr); + + for(int r = 0; r < data.h; ++r) + png_write_row(png_ptr, data.data + ((data.h - r - 1) * data.w * 4)); + + png_write_end(png_ptr, NULL); + + fclose(fp); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + + free(data.data); + + return true; + } +#endif + void reset() { log::messageln("core::reset()"); diff --git a/oxygine/src/core/oxygine.h b/oxygine/src/core/oxygine.h index 06383cc4c..660a1f38c 100644 --- a/oxygine/src/core/oxygine.h +++ b/oxygine/src/core/oxygine.h @@ -118,6 +118,12 @@ namespace oxygine SDL_Window* getWindow(); #endif + void captureWindow(ImageData &image); + +#ifdef OX_HAVE_LIBPNG + bool captureWindow(const char *pngFilename); +#endif + enum { EVENT_SYSTEM = sysEventID('c', 'S', 'y'), //events from SDL