Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions modules/highgui/include/opencv2/highgui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ for image display). **waitKey(25)** will display a frame and wait approximately
press (suitable for displaying a video frame-by-frame). To remove the window, use cv::destroyWindow.

@note [__Windows Backend Only__] Pressing Ctrl+C will copy the image to the clipboard. Pressing Ctrl+S will show a dialog to save the image.
@note [__Wayland Backend Only__] Supoorting format is extended.
- If the image is 8-bit signed, the pixels are biased by 128. That is, the
value range [-128,127] is mapped to [0,255].
- If the image is 16-bit signed, the pixels are divided by 256 and biased by 128. That is, the
value range [-32768,32767] is mapped to [0,255].

@param winname Name of the window.
@param mat Image to be shown.
Expand Down Expand Up @@ -394,6 +399,8 @@ CV_EXPORTS_W void resizeWindow(const String& winname, const cv::Size& size);
@param winname Name of the window.
@param x The new x-coordinate of the window.
@param y The new y-coordinate of the window.

@note [__Wayland Backend Only__] This function is not supported by the Wayland protocol limitation.
*/
CV_EXPORTS_W void moveWindow(const String& winname, int x, int y);

Expand All @@ -404,6 +411,8 @@ The function setWindowProperty enables changing properties of a window.
@param winname Name of the window.
@param prop_id Window property to edit. The supported operation flags are: (cv::WindowPropertyFlags)
@param prop_value New value of the window property. The supported flags are: (cv::WindowFlags)

@note [__Wayland Backend Only__] This function is not supported.
*/
CV_EXPORTS_W void setWindowProperty(const String& winname, int prop_id, double prop_value);

Expand All @@ -421,6 +430,8 @@ The function getWindowProperty returns properties of a window.
@param prop_id Window property to retrieve. The following operation flags are available: (cv::WindowPropertyFlags)

@sa setWindowProperty

@note [__Wayland Backend Only__] This function is not supported.
*/
CV_EXPORTS_W double getWindowProperty(const String& winname, int prop_id);

Expand All @@ -431,6 +442,8 @@ The function getWindowImageRect returns the client screen coordinates, width and
@param winname Name of the window.

@sa resizeWindow moveWindow

@note [__Wayland Backend Only__] This function is not supported by the Wayland protocol limitation.
*/
CV_EXPORTS_W Rect getWindowImageRect(const String& winname);

Expand Down
1 change: 1 addition & 0 deletions modules/highgui/src/precomp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ void cvSetModeWindow_WinRT(const char* name, double prop_value);
CvRect cvGetWindowRect_W32(const char* name);
CvRect cvGetWindowRect_GTK(const char* name);
CvRect cvGetWindowRect_COCOA(const char* name);
CvRect cvGetWindowRect_WAYLAND(const char* name);

double cvGetModeWindow_W32(const char* name);
double cvGetModeWindow_GTK(const char* name);
Expand Down
2 changes: 2 additions & 0 deletions modules/highgui/src/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ cv::Rect cv::getWindowImageRect(const String& winname)
return cvGetWindowRect_GTK(winname.c_str());
#elif defined (HAVE_COCOA)
return cvGetWindowRect_COCOA(winname.c_str());
#elif defined (HAVE_WAYLAND)
return cvGetWindowRect_WAYLAND(winname.c_str());
#else
return Rect(-1, -1, -1, -1);
#endif
Expand Down
138 changes: 107 additions & 31 deletions modules/highgui/src/window_wayland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,20 +84,73 @@ static int xkb_keysym_to_ascii(xkb_keysym_t keysym) {
return static_cast<int>(keysym & 0xff);
}

