41 #include <visp3/core/vpConfig.h>
43 #if defined(HAVE_OPENCV_HIGHGUI)
52 #include <visp3/core/vpDisplay.h>
53 #include <visp3/core/vpImageTools.h>
54 #include <visp3/core/vpIoTools.h>
55 #include <visp3/core/vpMath.h>
56 #include <visp3/gui/vpDisplayOpenCV.h>
59 #include <visp3/core/vpDebug.h>
60 #include <visp3/core/vpDisplayException.h>
62 #include <opencv2/core/core_c.h>
64 #if defined(HAVE_OPENCV_IMGPROC)
65 #include <opencv2/imgproc/imgproc.hpp>
69 #define CV_RGB(r, g, b) cv::Scalar((b), (g), (r), 0)
73 #include <visp3/gui/vpDisplayX.h>
78 std::vector<std::string> vpDisplayOpenCV::m_listTitles = std::vector<std::string>();
79 unsigned int vpDisplayOpenCV::m_nbWindows = 0;
104 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
105 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
106 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
107 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
108 y_rbuttonup(0), rbuttonup(false)
140 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
141 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
142 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
143 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
144 y_rbuttonup(0), rbuttonup(false)
147 init(I, x, y, title);
170 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
171 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
172 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
173 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
174 y_rbuttonup(0), rbuttonup(false)
202 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
203 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
204 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
205 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
206 y_rbuttonup(0), rbuttonup(false)
209 init(I, x, y, title);
236 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
237 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
238 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
239 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
240 y_rbuttonup(0), rbuttonup(false)
245 if (!title.empty()) {
249 std::ostringstream s;
251 m_title = std::string(
"Window ") + s.str();
257 for (
size_t i = 0; i < m_listTitles.size(); i++) {
258 if (m_listTitles[i] ==
m_title) {
259 std::ostringstream s;
261 m_title = std::string(
"Window ") + s.str();
268 m_listTitles.push_back(
m_title);
292 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
293 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
294 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
295 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
296 y_rbuttonup(0), rbuttonup(false)
370 int flags = cv::WINDOW_AUTOSIZE;
373 if (!title.empty()) {
378 std::ostringstream s;
380 m_title = std::string(
"Window ") + s.str();
386 for (
size_t i = 0; i < m_listTitles.size(); i++) {
387 if (m_listTitles[i] ==
m_title) {
388 std::ostringstream s;
390 m_title = std::string(
"Window ") + s.str();
397 m_listTitles.push_back(
m_title);
401 cv::namedWindow(this->
m_title, flags);
402 cv::moveWindow(this->
m_title.c_str(), this->m_windowXPosition, this->m_windowYPosition);
457 fontSize = cv::getTextSize(
"A", font, fontScale, thickness, &baseline);
459 fontHeight = fontSize.height + baseline;
510 cv::moveWindow(this->
m_title.c_str(), winx, winy);
533 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)
m_height ||
534 m_background.cols != (
int)
m_width) {
535 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
539 for (
unsigned int i = 0; i <
m_height; i++) {
540 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width);
541 for (
unsigned int j = 0; j <
m_width; j++) {
542 unsigned char val = I[i][j];
550 for (
unsigned int i = 0; i <
m_height; i++) {
551 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width);
552 for (
unsigned int j = 0; j <
m_width; j++) {
588 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)
m_height ||
589 m_background.cols != (
int)
m_width) {
590 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
594 unsigned int i_min = (
unsigned int)iP.
get_i();
595 unsigned int j_min = (
unsigned int)iP.
get_j();
596 unsigned int i_max = std::min<unsigned int>(i_min + h,
m_height);
597 unsigned int j_max = std::min<unsigned int>(j_min + w,
m_width);
598 for (
unsigned int i = i_min; i < i_max; i++) {
599 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width + j_min * 3);
600 for (
unsigned int j = j_min; j < j_max; j++) {
601 unsigned char val = I[i][j];
609 int i_min = std::max<int>((
int)ceil(iP.
get_i() /
m_scale), 0);
610 int j_min = std::max<int>((
int)ceil(iP.
get_j() /
m_scale), 0);
613 for (
int i = i_min; i < i_max; i++) {
614 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width + j_min * 3);
615 for (
int j = j_min; j < j_max; j++) {
647 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)
m_height ||
648 m_background.cols != (
int)
m_width) {
649 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
653 for (
unsigned int i = 0; i <
m_height; i++) {
654 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width);
655 for (
unsigned int j = 0; j <
m_width; j++) {
664 for (
unsigned int i = 0; i <
m_height; i++) {
665 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width);
666 for (
unsigned int j = 0; j <
m_width; j++) {
701 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)
m_height ||
702 m_background.cols != (
int)
m_width) {
703 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
707 unsigned int i_min = (
unsigned int)iP.
get_i();
708 unsigned int j_min = (
unsigned int)iP.
get_j();
709 unsigned int i_max = std::min<unsigned int>(i_min + h,
m_height);
710 unsigned int j_max = std::min<unsigned int>(j_min + w,
m_width);
711 for (
unsigned int i = i_min; i < i_max; i++) {
712 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width + j_min * 3);
713 for (
unsigned int j = j_min; j < j_max; j++) {
722 int i_min = std::max<int>((
int)ceil(iP.
get_i() /
m_scale), 0);
723 int j_min = std::max<int>((
int)ceil(iP.
get_j() /
m_scale), 0);
726 for (
int i = i_min; i < i_max; i++) {
727 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 *
m_width + j_min * 3);
728 for (
int j = j_min; j < j_max; j++) {
758 if (col !=
nullptr) {
763 cv::destroyWindow(this->
m_title);
764 for (
size_t i = 0; i < m_listTitles.size(); i++) {
765 if (
m_title == m_listTitles[i]) {
766 m_listTitles.erase(m_listTitles.begin() + (
long int)i);
785 cv::imshow(this->
m_title, m_background);
802 cv::imshow(this->
m_title.c_str(), m_background);
815 static bool warn_displayed =
false;
816 if (!warn_displayed) {
818 warn_displayed =
true;
830 unsigned int w,
unsigned int h,
unsigned int thickness)
838 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
839 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
886 cv::putText(m_background, text,
888 font, fontScale, col[color.
id]);
891 cvcolor = CV_RGB(color.
R, color.
G, color.
B);
892 cv::putText(m_background, text,
894 font, fontScale, cvcolor);
914 unsigned int thickness)
919 int r =
static_cast<int>(radius /
m_scale);
922 cv_color = col[color.
id];
925 cv_color = CV_RGB(color.
R, color.
G, color.
B);
929 int cv_thickness =
static_cast<int>(thickness);
930 cv::circle(m_background, cv::Point(x, y), r, cv_color, cv_thickness);
933 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
934 int filled = cv::FILLED;
936 int filled = CV_FILLED;
938 double opacity =
static_cast<double>(color.
A) / 255.0;
939 overlay([x, y, r, cv_color, filled](cv::Mat image) { cv::circle(image, cv::Point(x, y), r, cv_color, filled); },
956 unsigned int thickness)
984 unsigned int thickness)
992 bool vertical_line = (int)ip2_.
get_j() == (int)ip1_.
get_j();
995 std::swap(ip1_, ip2_);
999 std::swap(ip1_, ip2_);
1002 double diff_j = vertical_line ? 1 : ip2_.
get_j() - ip1_.
get_j();
1003 double deltaj = size / length * diff_j;
1004 double deltai = size / length * (ip2_.
get_i() - ip1_.
get_i());
1005 double slope = (ip2_.
get_i() - ip1_.
get_i()) / diff_j;
1006 double orig = ip1_.
get_i() - slope * ip1_.
get_j();
1008 if (vertical_line) {
1009 for (
unsigned int i = (
unsigned int)ip1_.
get_i(); i < ip2_.
get_i(); i += (
unsigned int)(2 * deltai)) {
1010 double j = ip1_.
get_j();
1015 for (
unsigned int j = (
unsigned int)ip1_.
get_j(); j < ip2_.
get_j(); j += (
unsigned int)(2 * deltaj)) {
1016 double i = slope * j + orig;
1033 unsigned int thickness)
1042 cvcolor = CV_RGB(color.
R, color.
G, color.
B);
1062 for (
unsigned int i = 0; i < thickness; i++) {
1066 col[color.
id], (
int)thickness);
1069 cvcolor = CV_RGB(color.
R, color.
G, color.
B);
1072 cvcolor, (
int)thickness);
1097 const vpColor &color,
bool fill,
unsigned int thickness)
1104 cv::Scalar cv_color;
1106 cv_color = col[color.
id];
1109 cv_color = CV_RGB(color.
R, color.
G, color.
B);
1112 if (fill ==
false) {
1113 int cv_thickness =
static_cast<int>(thickness);
1114 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1117 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1118 int filled = cv::FILLED;
1120 int filled = CV_FILLED;
1122 double opacity =
static_cast<double>(color.
A) / 255.0;
1123 overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
1124 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1148 const vpColor &color,
bool fill,
unsigned int thickness)
1155 cv::Scalar cv_color;
1157 cv_color = col[color.
id];
1160 cv_color = CV_RGB(color.
R, color.
G, color.
B);
1163 if (fill ==
false) {
1164 int cv_thickness =
static_cast<int>(thickness);
1165 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1168 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1169 int filled = cv::FILLED;
1171 int filled = CV_FILLED;
1173 double opacity =
static_cast<double>(color.
A) / 255.0;
1174 overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
1175 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1205 cv::Scalar cv_color;
1207 cv_color = col[color.
id];
1210 cv_color = CV_RGB(color.
R, color.
G, color.
B);
1213 if (fill ==
false) {
1214 int cv_thickness =
static_cast<int>(thickness);
1215 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1218 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1219 int filled = cv::FILLED;
1221 int filled = CV_FILLED;
1223 double opacity =
static_cast<double>(color.
A) / 255.0;
1224 overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
1225 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1256 lbuttondown =
false;
1257 mbuttondown =
false;
1258 rbuttondown =
false;
1263 lbuttondown =
false;
1267 mbuttondown =
false;
1271 rbuttondown =
false;
1276 }
while (ret ==
false && blocking ==
true);
1309 lbuttondown =
false;
1310 mbuttondown =
false;
1311 rbuttondown =
false;
1316 u = (
unsigned int)x_lbuttondown *
m_scale;
1317 v = (
unsigned int)y_lbuttondown *
m_scale;
1320 lbuttondown =
false;
1324 u = (
unsigned int)x_mbuttondown *
m_scale;
1325 v = (
unsigned int)y_mbuttondown *
m_scale;
1328 mbuttondown =
false;
1332 u = (
unsigned int)x_rbuttondown *
m_scale;
1333 v = (
unsigned int)y_rbuttondown *
m_scale;
1336 rbuttondown =
false;
1341 }
while (ret ==
false && blocking ==
true);
1375 lbuttondown =
false;
1376 mbuttondown =
false;
1377 rbuttondown =
false;
1382 u = (
unsigned int)x_lbuttondown *
m_scale;
1383 v = (
unsigned int)y_lbuttondown *
m_scale;
1387 lbuttondown =
false;
1391 u = (
unsigned int)x_mbuttondown *
m_scale;
1392 v = (
unsigned int)y_mbuttondown *
m_scale;
1396 mbuttondown =
false;
1400 u = (
unsigned int)x_rbuttondown *
m_scale;
1401 v = (
unsigned int)y_rbuttondown *
m_scale;
1405 rbuttondown =
false;
1410 }
while (ret ==
false && blocking ==
true);
1453 u = (
unsigned int)x_lbuttonup *
m_scale;
1454 v = (
unsigned int)y_lbuttonup *
m_scale;
1462 u = (
unsigned int)x_mbuttonup *
m_scale;
1463 v = (
unsigned int)y_mbuttonup *
m_scale;
1471 u = (
unsigned int)x_rbuttonup *
m_scale;
1472 v = (
unsigned int)y_rbuttonup *
m_scale;
1481 }
while (ret ==
false && blocking ==
true);
1503 case cv::EVENT_MOUSEMOVE:
1510 case cv::EVENT_LBUTTONDOWN:
1512 disp->lbuttondown =
true;
1513 disp->x_lbuttondown = x;
1514 disp->y_lbuttondown = y;
1517 case cv::EVENT_MBUTTONDOWN:
1519 disp->mbuttondown =
true;
1520 disp->x_mbuttondown = x;
1521 disp->y_mbuttondown = y;
1524 case cv::EVENT_RBUTTONDOWN:
1526 disp->rbuttondown =
true;
1527 disp->x_rbuttondown = x;
1528 disp->y_rbuttondown = y;
1531 case cv::EVENT_LBUTTONUP:
1533 disp->lbuttonup =
true;
1534 disp->x_lbuttonup = x;
1535 disp->y_lbuttonup = y;
1538 case cv::EVENT_MBUTTONUP:
1540 disp->mbuttonup =
true;
1541 disp->x_mbuttonup = x;
1542 disp->y_mbuttonup = y;
1545 case cv::EVENT_RBUTTONUP:
1547 disp->rbuttonup =
true;
1548 disp->x_rbuttonup = x;
1549 disp->y_rbuttonup = y;
1583 int key_pressed = cv::waitKey(delay);
1585 if (key_pressed == -1)
1622 int key_pressed = cv::waitKey(delay);
1623 if (key_pressed == -1)
1627 std::stringstream ss;
1657 double u = (
unsigned int)x_move /
m_scale;
1658 double v = (
unsigned int)y_move /
m_scale;
1687 u = (
unsigned int)x_move /
m_scale;
1688 v = (
unsigned int)y_move /
m_scale;
1707 #if defined(VISP_HAVE_X11)
1710 #elif defined(VISP_HAVE_XRANDR)
1711 std::string command =
"xrandr | grep '*'";
1712 FILE *fpipe = (FILE *)popen(command.c_str(),
"r");
1714 while (fgets(line,
sizeof(line), fpipe)) {
1715 std::string str(line);
1716 std::size_t found = str.find(
"Failed");
1718 if (found == std::string::npos) {
1719 std::vector<std::string> elm;
1721 for (
size_t i = 0; i < elm.size(); i++) {
1722 if (!elm[i].empty()) {
1724 if (resolution.size() == 2) {
1725 std::istringstream sswidth(resolution[0]), ssheight(resolution[1]);
1735 #elif defined(_WIN32)
1737 w = GetSystemMetrics(SM_CXSCREEN);
1738 h = GetSystemMetrics(SM_CYSCREEN);
1741 "implemented on winrt"));
1751 unsigned int width, height;
1761 unsigned int width, height;
1775 if (opacity < 1.0) {
1777 overlay = m_background.clone();
1787 if (opacity < 1.0) {
1788 cv::addWeighted(
overlay, opacity, m_background, 1.0 - opacity, 0.0, m_background);
1792 #elif !defined(VISP_BUILD_SHARED_LIBS)
1794 void dummy_vpDisplayOpenCV() { };
Class to define RGB colors available for display functionalities.
static const vpColor white
static const vpColor darkGray
static const vpColor black
static const vpColor cyan
static const vpColor orange
static const vpColor darkRed
static const vpColor blue
static const vpColor lightGray
static const vpColor lightBlue
static const vpColor darkGreen
static const vpColor darkBlue
static const vpColor purple
static const vpColor lightGreen
static const vpColor yellow
static const vpColor lightRed
static const vpColor green
static const vpColor gray
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void setTitle(const std::string &title) vp_override
void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1) vp_override
void overlay(std::function< void(cv::Mat &)> overlay_function, double opacity)
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) vp_override
unsigned int getScreenHeight() vp_override
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) vp_override
void displayImage(const vpImage< unsigned char > &I) vp_override
bool getKeyboardEvent(bool blocking=true) vp_override
void closeDisplay() vp_override
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) vp_override
void setFont(const std::string &font) vp_override
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") vp_override
void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) vp_override
virtual ~vpDisplayOpenCV() vp_override
unsigned int getScreenWidth() vp_override
void getScreenSize(unsigned int &width, unsigned int &height) vp_override
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) vp_override
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) vp_override
static void on_mouse(int event, int x, int y, int flags, void *param)
bool getClick(bool blocking=true) vp_override
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) vp_override
bool getPointerMotionEvent(vpImagePoint &ip) vp_override
void setWindowPosition(int winx, int winy) vp_override
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) vp_override
bool getPointerPosition(vpImagePoint &ip) vp_override
void getImage(vpImage< vpRGBa > &I) vp_override
Get the window pixmap and put it in vpRGBa image.
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) vp_override
void displayCircle(const vpImagePoint ¢er, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) vp_override
void clearDisplay(const vpColor &color=vpColor::white) vp_override
void flushDisplay() vp_override
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
void getScreenSize(unsigned int &width, unsigned int &height) vp_override
Class that defines generic functionalities for display.
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
int m_windowYPosition
display position
bool m_displayHasBeenInitialized
display has been initialized
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
error that can be emitted by ViSP classes.
@ functionNotImplementedError
Function not implemented.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
unsigned int getWidth() const
unsigned int getHeight() const
static double sqr(double x)
static int round(double x)
unsigned char B
Blue component.
unsigned char R
Red component.
unsigned char G
Green component.
unsigned char A
Additionnal component.
Defines a rectangle in the plane.