gtkmm DrawingArea on_draw函数无法访问opencv mat

时间:2019-05-07 21:52:18

标签: c++ opencv gtk gtkmm

我正在尝试截屏并在具有c ++的Linux系统上的绘图区域中显示内容。

我正在合并来自不同帖子的代码。截取屏幕快照时,该垫很好,可以使用imshow显示内容,但是一旦放在on_draw函数中,尺寸,行和列就正确了,但是数据很差。

更新:通过从on_draw回调中删除屏幕,解决了该问题。为什么要阻止从回调内部读取垫子?

来源: screenshotusing 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;
}

0 个答案:

没有答案