mirror of
https://github.com/opencv/opencv.git
synced 2026-07-30 15:53:03 +04:00
highgui: backends and plugins
This commit is contained in:
committed by
Alexander Alekhin
parent
7d66f1e391
commit
70f69cb265
@@ -40,14 +40,159 @@
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include <map>
|
||||
#include "backend.hpp"
|
||||
|
||||
#include "opencv2/core/opengl.hpp"
|
||||
#include "opencv2/core/utils/logger.hpp"
|
||||
|
||||
// in later times, use this file as a dispatcher to implementations like cvcap.cpp
|
||||
|
||||
|
||||
using namespace cv;
|
||||
using namespace cv::highgui_backend;
|
||||
|
||||
namespace cv {
|
||||
|
||||
Mutex& getWindowMutex()
|
||||
{
|
||||
static Mutex* g_window_mutex = new Mutex();
|
||||
return *g_window_mutex;
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
typedef std::map<std::string, highgui_backend::UIWindowBase::Ptr> WindowsMap_t;
|
||||
static WindowsMap_t& getWindowsMap()
|
||||
{
|
||||
static WindowsMap_t g_windowsMap;
|
||||
return g_windowsMap;
|
||||
}
|
||||
|
||||
static std::shared_ptr<UIWindow> findWindow_(const std::string& name)
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto& windowsMap = getWindowsMap();
|
||||
auto i = windowsMap.find(name);
|
||||
if (i != windowsMap.end())
|
||||
{
|
||||
const auto& ui_base = i->second;
|
||||
if (ui_base)
|
||||
{
|
||||
if (!ui_base->isActive())
|
||||
{
|
||||
windowsMap.erase(i);
|
||||
return std::shared_ptr<UIWindow>();
|
||||
}
|
||||
auto window = std::dynamic_pointer_cast<UIWindow>(ui_base);
|
||||
return window;
|
||||
}
|
||||
}
|
||||
return std::shared_ptr<UIWindow>();
|
||||
}
|
||||
|
||||
static void cleanupTrackbarCallbacksWithData_(); // forward declaration
|
||||
|
||||
static void cleanupClosedWindows_()
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto& windowsMap = getWindowsMap();
|
||||
for (auto it = windowsMap.begin(); it != windowsMap.end();)
|
||||
{
|
||||
const auto& ui_base = it->second;
|
||||
bool erase = (!ui_base || !ui_base->isActive());
|
||||
if (erase)
|
||||
{
|
||||
it = windowsMap.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
cleanupTrackbarCallbacksWithData_();
|
||||
}
|
||||
|
||||
// Just to support deprecated API, to be removed
|
||||
struct TrackbarCallbackWithData
|
||||
{
|
||||
std::weak_ptr<UITrackbar> trackbar_;
|
||||
int* data_;
|
||||
TrackbarCallback callback_;
|
||||
void* userdata_;
|
||||
|
||||
TrackbarCallbackWithData(int* data, TrackbarCallback callback, void* userdata)
|
||||
: data_(data)
|
||||
, callback_(callback), userdata_(userdata)
|
||||
{
|
||||
// trackbar_ is initialized separatelly
|
||||
}
|
||||
|
||||
~TrackbarCallbackWithData()
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "UI/Trackbar: Cleanup deprecated TrackbarCallbackWithData");
|
||||
}
|
||||
|
||||
void onChange(int pos)
|
||||
{
|
||||
if (data_)
|
||||
*data_ = pos;
|
||||
if (callback_)
|
||||
callback_(pos, userdata_);
|
||||
}
|
||||
|
||||
static void onChangeCallback(int pos, void* userdata)
|
||||
{
|
||||
TrackbarCallbackWithData* thiz = (TrackbarCallbackWithData*)userdata;
|
||||
CV_Assert(thiz);
|
||||
return thiz->onChange(pos);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector< std::shared_ptr<TrackbarCallbackWithData> > TrackbarCallbacksWithData_t;
|
||||
static TrackbarCallbacksWithData_t& getTrackbarCallbacksWithData()
|
||||
{
|
||||
static TrackbarCallbacksWithData_t g_trackbarCallbacksWithData;
|
||||
return g_trackbarCallbacksWithData;
|
||||
}
|
||||
|
||||
static void cleanupTrackbarCallbacksWithData_()
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto& callbacks = getTrackbarCallbacksWithData();
|
||||
for (auto it = callbacks.begin(); it != callbacks.end();)
|
||||
{
|
||||
const auto& cb = *it;
|
||||
bool erase = (!cb || cb->trackbar_.expired());
|
||||
if (erase)
|
||||
{
|
||||
it = callbacks.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace cv::impl
|
||||
|
||||
using namespace cv::impl;
|
||||
|
||||
CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_value)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
CV_Assert(name);
|
||||
|
||||
{
|
||||
auto window = findWindow_(name);
|
||||
if (window)
|
||||
{
|
||||
/*bool res = */window->setProperty(prop_id, prop_value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch(prop_id)
|
||||
{
|
||||
//change between fullscreen or not.
|
||||
@@ -109,8 +254,19 @@ CV_IMPL void cvSetWindowProperty(const char* name, int prop_id, double prop_valu
|
||||
/* return -1 if error */
|
||||
CV_IMPL double cvGetWindowProperty(const char* name, int prop_id)
|
||||
{
|
||||
if (!name)
|
||||
return -1;
|
||||
CV_TRACE_FUNCTION();
|
||||
CV_Assert(name);
|
||||
|
||||
{
|
||||
auto window = findWindow_(name);
|
||||
if (window)
|
||||
{
|
||||
double v = window->getProperty(prop_id);
|
||||
if (cvIsNaN(v))
|
||||
return -1;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
switch(prop_id)
|
||||
{
|
||||
@@ -209,9 +365,18 @@ CV_IMPL double cvGetWindowProperty(const char* name, int prop_id)
|
||||
|
||||
cv::Rect cvGetWindowImageRect(const char* name)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
if (!name)
|
||||
return cv::Rect(-1, -1, -1, -1);
|
||||
|
||||
{
|
||||
auto window = findWindow_(name);
|
||||
if (window)
|
||||
{
|
||||
return window->getImageRect();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (HAVE_QT)
|
||||
return cvGetWindowRect_QT(name);
|
||||
#elif defined(HAVE_WIN32UI)
|
||||
@@ -234,24 +399,90 @@ cv::Rect cv::getWindowImageRect(const String& winname)
|
||||
void cv::namedWindow( const String& winname, int flags )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
CV_Assert(!winname.empty());
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
cleanupClosedWindows_();
|
||||
auto& windowsMap = getWindowsMap();
|
||||
auto i = windowsMap.find(winname);
|
||||
if (i != windowsMap.end())
|
||||
{
|
||||
auto ui_base = i->second;
|
||||
if (ui_base)
|
||||
{
|
||||
auto window = std::dynamic_pointer_cast<UIWindow>(ui_base);
|
||||
if (!window)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "OpenCV/UI: Can't create window: '" << winname << "'");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
auto backend = getCurrentUIBackend();
|
||||
if (backend)
|
||||
{
|
||||
auto window = backend->createWindow(winname, flags);
|
||||
if (!window)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "OpenCV/UI: Can't create window: '" << winname << "'");
|
||||
return;
|
||||
}
|
||||
windowsMap.emplace(winname, window);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cvNamedWindow( winname.c_str(), flags );
|
||||
}
|
||||
|
||||
void cv::destroyWindow( const String& winname )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
auto window = findWindow_(winname);
|
||||
if (window)
|
||||
{
|
||||
window->destroy();
|
||||
cleanupClosedWindows_();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cvDestroyWindow( winname.c_str() );
|
||||
}
|
||||
|
||||
void cv::destroyAllWindows()
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto backend = getCurrentUIBackend();
|
||||
if (backend)
|
||||
{
|
||||
backend->destroyAllWindows();
|
||||
cleanupClosedWindows_();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cvDestroyAllWindows();
|
||||
}
|
||||
|
||||
void cv::resizeWindow( const String& winname, int width, int height )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
auto window = findWindow_(winname);
|
||||
if (window)
|
||||
{
|
||||
return window->resize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
cvResizeWindow( winname.c_str(), width, height );
|
||||
}
|
||||
|
||||
@@ -264,6 +495,15 @@ void cv::resizeWindow(const String& winname, const cv::Size& size)
|
||||
void cv::moveWindow( const String& winname, int x, int y )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
auto window = findWindow_(winname);
|
||||
if (window)
|
||||
{
|
||||
return window->move(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
cvMoveWindow( winname.c_str(), x, y );
|
||||
}
|
||||
|
||||
@@ -282,6 +522,16 @@ double cv::getWindowProperty(const String& winname, int prop_id)
|
||||
int cv::waitKeyEx(int delay)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto backend = getCurrentUIBackend();
|
||||
if (backend)
|
||||
{
|
||||
return backend->waitKeyEx(delay);
|
||||
}
|
||||
}
|
||||
|
||||
return cvWaitKey(delay);
|
||||
}
|
||||
|
||||
@@ -308,6 +558,16 @@ int cv::waitKey(int delay)
|
||||
int cv::pollKey()
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto backend = getCurrentUIBackend();
|
||||
if (backend)
|
||||
{
|
||||
return backend->pollKey();
|
||||
}
|
||||
}
|
||||
|
||||
// fallback. please implement a proper polling function
|
||||
return cvWaitKey(1);
|
||||
}
|
||||
@@ -318,6 +578,44 @@ int cv::createTrackbar(const String& trackbarName, const String& winName,
|
||||
void* userdata)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
CV_LOG_IF_WARNING(NULL, value, "UI/Trackbar(" << trackbarName << "@" << winName << "): Using 'value' pointer is unsafe and deprecated. Use NULL as value pointer. "
|
||||
"To fetch trackbar value setup callback.");
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto window = findWindow_(winName);
|
||||
if (window)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
auto cb = std::make_shared<TrackbarCallbackWithData>(value, callback, userdata);
|
||||
auto trackbar = window->createTrackbar(trackbarName, count, TrackbarCallbackWithData::onChangeCallback, cb.get());
|
||||
if (!trackbar)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "OpenCV/UI: Can't create trackbar: '" << trackbarName << "'@'" << winName << "'");
|
||||
return 0;
|
||||
}
|
||||
cb->trackbar_ = trackbar;
|
||||
getTrackbarCallbacksWithData().emplace_back(cb);
|
||||
getWindowsMap().emplace(trackbar->getID(), trackbar);
|
||||
trackbar->setPos(*value);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto trackbar = window->createTrackbar(trackbarName, count, callback, userdata);
|
||||
if (!trackbar)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "OpenCV/UI: Can't create trackbar: '" << trackbarName << "'@'" << winName << "'");
|
||||
return 0;
|
||||
}
|
||||
getWindowsMap().emplace(trackbar->getID(), trackbar);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cvCreateTrackbar2(trackbarName.c_str(), winName.c_str(),
|
||||
value, count, callback, userdata);
|
||||
}
|
||||
@@ -325,30 +623,92 @@ int cv::createTrackbar(const String& trackbarName, const String& winName,
|
||||
void cv::setTrackbarPos( const String& trackbarName, const String& winName, int value )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto window = findWindow_(winName);
|
||||
if (window)
|
||||
{
|
||||
auto trackbar = window->findTrackbar(trackbarName);
|
||||
CV_Assert(trackbar);
|
||||
return trackbar->setPos(value);
|
||||
}
|
||||
}
|
||||
|
||||
cvSetTrackbarPos(trackbarName.c_str(), winName.c_str(), value );
|
||||
}
|
||||
|
||||
void cv::setTrackbarMax(const String& trackbarName, const String& winName, int maxval)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto window = findWindow_(winName);
|
||||
if (window)
|
||||
{
|
||||
auto trackbar = window->findTrackbar(trackbarName);
|
||||
CV_Assert(trackbar);
|
||||
Range old_range = trackbar->getRange();
|
||||
Range range(std::min(old_range.start, maxval), maxval);
|
||||
return trackbar->setRange(range);
|
||||
}
|
||||
}
|
||||
|
||||
cvSetTrackbarMax(trackbarName.c_str(), winName.c_str(), maxval);
|
||||
}
|
||||
|
||||
void cv::setTrackbarMin(const String& trackbarName, const String& winName, int minval)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto window = findWindow_(winName);
|
||||
if (window)
|
||||
{
|
||||
auto trackbar = window->findTrackbar(trackbarName);
|
||||
CV_Assert(trackbar);
|
||||
Range old_range = trackbar->getRange();
|
||||
Range range(minval, std::max(minval, old_range.end));
|
||||
return trackbar->setRange(range);
|
||||
}
|
||||
}
|
||||
|
||||
cvSetTrackbarMin(trackbarName.c_str(), winName.c_str(), minval);
|
||||
}
|
||||
|
||||
int cv::getTrackbarPos( const String& trackbarName, const String& winName )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto window = findWindow_(winName);
|
||||
if (window)
|
||||
{
|
||||
auto trackbar = window->findTrackbar(trackbarName);
|
||||
CV_Assert(trackbar);
|
||||
return trackbar->getPos();
|
||||
}
|
||||
}
|
||||
|
||||
return cvGetTrackbarPos(trackbarName.c_str(), winName.c_str());
|
||||
}
|
||||
|
||||
void cv::setMouseCallback( const String& windowName, MouseCallback onMouse, void* param)
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
auto window = findWindow_(windowName);
|
||||
if (window)
|
||||
{
|
||||
return window->setMouseCallback(onMouse, param);
|
||||
}
|
||||
}
|
||||
|
||||
cvSetMouseCallback(windowName.c_str(), onMouse, param);
|
||||
}
|
||||
|
||||
@@ -403,6 +763,39 @@ namespace
|
||||
void cv::imshow( const String& winname, InputArray _img )
|
||||
{
|
||||
CV_TRACE_FUNCTION();
|
||||
|
||||
{
|
||||
cv::AutoLock lock(cv::getWindowMutex());
|
||||
cleanupClosedWindows_();
|
||||
auto& windowsMap = getWindowsMap();
|
||||
auto i = windowsMap.find(winname);
|
||||
if (i != windowsMap.end())
|
||||
{
|
||||
auto ui_base = i->second;
|
||||
if (ui_base)
|
||||
{
|
||||
auto window = std::dynamic_pointer_cast<UIWindow>(ui_base);
|
||||
if (!window)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "OpenCV/UI: invalid window name: '" << winname << "'");
|
||||
}
|
||||
return window->imshow(_img);
|
||||
}
|
||||
}
|
||||
auto backend = getCurrentUIBackend();
|
||||
if (backend)
|
||||
{
|
||||
auto window = backend->createWindow(winname, WINDOW_NORMAL);
|
||||
if (!window)
|
||||
{
|
||||
CV_LOG_ERROR(NULL, "OpenCV/UI: Can't create window: '" << winname << "'");
|
||||
return;
|
||||
}
|
||||
windowsMap.emplace(winname, window);
|
||||
return window->imshow(_img);
|
||||
}
|
||||
}
|
||||
|
||||
const Size size = _img.size();
|
||||
#ifndef HAVE_OPENGL
|
||||
CV_Assert(size.width>0 && size.height>0);
|
||||
|
||||
Reference in New Issue
Block a user