mirror of
https://github.com/opencv/opencv.git
synced 2025-07-20 19:17:36 +08:00
Merge pull request #25661 from itlab-vision:framebuffer
Highgui backend on top of Framebuffer #25661 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [ x] I agree to contribute to the project under Apache 2 License. - [ x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [ x] The PR is proposed to the proper branch - [ ] There is a reference to the original bug report and related work - [ x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [ x] The feature is well documented and sample code can be built with the project CMake Environment variables used: OPENCV_UI_BACKEND - you need to add the value “FB” OPENCV_UI_PRIORITY_FB - requires priority indication OPENCV_HIGHGUI_FB_MODE={FB|XVFB|EMU} - mode of using Framebuffer (default "FB") - FB - Linux Framebuffer - XVFB - virtual Framebuffer - EMU - emulation (images are not displayed) OPENCV_HIGHGUI_FB_DEVICE (FRAMEBUFFER) - path to the Framebuffer file (default "/dev/fb0"). Examples of using: sudo OPENCV_UI_BACKEND=FB ./opencv_test_highgui sudo OPENCV_UI_PRIORITY_FB=1111 ./opencv_test_highgui OPENCV_UI_BACKEND=FB OPENCV_HIGHGUI_FB_MODE=EMU ./opencv_test_highgui sudo OPENCV_UI_BACKEND=FB OPENCV_HIGHGUI_FB_MODE=FB ./opencv_test_highgui export DISPLAY=:99 Xvfb $DISPLAY -screen 0 1024x768x24 -fbdir /tmp/ -f /tmp/user.xvfb.auth& sudo -u sipeed XAUTHORITY=/tmp/user.xvfb.auth x11vnc -display $DISPLAY -listen localhost& DISPLAY=:0 gvncviewer localhost& FRAMEBUFFER=/tmp/Xvfb_screen0 OPENCV_UI_BACKEND=FB OPENCV_HIGHGUI_FB_MODE=XVFB ./opencv_test_highgui
This commit is contained in:
parent
76a1d26bcd
commit
efa4d9176a
@ -306,6 +306,10 @@ OCV_OPTION(WITH_GTK "Include GTK support" ON
|
|||||||
OCV_OPTION(WITH_GTK_2_X "Use GTK version 2" OFF
|
OCV_OPTION(WITH_GTK_2_X "Use GTK version 2" OFF
|
||||||
VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID
|
VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID
|
||||||
VERIFY HAVE_GTK AND NOT HAVE_GTK3)
|
VERIFY HAVE_GTK AND NOT HAVE_GTK3)
|
||||||
|
OCV_OPTION(WITH_FRAMEBUFFER "Include framebuffer support" OFF
|
||||||
|
VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID)
|
||||||
|
OCV_OPTION(WITH_FRAMEBUFFER_XVFB "Include virtual framebuffer support" OFF
|
||||||
|
VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID)
|
||||||
OCV_OPTION(WITH_WAYLAND "Include Wayland support" OFF
|
OCV_OPTION(WITH_WAYLAND "Include Wayland support" OFF
|
||||||
VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID
|
VISIBLE_IF UNIX AND NOT APPLE AND NOT ANDROID
|
||||||
VERIFY HAVE_WAYLAND)
|
VERIFY HAVE_WAYLAND)
|
||||||
@ -1462,6 +1466,13 @@ if(WITH_GTK OR HAVE_GTK)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_FRAMEBUFFER OR HAVE_FRAMEBUFFER)
|
||||||
|
status(" Framebuffer UI:" HAVE_FRAMEBUFFER THEN YES ELSE NO)
|
||||||
|
if(WITH_FRAMEBUFFER_XVFB OR HAVE_FRAMEBUFFER_XVFB)
|
||||||
|
status(" Virtual framebuffer UI:" HAVE_FRAMEBUFFER_XVFB THEN YES ELSE NO)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_OPENGL OR HAVE_OPENGL)
|
if(WITH_OPENGL OR HAVE_OPENGL)
|
||||||
status(" OpenGL support:" HAVE_OPENGL THEN "YES (${OPENGL_LIBRARIES})" ELSE NO)
|
status(" OpenGL support:" HAVE_OPENGL THEN "YES (${OPENGL_LIBRARIES})" ELSE NO)
|
||||||
endif()
|
endif()
|
||||||
|
9
cmake/checks/framebuffer.cpp
Normal file
9
cmake/checks/framebuffer.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#include <X11/XWDFile.h>
|
||||||
|
#include <X11/X.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
XWDFileHeader *xwd_header;
|
||||||
|
XWDColor *xwd_colors;
|
||||||
|
return 0;
|
||||||
|
}
|
@ -49,6 +49,16 @@ list(REMOVE_ITEM highgui_ext_hdrs "${CMAKE_CURRENT_LIST_DIR}/include/opencv2/${n
|
|||||||
|
|
||||||
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "")
|
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "")
|
||||||
|
|
||||||
|
if(WITH_FRAMEBUFFER AND HAVE_FRAMEBUFFER)
|
||||||
|
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "FB")
|
||||||
|
add_definitions(-DHAVE_FRAMEBUFFER)
|
||||||
|
list(APPEND highgui_srcs ${CMAKE_CURRENT_LIST_DIR}/src/window_framebuffer.cpp)
|
||||||
|
list(APPEND highgui_hdrs ${CMAKE_CURRENT_LIST_DIR}/src/window_framebuffer.hpp)
|
||||||
|
if(HAVE_FRAMEBUFFER_XVFB)
|
||||||
|
add_definitions(-DHAVE_FRAMEBUFFER_XVFB)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_WAYLAND AND HAVE_WAYLAND)
|
if(WITH_WAYLAND AND HAVE_WAYLAND)
|
||||||
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "Wayland")
|
set(OPENCV_HIGHGUI_BUILTIN_BACKEND "Wayland")
|
||||||
add_definitions(-DHAVE_WAYLAND)
|
add_definitions(-DHAVE_WAYLAND)
|
||||||
|
14
modules/highgui/cmake/detect_framebuffer.cmake
Normal file
14
modules/highgui/cmake/detect_framebuffer.cmake
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# --- FB ---
|
||||||
|
set(HAVE_FRAMEBUFFER ON)
|
||||||
|
if(WITH_FRAMEBUFFER_XVFB)
|
||||||
|
try_compile(HAVE_FRAMEBUFFER_XVFB
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"${OpenCV_SOURCE_DIR}/cmake/checks/framebuffer.cpp")
|
||||||
|
if(HAVE_FRAMEBUFFER_XVFB)
|
||||||
|
message(STATUS "Check virtual framebuffer - done")
|
||||||
|
else()
|
||||||
|
message(STATUS
|
||||||
|
"Check virtual framebuffer - failed\n"
|
||||||
|
"Please install the xorg-x11-proto-devel or x11proto-dev package\n")
|
||||||
|
endif()
|
||||||
|
endif()
|
@ -39,6 +39,8 @@ endmacro()
|
|||||||
add_backend("gtk" WITH_GTK)
|
add_backend("gtk" WITH_GTK)
|
||||||
add_backend("win32ui" WITH_WIN32UI)
|
add_backend("win32ui" WITH_WIN32UI)
|
||||||
add_backend("wayland" WITH_WAYLAND)
|
add_backend("wayland" WITH_WAYLAND)
|
||||||
|
add_backend("framebuffer" WITH_FRAMEBUFFER)
|
||||||
|
|
||||||
# TODO cocoa
|
# TODO cocoa
|
||||||
# TODO qt
|
# TODO qt
|
||||||
# TODO opengl
|
# TODO opengl
|
||||||
|
@ -127,6 +127,10 @@ std::shared_ptr<UIBackend> createUIBackendGTK();
|
|||||||
std::shared_ptr<UIBackend> createUIBackendQT();
|
std::shared_ptr<UIBackend> createUIBackendQT();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FRAMEBUFFER
|
||||||
|
std::shared_ptr<UIBackend> createUIBackendFramebuffer();
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // BUILD_PLUGIN
|
#endif // BUILD_PLUGIN
|
||||||
|
|
||||||
} // namespace highgui_backend
|
} // namespace highgui_backend
|
||||||
|
@ -44,6 +44,10 @@ std::vector<BackendInfo>& getBuiltinBackendsInfo()
|
|||||||
DECLARE_DYNAMIC_BACKEND("GTK2")
|
DECLARE_DYNAMIC_BACKEND("GTK2")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FRAMEBUFFER
|
||||||
|
DECLARE_STATIC_BACKEND("FB", createUIBackendFramebuffer)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0 // TODO
|
#if 0 // TODO
|
||||||
#ifdef HAVE_QT
|
#ifdef HAVE_QT
|
||||||
DECLARE_STATIC_BACKEND("QT", createUIBackendQT)
|
DECLARE_STATIC_BACKEND("QT", createUIBackendQT)
|
||||||
|
798
modules/highgui/src/window_framebuffer.cpp
Normal file
798
modules/highgui/src/window_framebuffer.cpp
Normal file
@ -0,0 +1,798 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
|
||||||
|
#include "precomp.hpp"
|
||||||
|
|
||||||
|
#include "window_framebuffer.hpp"
|
||||||
|
|
||||||
|
#include <opencv2/core/utils/configuration.private.hpp>
|
||||||
|
#include <opencv2/core/utils/logger.defines.hpp>
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
|
||||||
|
#else
|
||||||
|
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
|
||||||
|
#endif
|
||||||
|
#include <opencv2/core/utils/logger.hpp>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include "opencv2/imgproc.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_FRAMEBUFFER_XVFB
|
||||||
|
#include <X11/XWDFile.h>
|
||||||
|
#include <X11/X.h>
|
||||||
|
|
||||||
|
#define C32INT(ptr) ((((unsigned char*)ptr)[0] << 24) | (((unsigned char*)ptr)[1] << 16) | \
|
||||||
|
(((unsigned char*)ptr)[2] << 8) | (((unsigned char*)ptr)[3] << 0))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace highgui_backend {
|
||||||
|
|
||||||
|
std::shared_ptr<UIBackend> createUIBackendFramebuffer()
|
||||||
|
{
|
||||||
|
return std::make_shared<FramebufferBackend>();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string& getFBMode()
|
||||||
|
{
|
||||||
|
static std::string fbModeOpenCV =
|
||||||
|
cv::utils::getConfigurationParameterString("OPENCV_HIGHGUI_FB_MODE", "FB");
|
||||||
|
return fbModeOpenCV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string& getFBFileName()
|
||||||
|
{
|
||||||
|
static std::string fbFileNameFB =
|
||||||
|
cv::utils::getConfigurationParameterString("FRAMEBUFFER", "/dev/fb0");
|
||||||
|
static std::string fbFileNameOpenCV =
|
||||||
|
cv::utils::getConfigurationParameterString("OPENCV_HIGHGUI_FB_DEVICE", "");
|
||||||
|
|
||||||
|
if (!fbFileNameOpenCV.empty()) return fbFileNameOpenCV;
|
||||||
|
return fbFileNameFB;
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferWindow::FramebufferWindow(FramebufferBackend &_backend, int _flags):
|
||||||
|
backend(_backend), flags(_flags)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::FramebufferWindow()");
|
||||||
|
FB_ID = "FramebufferWindow";
|
||||||
|
windowRect = Rect(0,0, backend.getFBWidth(), backend.getFBHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferWindow::~FramebufferWindow()
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::~FramebufferWindow()");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferWindow::imshow(InputArray image)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::imshow(InputArray image)");
|
||||||
|
currentImg = image.getMat().clone();
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: InputArray image: "
|
||||||
|
<< cv::typeToString(image.type()) << " size " << image.size());
|
||||||
|
|
||||||
|
if (currentImg.empty())
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: image is empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CV_CheckEQ(currentImg.dims, 2, "UI: dims != 2");
|
||||||
|
|
||||||
|
Mat img = image.getMat();
|
||||||
|
switch (img.channels())
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
Mat tmp;
|
||||||
|
switch(img.type())
|
||||||
|
{
|
||||||
|
case CV_8U:
|
||||||
|
tmp = img;
|
||||||
|
break;
|
||||||
|
case CV_8S:
|
||||||
|
cv::convertScaleAbs(img, tmp, 1, 127);
|
||||||
|
break;
|
||||||
|
case CV_16S:
|
||||||
|
cv::convertScaleAbs(img, tmp, 1/255., 127);
|
||||||
|
break;
|
||||||
|
case CV_16U:
|
||||||
|
cv::convertScaleAbs(img, tmp, 1/255.);
|
||||||
|
break;
|
||||||
|
case CV_32F:
|
||||||
|
case CV_64F: // assuming image has values in range [0, 1)
|
||||||
|
img.convertTo(tmp, CV_8U, 255., 0.);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Mat rgb(img.rows, img.cols, CV_8UC3);
|
||||||
|
cvtColor(tmp, rgb, COLOR_GRAY2RGB);
|
||||||
|
img = rgb;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
Mat tmp(img.rows, img.cols, CV_8UC3);
|
||||||
|
convertToShow(img, tmp, true);
|
||||||
|
img = tmp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CV_Error(cv::Error::StsBadArg, "Bad image: wrong number of channels");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Mat bgra(img.rows, img.cols, CV_8UC4);
|
||||||
|
cvtColor(img, bgra, COLOR_RGB2BGRA, bgra.channels());
|
||||||
|
img = bgra;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newWidth = windowRect.width;
|
||||||
|
int newHeight = windowRect.height;
|
||||||
|
int cntChannel = img.channels();
|
||||||
|
cv::Size imgSize = currentImg.size();
|
||||||
|
|
||||||
|
if (flags & WINDOW_AUTOSIZE)
|
||||||
|
{
|
||||||
|
windowRect.width = imgSize.width;
|
||||||
|
windowRect.height = imgSize.height;
|
||||||
|
newWidth = windowRect.width;
|
||||||
|
newHeight = windowRect.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WINDOW_FREERATIO)
|
||||||
|
{
|
||||||
|
newWidth = windowRect.width;
|
||||||
|
newHeight = windowRect.height;
|
||||||
|
}
|
||||||
|
else //WINDOW_KEEPRATIO
|
||||||
|
{
|
||||||
|
double aspect_ratio = ((double)img.cols) / img.rows;
|
||||||
|
newWidth = windowRect.width;
|
||||||
|
newHeight = (int)(windowRect.width / aspect_ratio);
|
||||||
|
|
||||||
|
if (newHeight > windowRect.height)
|
||||||
|
{
|
||||||
|
newWidth = (int)(windowRect.height * aspect_ratio);
|
||||||
|
newHeight = windowRect.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((newWidth != img.cols) && (newHeight != img.rows))
|
||||||
|
{
|
||||||
|
Mat imResize;
|
||||||
|
cv::resize(img, imResize, cv::Size(newWidth, newHeight), INTER_LINEAR);
|
||||||
|
img = imResize;
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: Formated image: "
|
||||||
|
<< cv::typeToString(img.type()) << " size " << img.size());
|
||||||
|
|
||||||
|
if (backend.getMode() == FB_MODE_EMU)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: FramebufferWindow::imshow is used in EMU mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend.getFBPointer() == MAP_FAILED)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: Framebuffer is not mapped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xOffset = backend.getFBXOffset();
|
||||||
|
int yOffset = backend.getFBYOffset();
|
||||||
|
int fbHeight = backend.getFBHeight();
|
||||||
|
int fbWidth = backend.getFBWidth();
|
||||||
|
int lineLength = backend.getFBLineLength();
|
||||||
|
|
||||||
|
int img_start_x;
|
||||||
|
int img_start_y;
|
||||||
|
int img_end_x;
|
||||||
|
int img_end_y;
|
||||||
|
int fb_start_x;
|
||||||
|
int fb_start_y;
|
||||||
|
|
||||||
|
if (windowRect.y - yOffset < 0)
|
||||||
|
{
|
||||||
|
img_start_y = - (windowRect.y - yOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
img_start_y = 0;
|
||||||
|
}
|
||||||
|
if (windowRect.x - xOffset < 0)
|
||||||
|
{
|
||||||
|
img_start_x = - (windowRect.x - xOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
img_start_x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (windowRect.y + yOffset + img.rows > fbHeight)
|
||||||
|
{
|
||||||
|
img_end_y = fbHeight - windowRect.y - yOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
img_end_y = img.rows;
|
||||||
|
}
|
||||||
|
if (windowRect.x + xOffset + img.cols > fbWidth)
|
||||||
|
{
|
||||||
|
img_end_x = fbWidth - windowRect.x - xOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
img_end_x = img.cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (windowRect.y + yOffset >= 0)
|
||||||
|
{
|
||||||
|
fb_start_y = windowRect.y + yOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fb_start_y = 0;
|
||||||
|
}
|
||||||
|
if (windowRect.x + xOffset >= 0)
|
||||||
|
{
|
||||||
|
fb_start_x = windowRect.x + xOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fb_start_x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = img_start_y; y < img_end_y; y++)
|
||||||
|
{
|
||||||
|
std::memcpy(backend.getFBPointer() +
|
||||||
|
(fb_start_y + y - img_start_y) * lineLength + fb_start_x * cntChannel,
|
||||||
|
img.ptr<unsigned char>(y) + img_start_x * cntChannel,
|
||||||
|
(img_end_x - img_start_x) * cntChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double FramebufferWindow::getProperty(int /*prop*/) const
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: getProperty (not supported)");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramebufferWindow::setProperty(int /*prop*/, double /*value*/)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: setProperty (not supported)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferWindow::resize(int width, int height)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::resize(int width "
|
||||||
|
<< width <<", height " << height << ")");
|
||||||
|
|
||||||
|
CV_Assert(width > 0);
|
||||||
|
CV_Assert(height > 0);
|
||||||
|
|
||||||
|
if (!(flags & WINDOW_AUTOSIZE))
|
||||||
|
{
|
||||||
|
windowRect.width = width;
|
||||||
|
windowRect.height = height;
|
||||||
|
|
||||||
|
if (!currentImg.empty())
|
||||||
|
{
|
||||||
|
imshow(currentImg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferWindow::move(int x, int y)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::move(int x " << x << ", y " << y <<")");
|
||||||
|
|
||||||
|
windowRect.x = x;
|
||||||
|
windowRect.y = y;
|
||||||
|
|
||||||
|
if (!currentImg.empty())
|
||||||
|
{
|
||||||
|
imshow(currentImg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect FramebufferWindow::getImageRect() const
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::getImageRect()");
|
||||||
|
return windowRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferWindow::setTitle(const std::string& /*title*/)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: setTitle (not supported)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferWindow::setMouseCallback(MouseCallback /*onMouse*/, void* /*userdata*/)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: setMouseCallback (not supported)");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<UITrackbar> FramebufferWindow::createTrackbar(
|
||||||
|
const std::string& /*name*/,
|
||||||
|
int /*count*/,
|
||||||
|
TrackbarCallback /*onChange*/,
|
||||||
|
void* /*userdata*/)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: createTrackbar (not supported)");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<UITrackbar> FramebufferWindow::findTrackbar(const std::string& /*name*/)
|
||||||
|
{
|
||||||
|
CV_LOG_WARNING(NULL, "UI: findTrackbar (not supported)");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& FramebufferWindow::getID() const
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::getID()");
|
||||||
|
return FB_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramebufferWindow::isActive() const
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::isActive()");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferWindow::destroy()
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::destroy()");
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::fbOpenAndGetInfo()
|
||||||
|
{
|
||||||
|
std::string fbFileName = getFBFileName();
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferWindow::The following is used as a framebuffer file: \n"
|
||||||
|
<< fbFileName);
|
||||||
|
|
||||||
|
int fb_fd = open(fbFileName.c_str(), O_RDWR);
|
||||||
|
if (fb_fd == -1)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: can't open framebuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixInfo))
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: can't read fix info for framebuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &varInfo))
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: can't read var info for framebuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: framebuffer info: \n"
|
||||||
|
<< " red offset " << varInfo.red.offset << " length " << varInfo.red.length << "\n"
|
||||||
|
<< " green offset " << varInfo.green.offset << " length " << varInfo.green.length << "\n"
|
||||||
|
<< " blue offset " << varInfo.blue.offset << " length " << varInfo.blue.length << "\n"
|
||||||
|
<< "transp offset " << varInfo.transp.offset << " length " <<varInfo.transp.length << "\n"
|
||||||
|
<< "bits_per_pixel " << varInfo.bits_per_pixel);
|
||||||
|
|
||||||
|
if ((varInfo.red.offset != 16) && (varInfo.red.length != 8) &&
|
||||||
|
(varInfo.green.offset != 8) && (varInfo.green.length != 8) &&
|
||||||
|
(varInfo.blue.offset != 0) && (varInfo.blue.length != 8) &&
|
||||||
|
(varInfo.bits_per_pixel != 32) )
|
||||||
|
{
|
||||||
|
close(fb_fd);
|
||||||
|
CV_LOG_ERROR(NULL, "UI: Framebuffer format is not supported "
|
||||||
|
<< "(use BGRA format with bits_per_pixel = 32)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fbWidth = varInfo.xres;
|
||||||
|
fbHeight = varInfo.yres;
|
||||||
|
fbXOffset = varInfo.xoffset;
|
||||||
|
fbYOffset = varInfo.yoffset;
|
||||||
|
fbBitsPerPixel = varInfo.bits_per_pixel;
|
||||||
|
fbLineLength = fixInfo.line_length;
|
||||||
|
|
||||||
|
fbScreenSize = max(varInfo.xres, varInfo.xres_virtual) *
|
||||||
|
max(varInfo.yres, varInfo.yres_virtual) *
|
||||||
|
fbBitsPerPixel / 8;
|
||||||
|
|
||||||
|
fbPointer = (unsigned char*)
|
||||||
|
mmap(0, fbScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
|
||||||
|
|
||||||
|
if (fbPointer == MAP_FAILED)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: can't mmap framebuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fb_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::XvfbOpenAndGetInfo()
|
||||||
|
{
|
||||||
|
int fb_fd = -1;
|
||||||
|
|
||||||
|
#ifdef HAVE_FRAMEBUFFER_XVFB
|
||||||
|
std::string fbFileName = getFBFileName();
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferWindow::The following is used as a framebuffer file: \n"
|
||||||
|
<< fbFileName);
|
||||||
|
|
||||||
|
fb_fd = open(fbFileName.c_str(), O_RDWR);
|
||||||
|
if (fb_fd == -1)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: can't open framebuffer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
XWDFileHeader *xwd_header;
|
||||||
|
|
||||||
|
xwd_header = (XWDFileHeader*)
|
||||||
|
mmap(NULL, sizeof(XWDFileHeader), PROT_READ, MAP_SHARED, fb_fd, 0);
|
||||||
|
|
||||||
|
if (xwd_header == MAP_FAILED)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: can't mmap xwd header");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C32INT(&(xwd_header->pixmap_format)) != ZPixmap)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "Unsupported pixmap format: " << xwd_header->pixmap_format);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xwd_header->xoffset != 0)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: Unsupported xoffset value: " << xwd_header->xoffset );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int r = C32INT(&(xwd_header->red_mask));
|
||||||
|
unsigned int g = C32INT(&(xwd_header->green_mask));
|
||||||
|
unsigned int b = C32INT(&(xwd_header->blue_mask));
|
||||||
|
|
||||||
|
fbWidth = C32INT(&(xwd_header->pixmap_width));
|
||||||
|
fbHeight = C32INT(&(xwd_header->pixmap_height));
|
||||||
|
fbXOffset = 0;
|
||||||
|
fbYOffset = 0;
|
||||||
|
fbLineLength = C32INT(&(xwd_header->bytes_per_line));
|
||||||
|
fbBitsPerPixel = C32INT(&(xwd_header->bits_per_pixel));
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: XVFB info: \n"
|
||||||
|
<< " red_mask " << r << "\n"
|
||||||
|
<< " green_mask " << g << "\n"
|
||||||
|
<< " blue_mask " << b << "\n"
|
||||||
|
<< "bits_per_pixel " << fbBitsPerPixel);
|
||||||
|
|
||||||
|
if ((r != 16711680 ) && (g != 65280 ) && (b != 255 ) &&
|
||||||
|
(fbBitsPerPixel != 32))
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: Framebuffer format is not supported "
|
||||||
|
<< "(use BGRA format with bits_per_pixel = 32)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xvfb_len_header = C32INT(&(xwd_header->header_size));
|
||||||
|
xvfb_len_colors = sizeof(XWDColor) * C32INT(&(xwd_header->ncolors));
|
||||||
|
xvfb_len_pixmap = C32INT(&(xwd_header->bytes_per_line)) *
|
||||||
|
C32INT(&(xwd_header->pixmap_height));
|
||||||
|
|
||||||
|
munmap(xwd_header, sizeof(XWDFileHeader));
|
||||||
|
|
||||||
|
fbScreenSize = xvfb_len_header + xvfb_len_colors + xvfb_len_pixmap;
|
||||||
|
xwd_header = (XWDFileHeader*)
|
||||||
|
mmap(NULL, fbScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
|
||||||
|
|
||||||
|
fbPointer = (unsigned char*)xwd_header;
|
||||||
|
fbPointer_dist = xvfb_len_header + xvfb_len_colors;
|
||||||
|
|
||||||
|
#else
|
||||||
|
CV_LOG_WARNING(NULL, "UI: To use virtual framebuffer, "
|
||||||
|
<< "compile OpenCV with the WITH_FRAMEBUFFER_XVFB=ON");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fb_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_var_screeninfo &FramebufferBackend::getVarInfo()
|
||||||
|
{
|
||||||
|
return varInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_fix_screeninfo &FramebufferBackend::getFixInfo()
|
||||||
|
{
|
||||||
|
return fixInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFramebuffrerID()
|
||||||
|
{
|
||||||
|
return fbID;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFBWidth()
|
||||||
|
{
|
||||||
|
return fbWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFBHeight()
|
||||||
|
{
|
||||||
|
return fbHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFBXOffset()
|
||||||
|
{
|
||||||
|
return fbXOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFBYOffset()
|
||||||
|
{
|
||||||
|
return fbYOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFBBitsPerPixel()
|
||||||
|
{
|
||||||
|
return fbBitsPerPixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getFBLineLength()
|
||||||
|
{
|
||||||
|
return fbLineLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* FramebufferBackend::getFBPointer()
|
||||||
|
{
|
||||||
|
return fbPointer + fbPointer_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mat& FramebufferBackend::getBackgroundBuff()
|
||||||
|
{
|
||||||
|
return backgroundBuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenCVFBMode FramebufferBackend::getMode()
|
||||||
|
{
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferBackend::FramebufferBackend():mode(FB_MODE_FB), fbPointer_dist(0)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::FramebufferBackend()");
|
||||||
|
|
||||||
|
std::string fbModeStr = getFBMode();
|
||||||
|
|
||||||
|
if (fbModeStr == "EMU")
|
||||||
|
{
|
||||||
|
mode = FB_MODE_EMU;
|
||||||
|
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is trying to use EMU mode");
|
||||||
|
}
|
||||||
|
if (fbModeStr == "FB")
|
||||||
|
{
|
||||||
|
mode = FB_MODE_FB;
|
||||||
|
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is trying to use FB mode");
|
||||||
|
}
|
||||||
|
if (fbModeStr == "XVFB")
|
||||||
|
{
|
||||||
|
mode = FB_MODE_XVFB;
|
||||||
|
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is trying to use XVFB mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
fbID = -1;
|
||||||
|
if (mode == FB_MODE_FB)
|
||||||
|
{
|
||||||
|
fbID = fbOpenAndGetInfo();
|
||||||
|
}
|
||||||
|
if (mode == FB_MODE_XVFB)
|
||||||
|
{
|
||||||
|
fbID = XvfbOpenAndGetInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferWindow::fbID " << fbID);
|
||||||
|
|
||||||
|
if (fbID == -1)
|
||||||
|
{
|
||||||
|
mode = FB_MODE_EMU;
|
||||||
|
fbWidth = 640;
|
||||||
|
fbHeight = 480;
|
||||||
|
fbXOffset = 0;
|
||||||
|
fbYOffset = 0;
|
||||||
|
fbBitsPerPixel = 0;
|
||||||
|
fbLineLength = 0;
|
||||||
|
|
||||||
|
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is used in EMU mode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: Framebuffer's width, height, bits per pix: "
|
||||||
|
<< fbWidth << " " << fbHeight << " " << fbBitsPerPixel);
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: Framebuffer's offsets (x, y), line length: "
|
||||||
|
<< fbXOffset << " " << fbYOffset << " " << fbLineLength);
|
||||||
|
|
||||||
|
backgroundBuff = Mat(fbHeight, fbWidth, CV_8UC4);
|
||||||
|
int cntChannel = 4;
|
||||||
|
for (int y = fbYOffset; y < backgroundBuff.rows + fbYOffset; y++)
|
||||||
|
{
|
||||||
|
std::memcpy(backgroundBuff.ptr<unsigned char>(y - fbYOffset),
|
||||||
|
getFBPointer() + y * fbLineLength + fbXOffset * cntChannel,
|
||||||
|
backgroundBuff.cols * cntChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FramebufferBackend::~FramebufferBackend()
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::~FramebufferBackend()");
|
||||||
|
if(fbID == -1) return;
|
||||||
|
|
||||||
|
if (fbPointer != MAP_FAILED)
|
||||||
|
{
|
||||||
|
int cntChannel = 4;
|
||||||
|
for (int y = fbYOffset; y < backgroundBuff.rows + fbYOffset; y++)
|
||||||
|
{
|
||||||
|
std::memcpy(getFBPointer() + y * fbLineLength + fbXOffset * cntChannel,
|
||||||
|
backgroundBuff.ptr<cv::Vec4b>(y - fbYOffset),
|
||||||
|
backgroundBuff.cols * cntChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(fbPointer, fbScreenSize);
|
||||||
|
}
|
||||||
|
close(fbID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferBackend::destroyAllWindows() {
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::destroyAllWindows()");
|
||||||
|
}
|
||||||
|
|
||||||
|
// namedWindow
|
||||||
|
std::shared_ptr<UIWindow> FramebufferBackend::createWindow(
|
||||||
|
const std::string& winname,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::createWindow("
|
||||||
|
<< winname << ", " << flags << ")");
|
||||||
|
return std::make_shared<FramebufferWindow>(*this, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferBackend::initTermios(int echo, int wait)
|
||||||
|
{
|
||||||
|
tcgetattr(0, &old);
|
||||||
|
current = old;
|
||||||
|
current.c_lflag &= ~ICANON;
|
||||||
|
current.c_lflag &= ~ISIG;
|
||||||
|
current.c_cc[VMIN] = wait;
|
||||||
|
if (echo)
|
||||||
|
{
|
||||||
|
current.c_lflag |= ECHO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current.c_lflag &= ~ECHO;
|
||||||
|
}
|
||||||
|
tcsetattr(0, TCSANOW, ¤t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FramebufferBackend::resetTermios(void)
|
||||||
|
{
|
||||||
|
tcsetattr(0, TCSANOW, &old);
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::getch_(int echo, int wait)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
initTermios(echo, wait);
|
||||||
|
ch = getchar();
|
||||||
|
if (ch < 0)
|
||||||
|
{
|
||||||
|
rewind(stdin);
|
||||||
|
}
|
||||||
|
resetTermios();
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FramebufferBackend::kbhit()
|
||||||
|
{
|
||||||
|
int byteswaiting = 0;
|
||||||
|
initTermios(0, 1);
|
||||||
|
if (ioctl(0, FIONREAD, &byteswaiting) < 0)
|
||||||
|
{
|
||||||
|
CV_LOG_ERROR(NULL, "UI: Framebuffer ERR byteswaiting" );
|
||||||
|
}
|
||||||
|
resetTermios();
|
||||||
|
|
||||||
|
return byteswaiting > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::waitKeyEx(int delay)
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::waitKeyEx(int delay = " << delay << ")");
|
||||||
|
|
||||||
|
int code = -1;
|
||||||
|
|
||||||
|
if (delay <= 0)
|
||||||
|
{
|
||||||
|
int ch = getch_(0, 1);
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = " << (int)ch);
|
||||||
|
code = ch;
|
||||||
|
|
||||||
|
while ((ch = getch_(0, 0)) >= 0)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = "
|
||||||
|
<< (int)ch << " (additional code on <stdin>)");
|
||||||
|
code = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool f_kbhit = false;
|
||||||
|
while (!(f_kbhit = kbhit()) && (delay > 0))
|
||||||
|
{
|
||||||
|
delay -= 1;
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
|
if (f_kbhit)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend kbhit is True ");
|
||||||
|
|
||||||
|
int ch = getch_(0, 1);
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = " << (int)ch);
|
||||||
|
code = ch;
|
||||||
|
|
||||||
|
while ((ch = getch_(0, 0)) >= 0)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = "
|
||||||
|
<< (int)ch << " (additional code on <stdin>)");
|
||||||
|
code = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::waitKeyEx() result code = " << code);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FramebufferBackend::pollKey()
|
||||||
|
{
|
||||||
|
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::pollKey()");
|
||||||
|
int code = -1;
|
||||||
|
bool f_kbhit = false;
|
||||||
|
f_kbhit = kbhit();
|
||||||
|
|
||||||
|
if (f_kbhit)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend kbhit is True ");
|
||||||
|
|
||||||
|
int ch = getch_(0, 1);
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = " << (int)ch);
|
||||||
|
code = ch;
|
||||||
|
|
||||||
|
while ((ch = getch_(0, 0)) >= 0)
|
||||||
|
{
|
||||||
|
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = "
|
||||||
|
<< (int)ch << " (additional code on <stdin>)");
|
||||||
|
code = ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string FramebufferBackend::getName() const
|
||||||
|
{
|
||||||
|
return "FB";
|
||||||
|
}
|
||||||
|
|
||||||
|
}} // cv::highgui_backend::
|
135
modules/highgui/src/window_framebuffer.hpp
Normal file
135
modules/highgui/src/window_framebuffer.hpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// This file is part of OpenCV project.
|
||||||
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||||
|
// of this distribution and at http://opencv.org/license.html.
|
||||||
|
|
||||||
|
#ifndef OPENCV_HIGHGUI_WINDOWS_FRAMEBUFFER_HPP
|
||||||
|
#define OPENCV_HIGHGUI_WINDOWS_FRAMEBUFFER_HPP
|
||||||
|
|
||||||
|
#include "backend.hpp"
|
||||||
|
|
||||||
|
#include <linux/fb.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace highgui_backend {
|
||||||
|
|
||||||
|
enum OpenCVFBMode{
|
||||||
|
FB_MODE_EMU,
|
||||||
|
FB_MODE_FB,
|
||||||
|
FB_MODE_XVFB
|
||||||
|
};
|
||||||
|
|
||||||
|
class FramebufferBackend;
|
||||||
|
class FramebufferWindow : public UIWindow
|
||||||
|
{
|
||||||
|
FramebufferBackend &backend;
|
||||||
|
std::string FB_ID;
|
||||||
|
Rect windowRect;
|
||||||
|
|
||||||
|
int flags;
|
||||||
|
Mat currentImg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FramebufferWindow(FramebufferBackend &backend, int flags);
|
||||||
|
virtual ~FramebufferWindow();
|
||||||
|
|
||||||
|
virtual void imshow(InputArray image) override;
|
||||||
|
|
||||||
|
virtual double getProperty(int prop) const override;
|
||||||
|
virtual bool setProperty(int prop, double value) override;
|
||||||
|
|
||||||
|
virtual void resize(int width, int height) override;
|
||||||
|
virtual void move(int x, int y) override;
|
||||||
|
|
||||||
|
virtual Rect getImageRect() const override;
|
||||||
|
|
||||||
|
virtual void setTitle(const std::string& title) override;
|
||||||
|
|
||||||
|
virtual void setMouseCallback(MouseCallback onMouse, void* userdata /*= 0*/) override;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<UITrackbar> createTrackbar(
|
||||||
|
const std::string& name,
|
||||||
|
int count,
|
||||||
|
TrackbarCallback onChange /*= 0*/,
|
||||||
|
void* userdata /*= 0*/
|
||||||
|
) override;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<UITrackbar> findTrackbar(const std::string& name) override;
|
||||||
|
|
||||||
|
virtual const std::string& getID() const override;
|
||||||
|
|
||||||
|
virtual bool isActive() const override;
|
||||||
|
|
||||||
|
virtual void destroy() override;
|
||||||
|
}; // FramebufferWindow
|
||||||
|
|
||||||
|
class FramebufferBackend: public UIBackend
|
||||||
|
{
|
||||||
|
OpenCVFBMode mode;
|
||||||
|
|
||||||
|
struct termios old, current;
|
||||||
|
|
||||||
|
void initTermios(int echo, int wait);
|
||||||
|
void resetTermios(void);
|
||||||
|
int getch_(int echo, int wait);
|
||||||
|
bool kbhit();
|
||||||
|
|
||||||
|
fb_var_screeninfo varInfo;
|
||||||
|
fb_fix_screeninfo fixInfo;
|
||||||
|
int fbWidth;
|
||||||
|
int fbHeight;
|
||||||
|
int fbXOffset;
|
||||||
|
int fbYOffset;
|
||||||
|
int fbBitsPerPixel;
|
||||||
|
int fbLineLength;
|
||||||
|
long int fbScreenSize;
|
||||||
|
unsigned char* fbPointer;
|
||||||
|
unsigned int fbPointer_dist;
|
||||||
|
Mat backgroundBuff;
|
||||||
|
|
||||||
|
int fbOpenAndGetInfo();
|
||||||
|
int fbID;
|
||||||
|
|
||||||
|
unsigned int xvfb_len_header;
|
||||||
|
unsigned int xvfb_len_colors;
|
||||||
|
unsigned int xvfb_len_pixmap;
|
||||||
|
int XvfbOpenAndGetInfo();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
fb_var_screeninfo &getVarInfo();
|
||||||
|
fb_fix_screeninfo &getFixInfo();
|
||||||
|
int getFramebuffrerID();
|
||||||
|
int getFBWidth();
|
||||||
|
int getFBHeight();
|
||||||
|
int getFBXOffset();
|
||||||
|
int getFBYOffset();
|
||||||
|
int getFBBitsPerPixel();
|
||||||
|
int getFBLineLength();
|
||||||
|
unsigned char* getFBPointer();
|
||||||
|
Mat& getBackgroundBuff();
|
||||||
|
OpenCVFBMode getMode();
|
||||||
|
|
||||||
|
FramebufferBackend();
|
||||||
|
|
||||||
|
virtual ~FramebufferBackend();
|
||||||
|
|
||||||
|
virtual void destroyAllWindows()override;
|
||||||
|
|
||||||
|
// namedWindow
|
||||||
|
virtual std::shared_ptr<UIWindow> createWindow(
|
||||||
|
const std::string& winname,
|
||||||
|
int flags
|
||||||
|
)override;
|
||||||
|
|
||||||
|
virtual int waitKeyEx(int delay /*= 0*/)override;
|
||||||
|
virtual int pollKey() override;
|
||||||
|
|
||||||
|
virtual const std::string getName() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}} // cv::highgui_backend::
|
||||||
|
|
||||||
|
#endif
|
@ -148,7 +148,8 @@ static void Foo(int, void* counter)
|
|||||||
&& !defined HAVE_WIN32UI \
|
&& !defined HAVE_WIN32UI \
|
||||||
&& !defined HAVE_WAYLAND \
|
&& !defined HAVE_WAYLAND \
|
||||||
) \
|
) \
|
||||||
|| defined(__APPLE__) // test fails on Mac (cocoa)
|
|| defined(__APPLE__) /* test fails on Mac (cocoa) */ \
|
||||||
|
|| defined HAVE_FRAMEBUFFER /* trackbar is not supported */
|
||||||
TEST(Highgui_GUI, DISABLED_trackbar_unsafe)
|
TEST(Highgui_GUI, DISABLED_trackbar_unsafe)
|
||||||
#else
|
#else
|
||||||
TEST(Highgui_GUI, trackbar_unsafe)
|
TEST(Highgui_GUI, trackbar_unsafe)
|
||||||
@ -188,7 +189,8 @@ void testTrackbarCallback(int pos, void* param)
|
|||||||
&& !defined HAVE_WIN32UI \
|
&& !defined HAVE_WIN32UI \
|
||||||
&& !defined HAVE_WAYLAND \
|
&& !defined HAVE_WAYLAND \
|
||||||
) \
|
) \
|
||||||
|| defined(__APPLE__) // test fails on Mac (cocoa)
|
|| defined(__APPLE__) /* test fails on Mac (cocoa) */ \
|
||||||
|
|| defined HAVE_FRAMEBUFFER /* trackbar is not supported */
|
||||||
TEST(Highgui_GUI, DISABLED_trackbar)
|
TEST(Highgui_GUI, DISABLED_trackbar)
|
||||||
#else
|
#else
|
||||||
TEST(Highgui_GUI, trackbar)
|
TEST(Highgui_GUI, trackbar)
|
||||||
|
Loading…
Reference in New Issue
Block a user