static void write_mat_to_xrgb8888(cv::Mat const &img_, void *data) {
// Validate destination data.
CV_CheckFalse((data == nullptr), "Destination Address must not be nullptr.");

// Validate source img parameters.
CV_CheckFalse(img_.empty(), "Source Mat must not be empty.");
const int ncn = img_.channels();
CV_CheckType(img_.type(),
( (ncn == 1) || (ncn == 3) || (ncn == 4)),
"Unsupported channels, please convert to 1, 3 or 4 channels"
);

static void draw_xrgb8888(void *d, uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
*((uint32_t *) d) = ((a << 24) | (r << 16) | (g << 8) | b);
}

static void write_mat_to_xrgb8888(cv::Mat const &img, void *data) {
CV_Assert(data != nullptr);
CV_Assert(img.isContinuous());
// The supported Mat depth is according to imshow() specification.
const int depth = CV_MAT_DEPTH(img_.type());
CV_CheckDepth(img_.type(),
( (depth == CV_8U) || (depth == CV_8S) ||
(depth == CV_16U) || (depth == CV_16S) ||
(depth == CV_32F) || (depth == CV_64F) ),
"Unsupported depth, please convert to CV_8U"
);

for (int y = 0; y < img.rows; y++) {
for (int x = 0; x < img.cols; x++) {
auto p = img.at<cv::Vec3b>(y, x);
draw_xrgb8888((char *) data + (y * img.cols + x) * 4, 0x00, p[2], p[1], p[0]);
}
// Convert to CV_8U
cv::Mat img;
const int mtype = CV_MAKE_TYPE(CV_8U, ncn);
switch(CV_MAT_DEPTH(depth))
{
case CV_8U:
img = img_; // do nothing.
break;
case CV_8S:
// [-128,127] -> [0,255]
img_.convertTo(img, mtype, 1.0, 128);
break;
case CV_16U:
// [0,65535] -> [0,255]
img_.convertTo(img, mtype, 1.0/255. );
break;
case CV_16S:
// [-32768,32767] -> [0,255]
img_.convertTo(img, mtype, 1.0/255. , 128);
break;
case CV_32F:
case CV_64F:
// [0, 1] -> [0,255]
img_.convertTo(img, mtype, 255.);
break;
default:
// it cannot be reachable.
break;
}
CV_CheckDepthEQ(CV_MAT_DEPTH(img.type()), CV_8U, "img should be CV_8U");

// XRGB8888 in Little Endian(Wayland Request) = [B8:G8:R8:X8] in data array.
// X is not used to show. So we can use cvtColor() with GRAY2BGRA or BGR2BGRA or copyTo().
cv::Mat dst(img.size(), CV_MAKE_TYPE(CV_8U, 4), (uint8_t*)data);
if(ncn == 1)
{
cvtColor(img, dst, cv::COLOR_GRAY2BGRA);
}
else if(ncn == 3)
{
cvtColor(img, dst, cv::COLOR_BGR2BGRA);
}
else
{
CV_CheckTrue(ncn==4, "Unexpected channels");
img.copyTo(dst);
}
}

Expand Down Expand Up @@ -232,10 +285,10 @@ class cv_wl_mouse {
&handle_pointer_axis, &handle_pointer_frame,
&handle_pointer_axis_source, &handle_pointer_axis_stop,
&handle_pointer_axis_discrete,
#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8
#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
&handle_axis_value120,
#endif
#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
&handle_axis_relative_direction,
#endif
};
Expand Down Expand Up @@ -284,7 +337,7 @@ class cv_wl_mouse {
CV_UNUSED(discrete);
}

#if WL_POINTER_AXIS_VALUE120_SINCE_VERSION >= 8
#ifdef WL_POINTER_AXIS_VALUE120_SINCE_VERSION
static void
handle_axis_value120(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t value120) {
CV_UNUSED(data);
Expand All @@ -294,7 +347,7 @@ class cv_wl_mouse {
}
#endif

#if WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION >= 9
#ifdef WL_POINTER_AXIS_RELATIVE_DIRECTION_SINCE_VERSION
static void
handle_axis_relative_direction(void *data, struct wl_pointer *wl_pointer, uint32_t axis, uint32_t direction) {
CV_UNUSED(data);
Expand Down Expand Up @@ -686,7 +739,7 @@ class cv_wl_window {

void show_image(cv::Mat const &image);

void create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata);
int create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change, void *userdata);

weak_ptr<cv_wl_trackbar> get_trackbar(std::string const &) const;

Expand Down Expand Up @@ -723,10 +776,10 @@ class cv_wl_window {
struct xdg_toplevel *xdg_toplevel_;
struct xdg_toplevel_listener xdgtop_listener_{
&handle_toplevel_configure, &handle_toplevel_close,
#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4
#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
&handle_toplevel_configure_bounds,
#endif
#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
&handle_toplevel_wm_capabilities,
#endif
};
Expand Down Expand Up @@ -775,7 +828,7 @@ class cv_wl_window {

static void handle_toplevel_close(void *data, struct xdg_toplevel *surface);

#if XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION >= 4
#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
static void
handle_toplevel_configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height)
{
Expand All @@ -786,7 +839,7 @@ class cv_wl_window {
}
#endif

#if XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION >= 5
#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
static void
handle_toplevel_wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities)
{
Expand Down Expand Up @@ -1527,13 +1580,7 @@ cv_wl_viewer::cv_wl_viewer(cv_wl_window *window, int flags)
}

void cv_wl_viewer::set_image(cv::Mat const &image) {
if (image.type() == CV_8UC1) {
cv::Mat bgr;
cv::cvtColor(image, bgr, CV_GRAY2BGR);
image_ = bgr.clone();
} else {
image_ = image.clone();
}
image_ = image.clone();
image_changed_ = true;
}

Expand Down Expand Up @@ -1642,6 +1689,11 @@ cv_wl_trackbar::cv_wl_trackbar(cv_wl_window *window, std::string name,
on_change_.value = value;
on_change_.data = data;
on_change_.callback = on_change;

// initilize slider_.value if value is not nullptr.
if (value != nullptr){
set_pos(*value);
}
}

std::string const &cv_wl_trackbar::name() const {
Expand All @@ -1657,6 +1709,12 @@ void cv_wl_trackbar::set_pos(int value) {
slider_.value = value;
slider_moved_ = true;
window_->show();

// Update user-ptr value and call on_change() function if cv_wl_trackbar::draw() is not called.
if(slider_moved_) {
on_change_.update(slider_.value);
on_change_.call(slider_.value);
}
}
}

Expand All @@ -1666,6 +1724,12 @@ void cv_wl_trackbar::set_max(int maxval) {
slider_.value = maxval;
slider_moved_ = true;
window_->show();

// Update user-ptr and call on_change() function if cv_wl_trackbar::draw() is not called.
if(slider_moved_) {
on_change_.update(slider_.value);
on_change_.call(slider_.value);
}
}
}

Expand Down Expand Up @@ -1836,8 +1900,9 @@ void cv_wl_window::show_image(cv::Mat const &image) {
this->show();
}

void cv_wl_window::create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change,
int cv_wl_window::create_trackbar(std::string const &name, int *value, int count, CvTrackbarCallback2 on_change,
void *userdata) {
int ret = 0;
auto exists = this->get_trackbar(name).lock();
if (!exists) {
auto trackbar =
Expand All @@ -1846,7 +1911,9 @@ void cv_wl_window::create_trackbar(std::string const &name, int *value, int coun
);
widgets_.emplace_back(trackbar);
widget_geometries_.emplace_back(0, 0, 0, 0);
ret = 1;
}
return ret;
}

weak_ptr<cv_wl_trackbar> cv_wl_window::get_trackbar(std::string const &trackbar_name) const {
Expand Down Expand Up @@ -2324,6 +2391,7 @@ std::string const &cv_wl_core::get_window_name(void *handle) {
}

bool cv_wl_core::create_window(std::string const &name, int flags) {
CV_CheckTrue(display_ != nullptr, "Display is not connected.");
auto window = std::make_shared<cv_wl_window>(display_, name, flags);
auto result = windows_.insert(std::make_pair(name, window));
handles_[window.get()] = window->get_title();
Expand Down Expand Up @@ -2402,6 +2470,13 @@ CV_IMPL void cvResizeWindow(const char *name, int width, int height) {
throw_system_error("Could not get window name", errno)
}

CvRect cvGetWindowRect_WAYLAND(const char* name)
{
CV_UNUSED(name);
CV_LOG_ONCE_WARNING(nullptr, "Function not implemented: User cannot get window rect in Wayland");
return cvRect(-1, -1, -1, -1);
}

CV_IMPL int cvCreateTrackbar(const char *name_bar, const char *window_name, int *value, int count,
CvTrackbarCallback on_change) {
CV_UNUSED(name_bar);
Expand All @@ -2416,10 +2491,11 @@ CV_IMPL int cvCreateTrackbar(const char *name_bar, const char *window_name, int

CV_IMPL int cvCreateTrackbar2(const char *trackbar_name, const char *window_name, int *val, int count,
CvTrackbarCallback2 on_notify, void *userdata) {
int ret = 0;
if (auto window = CvWlCore::getInstance().get_window(window_name))
window->create_trackbar(trackbar_name, val, count, on_notify, userdata);
ret = window->create_trackbar(trackbar_name, val, count, on_notify, userdata);

return 0;
return ret;
}

CV_IMPL int cvGetTrackbarPos(const char *trackbar_name, const char *window_name) {
Expand Down
10 changes: 10 additions & 0 deletions modules/highgui/test/test_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ inline void verify_size(const std::string &nm, const cv::Mat &img)
{
EXPECT_NO_THROW(imshow(nm, img));
EXPECT_EQ(-1, waitKey(200));

// see https://github.com/opencv/opencv/issues/25550
// Wayland backend is not supported getWindowImageRect().
string framework;
EXPECT_NO_THROW(framework = currentUIFramework());
if(framework == "WAYLAND")
{
return;
}

Rect rc;
EXPECT_NO_THROW(rc = getWindowImageRect(nm));
EXPECT_EQ(rc.size(), img.size());
Expand Down