我正在尝试截屏并在具有c ++的Linux系统上的绘图区域中显示内容。
我正在合并来自不同帖子的代码。截取屏幕快照时,该垫很好,可以使用imshow显示内容,但是一旦放在on_draw函数中,尺寸,行和列就正确了,但是数据很差。
更新:通过从on_draw回调中删除屏幕,解决了该问题。为什么要阻止从回调内部读取垫子?
来源: screenshot, using opencv with gtkmm
HelloWorld.h
#include <gtkmm.h>
#include "ScreenDisplay.h"
class HelloWorld : public Gtk::Window
{
public:
HelloWorld();
virtual ~HelloWorld();
protected:
Gtk::Box m_box;
Gtk::Notebook m_notebook;
void on_button_clicked();
private:
ScreenDisplay m_screenDisplay;
Gtk::ScrolledWindow m_scrolledWindow;
Gtk::Button m_button;
};
HelloWorld.cpp
#include "HelloWorld.h"
HelloWorld::HelloWorld()
{
m_scrolledWindow.set_min_content_width(1000);
m_scrolledWindow.set_min_content_height(1000);
m_scrolledWindow.add(m_screenDisplay);
m_button.signal_clicked().connect(sigc::mem_fun(*this, &HelloWorld::on_button_clicked));
m_button.set_label("screenshot");
m_box.set_orientation(Gtk::ORIENTATION_VERTICAL);
m_box.pack_start(m_scrolledWindow, TRUE, TRUE);
m_box.pack_start(m_button, FALSE, FALSE);
add(m_box);
show_all();
}
HelloWorld::~HelloWorld()
{
}
void HelloWorld::on_button_clicked()
{
m_screenDisplay.TakeScreenshot();
}
ScreenDisplay.h
#include <gtkmm.h>
#include "opencv2/core/core.hpp"
class ScreenDisplay : public Gtk::DrawingArea
{
public:
ScreenDisplay();
virtual ~ScreenDisplay();
void TakeScreenshot();
protected:
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
private:
cv::Mat m_screenShot;
};
ScreenDisplay.cpp
#include "ScreenDisplay.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "opencv2/imgproc/imgproc.hpp"
#include <gdkmm/pixbuf.h>
#include <cairomm/context.h>
#include <gdkmm/general.h>
using namespace cv;
struct ScreenShot
{
ScreenShot(int x, int y, int width, int height):
x(x),
y(y),
width(width),
height(height)
{
display = XOpenDisplay(nullptr);
root = DefaultRootWindow(display);
init = true;
}
void operator() (cv::Mat& cvImg)
{
if(init == true)
init = false;
else
XDestroyImage(img);
img = XGetImage(display, root, x, y, width, height, AllPlanes, ZPixmap);
cvImg = cv::Mat(height, width, CV_8UC4, img->data);
}
~ScreenShot()
{
if(init == false)
XDestroyImage(img);
XCloseDisplay(display);
}
Display* display;
Window root;
int x,y,width,height;
XImage* img;
bool init;
};
ScreenDisplay::ScreenDisplay()
{
}
ScreenDisplay::~ScreenDisplay() { }
void ScreenDisplay::TakeScreenshot()
{
ScreenShot screen(0, 0, 1920, 1080);
screen(m_screenShot);
Glib::RefPtr<Gdk::Window> win = get_window();
Gdk::Rectangle r(0, 0, get_allocation().get_width(), get_allocation().get_height());
win->invalidate_rect(r, false);
}
bool ScreenDisplay::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
{
if (!m_screenShot.empty())
{
cv::Mat cv_frame1;
cv::cvtColor (m_screenShot, cv_frame1, CV_BGR2RGB);
Gdk::Cairo::set_source_pixbuf (cr, Gdk::Pixbuf::create_from_data(cv_frame1.data, Gdk::COLORSPACE_RGB, false, 8, cv_frame1.cols, cv_frame1.rows, cv_frame1.step));
cr->paint();
}
return true;
}