mirror of
https://github.com/fltk/fltk.git
synced 2026-05-31 22:04:26 +08:00
Create virtual Fl_RGB_Image* Fl_Gl_Window_Driver::capture_gl_rectangle()
This commit is contained in:
@@ -51,6 +51,7 @@ class Fl_Gl_Window_Driver;
|
|||||||
class FL_EXPORT Fl_Gl_Window : public Fl_Window {
|
class FL_EXPORT Fl_Gl_Window : public Fl_Window {
|
||||||
friend class Fl_Gl_Window_Driver;
|
friend class Fl_Gl_Window_Driver;
|
||||||
friend class _Fl_Gl_Overlay;
|
friend class _Fl_Gl_Overlay;
|
||||||
|
friend class Fl_OpenGL_Display_Device;
|
||||||
Fl_Gl_Window_Driver *pGlWindowDriver;
|
Fl_Gl_Window_Driver *pGlWindowDriver;
|
||||||
|
|
||||||
/** Returns a pointer to the window's Fl_Gl_Window_Driver object */
|
/** Returns a pointer to the window's Fl_Gl_Window_Driver object */
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ public:
|
|||||||
virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
|
virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
|
||||||
virtual int genlistsize() { return 0; } // support for gl_draw()
|
virtual int genlistsize() { return 0; } // support for gl_draw()
|
||||||
virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum);
|
virtual Fl_Font_Descriptor** fontnum_to_fontdescriptor(int fnum);
|
||||||
|
virtual Fl_RGB_Image* capture_gl_rectangle(int x, int y, int w, int h);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* Fl_Gl_Window_Driver_H */
|
#endif /* Fl_Gl_Window_Driver_H */
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ class Fl_Cocoa_Gl_Window_Driver : public Fl_Gl_Window_Driver {
|
|||||||
virtual void redraw_overlay();
|
virtual void redraw_overlay();
|
||||||
virtual void gl_start();
|
virtual void gl_start();
|
||||||
virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
|
virtual char *alpha_mask_for_string(const char *str, int n, int w, int h);
|
||||||
|
virtual Fl_RGB_Image* capture_gl_rectangle(int x, int y, int w, int h);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Describes crap needed to create a GLContext.
|
// Describes crap needed to create a GLContext.
|
||||||
@@ -245,4 +246,56 @@ void Fl_Cocoa_Gl_Window_Driver::gl_start() {
|
|||||||
Fl_Cocoa_Window_Driver::gl_start(gl_start_context);
|
Fl_Cocoa_Window_Driver::gl_start(gl_start_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert BGRA to RGB and also exchange top and bottom
|
||||||
|
static uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth)
|
||||||
|
{
|
||||||
|
uchar *newimg = new uchar[3*w*h];
|
||||||
|
uchar *to = newimg;
|
||||||
|
for (int i = h-1; i >= 0; i--) {
|
||||||
|
uchar *from = baseAddress + i * mByteWidth;
|
||||||
|
for (int j = 0; j < w; j++, from += 4) {
|
||||||
|
#if defined(__ppc__) && __ppc__
|
||||||
|
memcpy(to, from + 1, 3);
|
||||||
|
to += 3;
|
||||||
|
#else
|
||||||
|
*(to++) = *(from+2);
|
||||||
|
*(to++) = *(from+1);
|
||||||
|
*(to++) = *from;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] baseAddress;
|
||||||
|
return newimg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Fl_RGB_Image* Fl_Cocoa_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
Fl_Gl_Window* glw = pWindow;
|
||||||
|
float factor = glw->pixels_per_unit();
|
||||||
|
if (factor != 1) {
|
||||||
|
w *= factor; h *= factor; x *= factor; y *= factor;
|
||||||
|
}
|
||||||
|
Fl_Cocoa_Window_Driver::GLcontext_makecurrent(glw->context());
|
||||||
|
Fl_Cocoa_Window_Driver::flush_context(glw->context()); // to capture also the overlay and for directGL demo
|
||||||
|
// Read OpenGL context pixels directly.
|
||||||
|
// For extra safety, save & restore OpenGL states that are changed
|
||||||
|
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
|
||||||
|
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
||||||
|
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
||||||
|
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
||||||
|
// Read a block of pixels from the frame buffer
|
||||||
|
int mByteWidth = w * 4;
|
||||||
|
mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
|
||||||
|
uchar *baseAddress = new uchar[mByteWidth * h];
|
||||||
|
glReadPixels(x, glw->pixel_h() - (y+h), w, h,
|
||||||
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, baseAddress);
|
||||||
|
glPopClientAttrib();
|
||||||
|
baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth);
|
||||||
|
Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w);
|
||||||
|
img->alloc_array = 1;
|
||||||
|
Fl_Cocoa_Window_Driver::flush_context(glw->context());
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAVE_GL
|
#endif // HAVE_GL
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
#include "../../config_lib.h"
|
#include "../../config_lib.h"
|
||||||
#include <FL/Fl_Gl_Window.H>
|
#include <FL/Fl_Gl_Window.H>
|
||||||
|
#include "../../Fl_Gl_Window_Driver.H"
|
||||||
#include <FL/Fl_Image.H>
|
#include <FL/Fl_Image.H>
|
||||||
|
#include "../../Fl_Screen_Driver.H"
|
||||||
|
#include "../../Fl_Window_Driver.H"
|
||||||
#include <FL/gl.h>
|
#include <FL/gl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -35,69 +38,17 @@ Fl_OpenGL_Display_Device::Fl_OpenGL_Display_Device(Fl_OpenGL_Graphics_Driver *gr
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef FL_CFG_GFX_QUARTZ
|
|
||||||
#include "../../Fl_Gl_Window_Driver.H"
|
|
||||||
#include "../Cocoa/Fl_Cocoa_Window_Driver.H"
|
|
||||||
|
|
||||||
// convert BGRA to RGB and also exchange top and bottom
|
|
||||||
static uchar *convert_BGRA_to_RGB(uchar *baseAddress, int w, int h, int mByteWidth)
|
|
||||||
{
|
|
||||||
uchar *newimg = new uchar[3*w*h];
|
|
||||||
uchar *to = newimg;
|
|
||||||
for (int i = h-1; i >= 0; i--) {
|
|
||||||
uchar *from = baseAddress + i * mByteWidth;
|
|
||||||
for (int j = 0; j < w; j++, from += 4) {
|
|
||||||
#if defined(__ppc__) && __ppc__
|
|
||||||
memcpy(to, from + 1, 3);
|
|
||||||
to += 3;
|
|
||||||
#else
|
|
||||||
*(to++) = *(from+2);
|
|
||||||
*(to++) = *(from+1);
|
|
||||||
*(to++) = *from;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete[] baseAddress;
|
|
||||||
return newimg;
|
|
||||||
}
|
|
||||||
|
|
||||||
Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window* glw, int x, int y, int w, int h)
|
Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window* glw, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
float factor = glw->pixels_per_unit();
|
return glw->gl_driver()->capture_gl_rectangle(x, y, w, h);
|
||||||
if (factor != 1) {
|
|
||||||
w *= factor; h *= factor; x *= factor; y *= factor;
|
|
||||||
}
|
|
||||||
Fl_Cocoa_Window_Driver::GLcontext_makecurrent(glw->context());
|
|
||||||
Fl_Cocoa_Window_Driver::flush_context(glw->context()); // to capture also the overlay and for directGL demo
|
|
||||||
// Read OpenGL context pixels directly.
|
|
||||||
// For extra safety, save & restore OpenGL states that are changed
|
|
||||||
glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
|
|
||||||
glPixelStorei(GL_PACK_ALIGNMENT, 4); /* Force 4-byte alignment */
|
|
||||||
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
|
|
||||||
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
|
|
||||||
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
|
|
||||||
// Read a block of pixels from the frame buffer
|
|
||||||
int mByteWidth = w * 4;
|
|
||||||
mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes
|
|
||||||
uchar *baseAddress = new uchar[mByteWidth * h];
|
|
||||||
glReadPixels(x, glw->pixel_h() - (y+h), w, h,
|
|
||||||
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, baseAddress);
|
|
||||||
glPopClientAttrib();
|
|
||||||
baseAddress = convert_BGRA_to_RGB(baseAddress, w, h, mByteWidth);
|
|
||||||
Fl_RGB_Image *img = new Fl_RGB_Image(baseAddress, w, h, 3, 3 * w);
|
|
||||||
img->alloc_array = 1;
|
|
||||||
Fl_Cocoa_Window_Driver::flush_context(glw->context());
|
|
||||||
return img;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
/* Captures a rectangle of a Fl_Gl_Window and returns it as a RGB image.
|
||||||
|
This is the platform-independent version. Some platforms may re-implement it.
|
||||||
#include "../../Fl_Screen_Driver.H"
|
|
||||||
#include "../../Fl_Window_Driver.H"
|
|
||||||
Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window *glw, int x, int y, int w, int h)
|
|
||||||
/* captures a rectangle of a Fl_Gl_Window window, and returns it as a RGB image
|
|
||||||
*/
|
*/
|
||||||
|
Fl_RGB_Image* Fl_Gl_Window_Driver::capture_gl_rectangle(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
|
Fl_Gl_Window *glw = pWindow;
|
||||||
glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo
|
glw->flush(); // forces a GL redraw, necessary for the glpuzzle demo
|
||||||
// Read OpenGL context pixels directly.
|
// Read OpenGL context pixels directly.
|
||||||
// For extra safety, save & restore OpenGL states that are changed
|
// For extra safety, save & restore OpenGL states that are changed
|
||||||
@@ -135,5 +86,3 @@ Fl_RGB_Image* Fl_OpenGL_Display_Device::capture_gl_rectangle(Fl_Gl_Window *glw,
|
|||||||
img->alloc_array = 1;
|
img->alloc_array = 1;
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
Reference in New Issue
Block a user