66 #include <opencv2/imgproc/imgproc.hpp>
67 #include <opencv2/highgui/highgui.hpp>
68 #include <opencv2/core/core.hpp>
88 void init(
const cv::String& theWindowName,
int theDelayWaitKey = -1,
bool theCreateNamedWindow =
true);
106 void init(
const cv::String theWindowNames[],
size_t theHowManyWindows,
int theDelayWaitKey = -1,
bool theCreateNamedWindows =
true);
122 void watch(
const cv::String& theWindowName,
bool theCreateNamedWindow =
true);
183 void context(
const cv::String& theWindowName);
202 void imshow(
const cv::String& theWindowName, cv::InputArray theFrame);
211 int lastKeyPressed();
219 cv::Point mouse(
const cv::String& theWindowName =
"");
248 bool mouse(
int theQuery);
262 bool mouse(
const cv::String& theWindowName,
int theQuery);
275 bool mouse(
int theButton,
int theQuery);
286 bool mouse(
const cv::String& theWindowName,
int theButton,
int theQuery);
298 bool button(cv::Mat& theWhere,
int theX,
int theY,
const cv::String& theLabel);
312 bool button(cv::Mat& theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theLabel);
331 bool button(cv::Mat& theWhere,
int theX,
int theY, cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown);
344 void image(cv::Mat& theWhere,
int theX,
int theY, cv::Mat& theImage);
358 bool checkbox(cv::Mat& theWhere,
int theX,
int theY,
const cv::String& theLabel,
bool *theState,
unsigned int theColor = 0xCECECE);
372 void text(cv::Mat& theWhere,
int theX,
int theY,
const cv::String& theText,
double theFontScale = 0.4,
unsigned int theColor = 0xCECECE);
391 void printf(cv::Mat& theWhere,
int theX,
int theY,
double theFontScale,
unsigned int theColor,
const char *theFmt, ...);
410 void printf(cv::Mat& theWhere,
int theX,
int theY,
const char *theFmt, ...);
424 int counter(cv::Mat& theWhere,
int theX,
int theY,
int *theValue,
int theStep = 1,
const char *theFormat =
"%d");
438 double counter(cv::Mat& theWhere,
int theX,
int theY,
double *theValue,
double theStep = 0.5,
const char *theFormat =
"%.2f");
474 template <
typename T>
475 bool trackbar(cv::Mat& theWhere,
int theX,
int theY,
int theWidth, T *theValue, T theMin, T theMax,
int theSegments = 1,
const char *theLabelFormat =
"%.1Lf",
unsigned int theOptions = 0, T theDiscreteStep = 1);
489 void window(cv::Mat& theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theTitle);
504 void rect(cv::Mat& theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theBorderColor,
unsigned int theFillingColor = 0xff000000);
519 void sparkline(cv::Mat& theWhere, std::vector<double>& theValues,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theColor = 0x00FF00);
542 int iarea(
int theX,
int theY,
int theWidth,
int theHeight);
605 void beginRow(cv::Mat &theWhere,
int theX,
int theY,
int theWidth = -1,
int theHeight = -1,
int thePadding = 0);
678 void beginColumn(cv::Mat &theWhere,
int theX,
int theY,
int theWidth = -1,
int theHeight = -1,
int thePadding = 0);
705 void beginRow(
int theWidth = -1,
int theHeight = -1,
int thePadding = 0);
722 void beginColumn(
int theWidth = -1,
int theHeight = -1,
int thePadding = 0);
739 void space(
int theValue = 5);
756 void text(
const cv::String& theText,
double theFontScale = 0.4,
unsigned int theColor = 0xCECECE);
775 bool button(
int theWidth,
int theHeight,
const cv::String& theLabel);
791 bool button(
const cv::String& theLabel);
815 bool button(cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown);
831 void image(cv::Mat& theImage);
849 bool checkbox(
const cv::String& theLabel,
bool *theState,
unsigned int theColor = 0xCECECE);
873 void printf(
double theFontScale,
unsigned int theColor,
const char *theFmt, ...);
896 void printf(
const char *theFmt, ...);
915 int counter(
int *theValue,
int theStep = 1,
const char *theFormat =
"%d");
934 double counter(
double *theValue,
double theStep = 0.5,
const char *theFormat =
"%.2f");
975 template <
typename T>
976 bool trackbar(
int theWidth, T *theValue, T theMin, T theMax,
int theSegments = 1,
const char *theLabelFormat =
"%.1Lf",
unsigned int theOptions = 0, T theDiscreteStep = 1);
993 void window(
int theWidth,
int theHeight,
const cv::String& theTitle);
1011 void rect(
int theWidth,
int theHeight,
unsigned int theBorderColor,
unsigned int theFillingColor = 0xff000000);
1028 void sparkline(std::vector<double>& theValues,
int theWidth,
int theHeight,
unsigned int theColor = 0x00FF00);
1040 void update(
const cv::String& theWindowName =
"");
1043 void handleMouse(
int theEvent,
int theX,
int theY,
int theFlags,
void* theData);
1046 #if (CV_MAJOR_VERSION < 3)
1047 #define CVUI_ANTIALISED CV_AA
1049 #define CVUI_ANTIALISED cv::LINE_AA
1051 #define CVUI_FILLED -1
1055 #if !defined(_MSC_VER)
1056 #define vsprintf_s vsprintf
1057 #define sprintf_s sprintf
1062 #define _CVUI_COMPILE_MESSAGE(x) message(x)
1069 #define __cvui_min min
1073 #define __cvui_max max
1077 #define _CVUI_COMPILE_MESSAGE(x) message x
1081 #define _CVUI_IMPLEMENTATION_NOTICE "cvui.h: compiling implementation because of CVUI_IMPLEMENTATION. See: https://dovyski.github.io/cvui/usage/"
1082 #define _CVUI_NO_IMPLEMENTATION_NOTICE "cvui.h: implementation skipped. Ensure one of your C++ files included cvui.h after a #define CVUI_IMPLEMENTATION. See: https://dovyski.github.io/cvui/usage/"
1097 #undef MIDDLE_BUTTON
1104 #pragma GCC diagnostic ignored "-Wunused-variable"
1108 static const char *VERSION =
"2.7.0";
1111 const int COLUMN = 1;
1113 const int CLICK = 3;
1117 const int IS_DOWN = 7;
1120 const int LEFT_BUTTON = 0;
1121 const int MIDDLE_BUTTON = 1;
1122 const int RIGHT_BUTTON = 2;
1125 const unsigned int TRACKBAR_HIDE_SEGMENT_LABELS = 1;
1126 const unsigned int TRACKBAR_HIDE_STEP_SCALE = 2;
1127 const unsigned int TRACKBAR_DISCRETE = 4;
1128 const unsigned int TRACKBAR_HIDE_MIN_MAX_LABELS = 8;
1129 const unsigned int TRACKBAR_HIDE_VALUE_LABEL = 16;
1130 const unsigned int TRACKBAR_HIDE_LABELS = 32;
1151 std::string textBeforeShortcut;
1152 std::string textAfterShortcut;
1164 cvui_mouse_btn_t buttons[3];
1165 cvui_mouse_btn_t anyButton;
1171 cv::String windowName;
1179 static cv::String gDefaultContext;
1180 static cv::String gCurrentContext;
1181 static std::map<cv::String, cvui_context_t> gContexts;
1182 static char gBuffer[1024];
1183 static int gLastKeyPressed;
1184 static int gDelayWaitKey;
1185 static cvui_block_t gScreen;
1187 struct TrackbarParams {
1192 unsigned int options;
1193 std::string labelFormat;
1195 inline TrackbarParams()
1201 , labelFormat(
"%.0Lf")
1205 static cvui_block_t gStack[100];
1206 static int gStackCount = -1;
1207 static const int gTrackbarMarginX = 14;
1209 bool isMouseButton(cvui_mouse_btn_t& theButton,
int theQuery);
1210 void resetMouseButton(cvui_mouse_btn_t& theButton);
1211 void init(
const cv::String& theWindowName,
int theDelayWaitKey);
1212 cvui_context_t& getContext(
const cv::String& theWindowName =
"");
1213 bool bitsetHas(
unsigned int theBitset,
unsigned int theValue);
1214 void error(
int theId, std::string theMessage);
1215 void updateLayoutFlow(cvui_block_t& theBlock, cv::Size theSize);
1216 bool blockStackEmpty();
1217 cvui_block_t& topBlock();
1218 cvui_block_t& pushBlock();
1219 cvui_block_t& popBlock();
1220 void begin(
int theType, cv::Mat &theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
int thePadding);
1221 void end(
int theType);
1222 cvui_label_t createLabel(
const std::string &theLabel);
1223 int iarea(
int theX,
int theY,
int theWidth,
int theHeight);
1224 bool button(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theLabel,
bool theUpdateLayout);
1225 bool button(cvui_block_t& theBlock,
int theX,
int theY,
const cv::String& theLabel);
1226 bool button(cvui_block_t& theBlock,
int theX,
int theY, cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown,
bool theUpdateLayout);
1227 void image(cvui_block_t& theBlock,
int theX,
int theY, cv::Mat& theImage);
1228 bool checkbox(cvui_block_t& theBlock,
int theX,
int theY,
const cv::String& theLabel,
bool *theState,
unsigned int theColor);
1229 void text(cvui_block_t& theBlock,
int theX,
int theY,
const cv::String& theText,
double theFontScale,
unsigned int theColor,
bool theUpdateLayout);
1230 int counter(cvui_block_t& theBlock,
int theX,
int theY,
int *theValue,
int theStep,
const char *theFormat);
1231 double counter(cvui_block_t& theBlock,
int theX,
int theY,
double *theValue,
double theStep,
const char *theFormat);
1232 void window(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theTitle);
1233 void rect(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theBorderColor,
unsigned int theFillingColor);
1234 void sparkline(cvui_block_t& theBlock, std::vector<double>& theValues,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theColor);
1235 bool trackbar(cvui_block_t &theBlock,
int theX,
int theY,
int theWidth,
long double *theValue,
const TrackbarParams& theParams);
1236 inline void trackbarForceValuesAsMultiplesOfSmallStep(
const TrackbarParams & theParams,
long double *theValue);
1237 inline long double trackbarXPixelToValue(
const TrackbarParams & theParams, cv::Rect & theBounding,
int thePixelX);
1238 inline int trackbarValueToXPixel(
const TrackbarParams & theParams, cv::Rect & theBounding,
long double theValue);
1239 inline double clamp01(
double value);
1240 void findMinMax(std::vector<double>& theValues,
double *theMin,
double *theMax);
1241 cv::Scalar hexToScalar(
unsigned int theColor);
1242 void resetRenderingBuffer(cvui_block_t& theScreen);
1244 template <
typename T>
1245 TrackbarParams makeTrackbarParams(T min, T max,
int theDecimals = 1,
int theSegments = 1, T theStep = -1.,
unsigned int theOptions = 0,
const char *theFormat =
"%.1Lf");
1247 template<
typename T>
1248 bool trackbar(T *theValue,
const TrackbarParams& theParams);
1250 template <
typename T>
1251 bool trackbar(cv::Mat& theWhere,
int theX,
int theY,
int theWidth, T *theValue,
const TrackbarParams& theParams);
1253 template<
typename num_type>
1254 TrackbarParams makeTrackbarParams(num_type theMin, num_type theMax, num_type theStep,
int theSegments,
const char *theLabelFormat,
unsigned int theOptions) {
1255 TrackbarParams aParams;
1257 aParams.min = (
long double)theMin;
1258 aParams.max = (
long double)theMax;
1259 aParams.step = (
long double)theStep;
1260 aParams.options = theOptions;
1261 aParams.segments = theSegments;
1262 aParams.labelFormat = theLabelFormat;
1267 template <
typename num_type>
1268 bool trackbar(
int theWidth, num_type *theValue,
const TrackbarParams& theParams) {
1269 cvui_block_t& aBlock = internal::topBlock();
1271 long double aValueAsDouble =
static_cast<long double>(*theValue);
1272 bool aResult = internal::trackbar(aBlock, aBlock.anchor.x, aBlock.anchor.y, theWidth, &aValueAsDouble, theParams);
1273 *theValue =
static_cast<num_type
>(aValueAsDouble);
1278 template <
typename num_type>
1279 bool trackbar(cv::Mat& theWhere,
int theX,
int theY,
int theWidth, num_type *theValue,
const TrackbarParams& theParams) {
1280 gScreen.where = theWhere;
1282 long double aValueAsDouble =
static_cast<long double>(*theValue);
1283 bool aResult = internal::trackbar(gScreen, theX, theY, theWidth, &aValueAsDouble, theParams);
1284 *theValue =
static_cast<num_type
>(aValueAsDouble);
1292 void text(cvui_block_t& theBlock,
const cv::String& theText, cv::Point& thePos,
double theFontScale,
unsigned int theColor);
1293 void button(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
const cv::String& theLabel);
1294 void buttonLabel(cvui_block_t& theBlock,
int theState, cv::Rect theRect,
const cv::String& theLabel, cv::Size& theTextSize);
1295 void image(cvui_block_t& theBlock, cv::Rect& theRect, cv::Mat& theImage);
1296 void counter(cvui_block_t& theBlock, cv::Rect& theShape,
const cv::String& theValue);
1297 void trackbarHandle(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
1298 void trackbarPath(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
1299 void trackbarSteps(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
1300 void trackbarSegmentLabel(cvui_block_t& theBlock, cv::Rect& theShape,
const internal::TrackbarParams &theParams,
long double theValue, cv::Rect& theWorkingArea,
bool theShowLabel);
1301 void trackbarSegments(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea);
1302 void trackbar(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams);
1303 void checkbox(cvui_block_t& theBlock,
int theState, cv::Rect& theShape);
1304 void checkboxLabel(cvui_block_t& theBlock, cv::Rect& theRect,
const cv::String& theLabel, cv::Size& theTextSize,
unsigned int theColor);
1305 void checkboxCheck(cvui_block_t& theBlock, cv::Rect& theShape);
1306 void window(cvui_block_t& theBlock, cv::Rect& theTitleBar, cv::Rect& theContent,
const cv::String& theTitle);
1307 void rect(cvui_block_t& theBlock, cv::Rect& thePos,
unsigned int theBorderColor,
unsigned int theFillingColor);
1308 void sparkline(cvui_block_t& theBlock, std::vector<double>& theValues, cv::Rect &theRect,
double theMin,
double theMax,
unsigned int theColor);
1310 int putText(cvui_block_t& theBlock,
int theState, cv::Scalar aColor,
const std::string& theText,
const cv::Point & thePosition);
1311 int putTextCentered(cvui_block_t& theBlock,
const cv::Point & position,
const std::string &text);
1314 template <
typename num_type>
1315 bool trackbar(cv::Mat& theWhere,
int theX,
int theY,
int theWidth, num_type *theValue, num_type theMin, num_type theMax,
int theSegments,
const char *theLabelFormat,
unsigned int theOptions, num_type theDiscreteStep) {
1316 internal::TrackbarParams aParams = internal::makeTrackbarParams(theMin, theMax, theDiscreteStep, theSegments, theLabelFormat, theOptions);
1317 return trackbar<num_type>(theWhere, theX, theY, theWidth, theValue, aParams);
1320 template <
typename num_type>
1321 bool trackbar(
int theWidth, num_type *theValue, num_type theMin, num_type theMax,
int theSegments,
const char *theLabelFormat,
unsigned int theOptions, num_type theDiscreteStep) {
1322 internal::TrackbarParams aParams = internal::makeTrackbarParams(theMin, theMax, theDiscreteStep, theSegments, theLabelFormat, theOptions);
1323 return trackbar<num_type>(theWidth, theValue, aParams);
1332 #if !defined(CVUI_IMPLEMENTATION) && !defined(CVUI_DISABLE_COMPILATION_NOTICES)
1335 #pragma _CVUI_COMPILE_MESSAGE(_CVUI_NO_IMPLEMENTATION_NOTICE)
1341 #ifndef CVUI_DISABLE_COMPILATION_NOTICES
1342 #pragma _CVUI_COMPILE_MESSAGE(_CVUI_IMPLEMENTATION_NOTICE)
1352 bool isMouseButton(cvui_mouse_btn_t& theButton,
int theQuery) {
1358 aRet = theButton.justReleased;
break;
1360 aRet = theButton.justPressed;
break;
1362 aRet = theButton.pressed;
break;
1368 void resetMouseButton(cvui_mouse_btn_t& theButton) {
1369 theButton.justPressed =
false;
1370 theButton.justReleased =
false;
1371 theButton.pressed =
false;
1374 void init(
const cv::String& theWindowName,
int theDelayWaitKey) {
1375 internal::gDefaultContext = theWindowName;
1376 internal::gCurrentContext = theWindowName;
1377 internal::gDelayWaitKey = theDelayWaitKey;
1378 internal::gLastKeyPressed = -1;
1381 cvui_context_t& getContext(
const cv::String& theWindowName) {
1382 if (!theWindowName.empty()) {
1384 return internal::gContexts[theWindowName];
1386 }
else if (!internal::gCurrentContext.empty()) {
1388 return internal::gContexts[internal::gCurrentContext];
1390 }
else if (!internal::gDefaultContext.empty()) {
1392 return internal::gContexts[internal::gDefaultContext];
1397 internal::error(5,
"Unable to read context. Did you forget to call cvui::init()?");
1398 return internal::gContexts[
"first"];
1402 bool bitsetHas(
unsigned int theBitset,
unsigned int theValue) {
1403 return (theBitset & theValue) != 0;
1406 void error(
int theId, std::string theMessage) {
1407 std::cout <<
"[CVUI] Fatal error (code " << theId <<
"): " << theMessage <<
"\n";
1408 cv::waitKey(100000);
1412 void updateLayoutFlow(cvui_block_t& theBlock, cv::Size theSize) {
1415 if (theBlock.type == ROW) {
1416 aValue = theSize.width + theBlock.padding;
1418 theBlock.anchor.x += aValue;
1419 theBlock.fill.width += aValue;
1420 theBlock.fill.height = std::max(theSize.height, theBlock.fill.height);
1423 else if (theBlock.type == COLUMN) {
1424 aValue = theSize.height + theBlock.padding;
1426 theBlock.anchor.y += aValue;
1427 theBlock.fill.height += aValue;
1428 theBlock.fill.width = std::max(theSize.width, theBlock.fill.width);
1432 bool blockStackEmpty() {
1433 return gStackCount == -1;
1436 cvui_block_t& topBlock() {
1437 if (gStackCount < 0) {
1438 error(3,
"You are using a function that should be enclosed by begin*() and end*(), but you probably forgot to call begin*().");
1441 return gStack[gStackCount];
1444 cvui_block_t& pushBlock() {
1445 return gStack[++gStackCount];
1448 cvui_block_t& popBlock() {
1450 if (gStackCount < 0) {
1451 error(1,
"Mismatch in the number of begin*()/end*() calls. You are calling one more than the other.");
1454 return gStack[gStackCount--];
1457 void begin(
int theType, cv::Mat &theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
int thePadding) {
1458 cvui_block_t& aBlock = internal::pushBlock();
1460 aBlock.where = theWhere;
1462 aBlock.rect.x = theX;
1463 aBlock.rect.y = theY;
1464 aBlock.rect.width = theWidth;
1465 aBlock.rect.height = theHeight;
1467 aBlock.fill = aBlock.rect;
1468 aBlock.fill.width = 0;
1469 aBlock.fill.height = 0;
1471 aBlock.anchor.x = theX;
1472 aBlock.anchor.y = theY;
1474 aBlock.padding = thePadding;
1475 aBlock.type = theType;
1478 void end(
int theType) {
1479 cvui_block_t& aBlock = popBlock();
1481 if (aBlock.type != theType) {
1482 error(4,
"Calling wrong type of end*(). E.g. endColumn() instead of endRow(). Check if your begin*() calls are matched with their appropriate end*() calls.");
1489 if (!blockStackEmpty()) {
1490 cvui_block_t& aTop = topBlock();
1500 aSize.width = aBlock.rect.width < 0 ? aBlock.fill.width : aBlock.rect.width;
1501 aSize.height = aBlock.rect.height < 0 ? aBlock.fill.height : aBlock.rect.height;
1503 updateLayoutFlow(aTop, aSize);
1508 void findMinMax(std::vector<double>& theValues,
double *theMin,
double *theMax) {
1509 std::vector<double>::size_type aSize = theValues.size(), i;
1510 double aMin = theValues[0], aMax = theValues[0];
1512 for (i = 0; i < aSize; i++) {
1513 if (theValues[i] < aMin) {
1514 aMin = theValues[i];
1517 if (theValues[i] > aMax) {
1518 aMax = theValues[i];
1526 cvui_label_t createLabel(
const std::string &theLabel) {
1527 cvui_label_t aLabel;
1528 std::stringstream aBefore, aAfter;
1530 aLabel.hasShortcut =
false;
1531 aLabel.shortcut = 0;
1532 aLabel.textBeforeShortcut =
"";
1533 aLabel.textAfterShortcut =
"";
1535 for (
size_t i = 0; i < theLabel.size(); i++) {
1536 char c = theLabel[i];
1537 if ((c ==
'&') && (i < theLabel.size() - 1)) {
1538 aLabel.hasShortcut =
true;
1539 aLabel.shortcut = theLabel[i + 1];
1542 else if (!aLabel.hasShortcut) {
1550 aLabel.textBeforeShortcut = aBefore.str();
1551 aLabel.textAfterShortcut = aAfter.str();
1556 cv::Scalar hexToScalar(
unsigned int theColor) {
1557 int aAlpha = (theColor >> 24) & 0xff;
1558 int aRed = (theColor >> 16) & 0xff;
1559 int aGreen = (theColor >> 8) & 0xff;
1560 int aBlue = theColor & 0xff;
1562 return cv::Scalar(aBlue, aGreen, aRed, aAlpha);
1565 void resetRenderingBuffer(cvui_block_t& theScreen) {
1566 theScreen.rect.x = 0;
1567 theScreen.rect.y = 0;
1568 theScreen.rect.width = 0;
1569 theScreen.rect.height = 0;
1571 theScreen.fill = theScreen.rect;
1572 theScreen.fill.width = 0;
1573 theScreen.fill.height = 0;
1575 theScreen.anchor.x = 0;
1576 theScreen.anchor.y = 0;
1578 theScreen.padding = 0;
1582 inline double clamp01(
double value)
1584 value = value > 1. ? 1. : value;
1585 value = value < 0. ? 0. : value;
1589 inline void trackbarForceValuesAsMultiplesOfSmallStep(
const TrackbarParams & theParams,
long double *theValue)
1591 if (bitsetHas(theParams.options, TRACKBAR_DISCRETE) && theParams.step != 0.) {
1592 long double k = (*theValue - theParams.min) / theParams.step;
1593 k = (
long double)cvRound((
double)k);
1594 *theValue = theParams.min + theParams.step * k;
1598 inline long double trackbarXPixelToValue(
const TrackbarParams & theParams, cv::Rect & theBounding,
int thePixelX)
1600 long double ratio = (thePixelX - (
long double)(theBounding.x + gTrackbarMarginX)) / (
long double)(theBounding.width - 2 * gTrackbarMarginX);
1601 ratio = clamp01(ratio);
1602 long double value = theParams.min + ratio * (theParams.max - theParams.min);
1606 inline int trackbarValueToXPixel(
const TrackbarParams & theParams, cv::Rect & theBounding,
long double theValue)
1608 long double aRatio = (theValue - theParams.min) / (theParams.max - theParams.min);
1609 aRatio = clamp01(aRatio);
1610 long double thePixelsX = (
long double)theBounding.x + gTrackbarMarginX + aRatio * (
long double)(theBounding.width - 2 * gTrackbarMarginX);
1611 return (
int)thePixelsX;
1614 int iarea(
int theX,
int theY,
int theWidth,
int theHeight) {
1615 cvui_mouse_t& aMouse = internal::getContext().mouse;
1618 int aRet = cvui::OUT;
1621 bool aMouseIsOver = cv::Rect(theX, theY, theWidth, theHeight).contains(aMouse.position);
1624 if (aMouse.anyButton.pressed) {
1632 if (aMouseIsOver && aMouse.anyButton.justReleased) {
1639 bool button(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theLabel,
bool theUpdateLayout) {
1641 cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1,
nullptr);
1644 cv::Rect aRect(theX, theY, theWidth, theHeight);
1647 int aStatus = cvui::iarea(theX, theY, aRect.width, aRect.height);
1648 render::button(theBlock, aStatus, aRect, theLabel);
1649 render::buttonLabel(theBlock, aStatus, aRect, theLabel, aTextSize);
1653 if (theUpdateLayout) {
1654 cv::Size aSize(theWidth, theHeight);
1655 updateLayoutFlow(theBlock, aSize);
1658 bool aWasShortcutPressed =
false;
1661 if (internal::gLastKeyPressed != -1) {
1663 auto aLabel = internal::createLabel(theLabel);
1664 if (aLabel.hasShortcut && (tolower(aLabel.shortcut) == tolower((
char)internal::gLastKeyPressed))) {
1665 aWasShortcutPressed =
true;
1670 return aStatus == cvui::CLICK || aWasShortcutPressed;
1673 bool button(cvui_block_t& theBlock,
int theX,
int theY,
const cv::String& theLabel) {
1675 cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1,
nullptr);
1678 return internal::button(theBlock, theX, theY, aTextSize.width + 30, aTextSize.height + 18, theLabel,
true);
1681 bool button(cvui_block_t& theBlock,
int theX,
int theY, cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown,
bool theUpdateLayout) {
1682 cv::Rect aRect(theX, theY, theIdle.cols, theIdle.rows);
1683 int aStatus = cvui::iarea(theX, theY, aRect.width, aRect.height);
1686 case cvui::OUT: render::image(theBlock, aRect, theIdle);
break;
1687 case cvui::OVER: render::image(theBlock, aRect, theOver);
break;
1688 case cvui::DOWN: render::image(theBlock, aRect, theDown);
break;
1693 if (theUpdateLayout) {
1694 cv::Size aSize(aRect.width, aRect.height);
1695 updateLayoutFlow(theBlock, aSize);
1699 return aStatus == cvui::CLICK;
1702 void image(cvui_block_t& theBlock,
int theX,
int theY, cv::Mat& theImage) {
1703 cv::Rect aRect(theX, theY, theImage.cols, theImage.rows);
1706 render::image(theBlock, aRect, theImage);
1709 cv::Size aSize(theImage.cols, theImage.rows);
1710 updateLayoutFlow(theBlock, aSize);
1713 bool checkbox(cvui_block_t& theBlock,
int theX,
int theY,
const cv::String& theLabel,
bool *theState,
unsigned int theColor) {
1714 cvui_mouse_t& aMouse = internal::getContext().mouse;
1715 cv::Rect aRect(theX, theY, 15, 15);
1716 cv::Size aTextSize = getTextSize(theLabel, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1,
nullptr);
1717 cv::Rect aHitArea(theX, theY, aRect.width + aTextSize.width + 6, aRect.height);
1718 bool aMouseIsOver = aHitArea.contains(aMouse.position);
1721 render::checkbox(theBlock, cvui::OVER, aRect);
1723 if (aMouse.anyButton.justReleased) {
1724 *theState = !(*theState);
1727 render::checkbox(theBlock, cvui::OUT, aRect);
1730 render::checkboxLabel(theBlock, aRect, theLabel, aTextSize, theColor);
1733 render::checkboxCheck(theBlock, aRect);
1737 cv::Size aSize(aHitArea.width, aHitArea.height);
1738 updateLayoutFlow(theBlock, aSize);
1743 void text(cvui_block_t& theBlock,
int theX,
int theY,
const cv::String& theText,
double theFontScale,
unsigned int theColor,
bool theUpdateLayout) {
1744 cv::Size aTextSize = cv::getTextSize(theText, cv::FONT_HERSHEY_SIMPLEX, theFontScale, 1,
nullptr);
1745 cv::Point aPos(theX, theY + aTextSize.height);
1747 render::text(theBlock, theText, aPos, theFontScale, theColor);
1749 if (theUpdateLayout) {
1751 aTextSize.height += 1;
1753 updateLayoutFlow(theBlock, aTextSize);
1757 int counter(cvui_block_t& theBlock,
int theX,
int theY,
int *theValue,
int theStep,
const char *theFormat) {
1758 cv::Rect aContentArea(theX + 22, theY, 48, 22);
1760 if (internal::button(theBlock, theX, theY, 22, 22,
"-",
false)) {
1761 *theValue -= theStep;
1764 sprintf_s(internal::gBuffer, theFormat, *theValue);
1765 render::counter(theBlock, aContentArea, internal::gBuffer);
1767 if (internal::button(theBlock, aContentArea.x + aContentArea.width, theY, 22, 22,
"+",
false)) {
1768 *theValue += theStep;
1772 cv::Size aSize(22 * 2 + aContentArea.width, aContentArea.height);
1773 updateLayoutFlow(theBlock, aSize);
1778 double counter(cvui_block_t& theBlock,
int theX,
int theY,
double *theValue,
double theStep,
const char *theFormat) {
1779 cv::Rect aContentArea(theX + 22, theY, 48, 22);
1781 if (internal::button(theBlock, theX, theY, 22, 22,
"-",
false)) {
1782 *theValue -= theStep;
1785 sprintf_s(internal::gBuffer, theFormat, *theValue);
1786 render::counter(theBlock, aContentArea, internal::gBuffer);
1788 if (internal::button(theBlock, aContentArea.x + aContentArea.width, theY, 22, 22,
"+",
false)) {
1789 *theValue += theStep;
1793 cv::Size aSize(22 * 2 + aContentArea.width, aContentArea.height);
1794 updateLayoutFlow(theBlock, aSize);
1799 bool trackbar(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
long double *theValue,
const TrackbarParams & theParams) {
1800 cvui_mouse_t& aMouse = internal::getContext().mouse;
1801 cv::Rect aContentArea(theX, theY, theWidth, 45);
1802 long double aValue = *theValue;
1803 bool aMouseIsOver = aContentArea.contains(aMouse.position);
1805 render::trackbar(theBlock, aMouseIsOver ? OVER : OUT, aContentArea, *theValue, theParams);
1807 if (aMouse.anyButton.pressed && aMouseIsOver) {
1808 *theValue = internal::trackbarXPixelToValue(theParams, aContentArea, aMouse.position.x);
1810 if (bitsetHas(theParams.options, TRACKBAR_DISCRETE)) {
1811 internal::trackbarForceValuesAsMultiplesOfSmallStep(theParams, theValue);
1816 cv::Size aSize = aContentArea.size();
1817 updateLayoutFlow(theBlock, aSize);
1819 return (*theValue != aValue);
1823 void window(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theTitle) {
1824 cv::Rect aTitleBar(theX, theY, theWidth, 20);
1825 cv::Rect aContent(theX, theY + aTitleBar.height, theWidth, theHeight - aTitleBar.height);
1827 render::window(theBlock, aTitleBar, aContent, theTitle);
1830 cv::Size aSize(theWidth, theHeight);
1831 updateLayoutFlow(theBlock, aSize);
1834 void rect(cvui_block_t& theBlock,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theBorderColor,
unsigned int theFillingColor) {
1835 cv::Point aAnchor(theX, theY);
1836 cv::Rect aRect(theX, theY, theWidth, theHeight);
1838 aRect.x = aRect.width < 0 ? aAnchor.x + aRect.width : aAnchor.x;
1839 aRect.y = aRect.height < 0 ? aAnchor.y + aRect.height : aAnchor.y;
1840 aRect.width = std::abs(aRect.width);
1841 aRect.height = std::abs(aRect.height);
1843 render::rect(theBlock, aRect, theBorderColor, theFillingColor);
1846 cv::Size aSize(aRect.width, aRect.height);
1847 updateLayoutFlow(theBlock, aSize);
1850 void sparkline(cvui_block_t& theBlock, std::vector<double>& theValues,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theColor) {
1852 cv::Rect aRect(theX, theY, theWidth, theHeight);
1853 std::vector<double>::size_type aHowManyValues = theValues.size();
1855 if (aHowManyValues >= 2) {
1856 internal::findMinMax(theValues, &aMin, &aMax);
1857 render::sparkline(theBlock, theValues, aRect, aMin, aMax, theColor);
1859 internal::text(theBlock, theX, theY, aHowManyValues == 0 ?
"No data." :
"Insufficient data points.", 0.4, 0xCECECE,
false);
1863 cv::Size aSize(theWidth, theHeight);
1864 updateLayoutFlow(theBlock, aSize);
1872 void text(cvui_block_t& theBlock,
const cv::String& theText, cv::Point& thePos,
double theFontScale,
unsigned int theColor) {
1873 cv::putText(theBlock.where, theText, thePos, cv::FONT_HERSHEY_SIMPLEX, theFontScale, internal::hexToScalar(theColor), 1, CVUI_ANTIALISED);
1876 void button(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
const cv::String& theLabel) {
1878 cv::rectangle(theBlock.where, theShape, cv::Scalar(0x29, 0x29, 0x29));
1881 theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
1882 cv::rectangle(theBlock.where, theShape, cv::Scalar(0x4A, 0x4A, 0x4A));
1885 theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
1886 cv::rectangle(theBlock.where, theShape, theState == OUT ? cv::Scalar(0x42, 0x42, 0x42) : (theState == OVER ? cv::Scalar(0x52, 0x52, 0x52) : cv::Scalar(0x32, 0x32, 0x32)), CVUI_FILLED);
1889 int putText(cvui_block_t& theBlock,
int theState, cv::Scalar aColor,
const std::string& theText,
const cv::Point & thePosition) {
1890 double aFontSize = theState == cvui::DOWN ? 0.39 : 0.4;
1893 if (theText !=
"") {
1894 cv::putText(theBlock.where, theText, thePosition, cv::FONT_HERSHEY_SIMPLEX, aFontSize, aColor, 1, CVUI_ANTIALISED);
1895 aSize = cv::getTextSize(theText, cv::FONT_HERSHEY_SIMPLEX, aFontSize, 1,
nullptr);
1901 int putTextCentered(cvui_block_t& theBlock,
const cv::Point & position,
const std::string &text) {
1902 double aFontScale = 0.3;
1904 auto size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, aFontScale, 1,
nullptr);
1905 cv::Point positionDecentered(position.x - size.width / 2, position.y);
1906 cv::putText(theBlock.where, text, positionDecentered, cv::FONT_HERSHEY_SIMPLEX, aFontScale, cv::Scalar(0xCE, 0xCE, 0xCE), 1, CVUI_ANTIALISED);
1911 void buttonLabel(cvui_block_t& theBlock,
int theState, cv::Rect theRect,
const cv::String& theLabel, cv::Size& theTextSize) {
1912 cv::Point aPos(theRect.x + theRect.width / 2 - theTextSize.width / 2, theRect.y + theRect.height / 2 + theTextSize.height / 2);
1913 cv::Scalar aColor = cv::Scalar(0xCE, 0xCE, 0xCE);
1915 auto aLabel = internal::createLabel(theLabel);
1917 if (!aLabel.hasShortcut) {
1918 putText(theBlock, theState, aColor, theLabel, aPos);
1921 int aWidth = putText(theBlock, theState, aColor, aLabel.textBeforeShortcut, aPos);
1922 int aStart = aPos.x + aWidth;
1925 std::string aShortcut;
1926 aShortcut.push_back(aLabel.shortcut);
1928 aWidth = putText(theBlock, theState, aColor, aShortcut, aPos);
1929 int aEnd = aStart + aWidth;
1932 putText(theBlock, theState, aColor, aLabel.textAfterShortcut, aPos);
1933 cv::line(theBlock.where, cv::Point(aStart, aPos.y + 3), cv::Point(aEnd, aPos.y + 3), aColor, 1, CVUI_ANTIALISED);
1937 void image(cvui_block_t& theBlock, cv::Rect& theRect, cv::Mat& theImage) {
1938 theImage.copyTo(theBlock.where(theRect));
1941 void counter(cvui_block_t& theBlock, cv::Rect& theShape,
const cv::String& theValue) {
1942 cv::rectangle(theBlock.where, theShape, cv::Scalar(0x29, 0x29, 0x29), CVUI_FILLED);
1943 cv::rectangle(theBlock.where, theShape, cv::Scalar(0x45, 0x45, 0x45));
1945 cv::Size aTextSize = getTextSize(theValue, cv::FONT_HERSHEY_SIMPLEX, 0.4, 1,
nullptr);
1947 cv::Point aPos(theShape.x + theShape.width / 2 - aTextSize.width / 2, theShape.y + aTextSize.height / 2 + theShape.height / 2);
1948 cv::putText(theBlock.where, theValue, aPos, cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, CVUI_ANTIALISED);
1951 void trackbarHandle(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea) {
1952 cv::Point aBarTopLeft(theWorkingArea.x, theWorkingArea.y + theWorkingArea.height / 2);
1956 int aPixelX = internal::trackbarValueToXPixel(theParams, theShape, theValue);
1957 int aIndicatorWidth = 5;
1958 int aIndicatorHeight = 8;
1959 cv::Point aPoint1(aPixelX - aIndicatorWidth, aBarTopLeft.y - aIndicatorHeight-4);
1960 cv::Point aPoint2(aPixelX + aIndicatorWidth, aBarTopLeft.y + aBarHeight + aIndicatorHeight-4);
1961 cv::Rect aRect(aPoint1, aPoint2);
1963 int aFillColor = theState == OVER ? 0x4084DF : 0x4084DF;
1967 rect(theBlock, aRect, aFillColor, aFillColor);
1969 bool aShowLabel = internal::bitsetHas(theParams.options, cvui::TRACKBAR_HIDE_VALUE_LABEL) ==
false;
1973 cv::Point aTextPos(aPixelX, aPoint2.y + 11);
1974 sprintf_s(internal::gBuffer, theParams.labelFormat.c_str(),
static_cast<long double>(theValue));
1975 putTextCentered(theBlock, aTextPos, internal::gBuffer);
1979 void trackbarPath(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea) {
1980 int aBarHeight = 22;
1982 cv::Point aBarTopLeft(theWorkingArea.x, theWorkingArea.y + 10);
1983 cv::Rect aRect(aBarTopLeft, cv::Size(theWorkingArea.width, aBarHeight));
1985 int aBorderColor = theState == OVER ? 0x4e4e4e : 0x3e3e3e;
1987 rect(theBlock, aRect, aBorderColor, 0x25354e);
1988 cv::line(theBlock.where, cv::Point(aRect.x + 1, aRect.y + aBarHeight - 2), cv::Point(aRect.x + aRect.width - 2, aRect.y + aBarHeight - 2), cv::Scalar(0x0e, 0x0e, 0x0e));
1991 void trackbarSteps(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea) {
1992 cv::Point aBarTopLeft(theWorkingArea.x, theWorkingArea.y + theWorkingArea.height / 2);
1993 cv::Scalar aColor(0x51, 0x51, 0x51);
1995 bool aDiscrete = internal::bitsetHas(theParams.options, cvui::TRACKBAR_DISCRETE);
1996 long double aFixedStep = aDiscrete ? theParams.step : (theParams.max - theParams.min) / 20;
1999 for (
long double aValue = theParams.min; aValue <= theParams.max; aValue += aFixedStep) {
2000 int aPixelX = internal::trackbarValueToXPixel(theParams, theShape, aValue);
2001 cv::Point aPoint1(aPixelX, aBarTopLeft.y);
2002 cv::Point aPoint2(aPixelX, aBarTopLeft.y - 3);
2003 cv::line(theBlock.where, aPoint1, aPoint2, aColor);
2007 void trackbarSegmentLabel(cvui_block_t& theBlock, cv::Rect& theShape,
const internal::TrackbarParams &theParams,
long double theValue, cv::Rect& theWorkingArea,
bool theShowLabel) {
2008 cv::Scalar aColor(0x51, 0x51, 0x51);
2009 cv::Point aBarTopLeft(theWorkingArea.x, theWorkingArea.y + theWorkingArea.height / 2);
2011 int aPixelX = internal::trackbarValueToXPixel(theParams, theShape, theValue);
2013 cv::Point aPoint1(aPixelX, aBarTopLeft.y);
2014 cv::Point aPoint2(aPixelX, aBarTopLeft.y - 8);
2015 cv::line(theBlock.where, aPoint1, aPoint2, aColor);
2019 sprintf_s(internal::gBuffer, theParams.labelFormat.c_str(), theValue);
2020 cv::Point aTextPos(aPixelX, aBarTopLeft.y - 11);
2021 putTextCentered(theBlock, aTextPos, internal::gBuffer);
2025 void trackbarSegments(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams, cv::Rect& theWorkingArea) {
2026 int aSegments = theParams.segments < 1 ? 1 : theParams.segments;
2027 long double aSegmentLength = (
long double)(theParams.max - theParams.min) / (
long double)aSegments;
2029 bool aHasMinMaxLabels = internal::bitsetHas(theParams.options, TRACKBAR_HIDE_MIN_MAX_LABELS) ==
false;
2032 trackbarSegmentLabel(theBlock, theShape, theParams, theParams.min, theWorkingArea, aHasMinMaxLabels);
2035 bool aHasSegmentLabels = internal::bitsetHas(theParams.options, TRACKBAR_HIDE_SEGMENT_LABELS) ==
false;
2037 for (
long double aValue = theParams.min; aValue <= theParams.max; aValue += aSegmentLength) {
2038 trackbarSegmentLabel(theBlock, theShape, theParams, aValue, theWorkingArea, aHasSegmentLabels);
2042 trackbarSegmentLabel(theBlock, theShape, theParams, theParams.max, theWorkingArea, aHasMinMaxLabels);
2045 void trackbar(cvui_block_t& theBlock,
int theState, cv::Rect& theShape,
double theValue,
const internal::TrackbarParams &theParams) {
2046 cv::Rect aWorkingArea(theShape.x + internal::gTrackbarMarginX, theShape.y, theShape.width - 2 * internal::gTrackbarMarginX, theShape.height);
2048 trackbarPath(theBlock, theState, theShape, theValue, theParams, aWorkingArea);
2050 bool aHideAllLabels = internal::bitsetHas(theParams.options, cvui::TRACKBAR_HIDE_LABELS);
2051 bool aShowSteps = internal::bitsetHas(theParams.options, cvui::TRACKBAR_HIDE_STEP_SCALE) ==
false;
2053 if (aShowSteps && !aHideAllLabels) {
2054 trackbarSteps(theBlock, theState, theShape, theValue, theParams, aWorkingArea);
2057 if (!aHideAllLabels) {
2058 trackbarSegments(theBlock, theState, theShape, theValue, theParams, aWorkingArea);
2061 trackbarHandle(theBlock, theState, theShape, theValue, theParams, aWorkingArea);
2064 void checkbox(cvui_block_t& theBlock,
int theState, cv::Rect& theShape) {
2066 cv::rectangle(theBlock.where, theShape, theState == OUT ? cv::Scalar(0x63, 0x63, 0x63) : cv::Scalar(0x80, 0x80, 0x80));
2069 theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
2070 cv::rectangle(theBlock.where, theShape, cv::Scalar(0x17, 0x17, 0x17));
2073 theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
2074 cv::rectangle(theBlock.where, theShape, cv::Scalar(0x29, 0x29, 0x29), CVUI_FILLED);
2077 void checkboxLabel(cvui_block_t& theBlock, cv::Rect& theRect,
const cv::String& theLabel, cv::Size& theTextSize,
unsigned int theColor) {
2078 cv::Point aPos(theRect.x + theRect.width + 6, theRect.y + theTextSize.height + theRect.height / 2 - theTextSize.height / 2 - 1);
2079 text(theBlock, theLabel, aPos, 0.4, theColor);
2082 void checkboxCheck(cvui_block_t& theBlock, cv::Rect& theShape) {
2083 theShape.x++; theShape.y++; theShape.width -= 2; theShape.height -= 2;
2084 cv::rectangle(theBlock.where, theShape, cv::Scalar(0xFF, 0xBF, 0x75), CVUI_FILLED);
2087 void window(cvui_block_t& theBlock, cv::Rect& theTitleBar, cv::Rect& theContent,
const cv::String& theTitle) {
2088 bool aTransparecy =
false;
2089 double aAlpha = 0.3;
2094 cv::rectangle(theBlock.where, theTitleBar, cv::Scalar(0x4A, 0x4A, 0x4A));
2096 theTitleBar.x++; theTitleBar.y++; theTitleBar.width -= 2; theTitleBar.height -= 2;
2097 cv::rectangle(theBlock.where, theTitleBar, cv::Scalar(0x21, 0x21, 0x21), CVUI_FILLED);
2100 cv::Point aPos(theTitleBar.x + 5, theTitleBar.y + 12);
2101 cv::putText(theBlock.where, theTitle, aPos, cv::FONT_HERSHEY_SIMPLEX, 0.4, cv::Scalar(0xCE, 0xCE, 0xCE), 1, CVUI_ANTIALISED);
2105 cv::rectangle(theBlock.where, theContent, cv::Scalar(0x4A, 0x4A, 0x4A));
2108 theContent.x++; theContent.y++; theContent.width -= 2; theContent.height -= 2;
2109 cv::rectangle(aOverlay, theContent, cv::Scalar(0x31, 0x31, 0x31), CVUI_FILLED);
2112 theBlock.where.copyTo(aOverlay);
2113 cv::rectangle(aOverlay, theContent, cv::Scalar(0x31, 0x31, 0x31), CVUI_FILLED);
2114 cv::addWeighted(aOverlay, aAlpha, theBlock.where, 1.0 - aAlpha, 0.0, theBlock.where);
2118 cv::rectangle(theBlock.where, theContent, cv::Scalar(0x31, 0x31, 0x31), CVUI_FILLED);
2122 void rect(cvui_block_t& theBlock, cv::Rect& thePos,
unsigned int theBorderColor,
unsigned int theFillingColor) {
2123 cv::Scalar aBorder = internal::hexToScalar(theBorderColor);
2124 cv::Scalar aFilling = internal::hexToScalar(theFillingColor);
2126 bool aHasFilling = aFilling[3] != 0xff;
2129 if (aFilling[3] == 0x00) {
2131 cv::rectangle(theBlock.where, thePos, aFilling, CVUI_FILLED, CVUI_ANTIALISED);
2134 cv::Rect aClippedRect = thePos & cv::Rect(cv::Point(0, 0), theBlock.where.size());
2135 double aAlpha = 1.00 -
static_cast<double>(aFilling[3]) / 255;
2136 cv::Mat aOverlay(aClippedRect.size(), theBlock.where.type(), aFilling);
2137 cv::addWeighted(aOverlay, aAlpha, theBlock.where(aClippedRect), 1.00 - aAlpha, 0.0, theBlock.where(aClippedRect));
2142 cv::rectangle(theBlock.where, thePos, aBorder, 1, CVUI_ANTIALISED);
2145 void sparkline(cvui_block_t& theBlock, std::vector<double>& theValues, cv::Rect &theRect,
double theMin,
double theMax,
unsigned int theColor) {
2146 std::vector<double>::size_type aSize = theValues.size(), i;
2147 double aGap, aPosX, aScale = 0, x, y;
2149 aScale = theMax - theMin;
2150 aGap = (double)theRect.width / aSize;
2153 for (i = 0; i <= aSize - 2; i++) {
2155 y = (theValues[i] - theMin) / aScale * -(theRect.height - 5) + theRect.y + theRect.height - 5;
2156 cv::Point aPoint1((
int)x, (
int)y);
2159 y = (theValues[i + 1] - theMin) / aScale * -(theRect.height - 5) + theRect.y + theRect.height - 5;
2160 cv::Point aPoint2((
int)x, (
int)y);
2162 cv::line(theBlock.where, aPoint1, aPoint2, internal::hexToScalar(theColor));
2168 void init(
const cv::String& theWindowName,
int theDelayWaitKey,
bool theCreateNamedWindow) {
2169 internal::init(theWindowName, theDelayWaitKey);
2170 watch(theWindowName, theCreateNamedWindow);
2173 void init(
const cv::String theWindowNames[],
size_t theHowManyWindows,
int theDelayWaitKey,
bool theCreateNamedWindows) {
2174 internal::init(theWindowNames[0], theDelayWaitKey);
2176 for (
size_t i = 0; i < theHowManyWindows; i++) {
2177 watch(theWindowNames[i], theCreateNamedWindows);
2181 void watch(
const cv::String& theWindowName,
bool theCreateNamedWindow) {
2182 cvui_context_t aContex;
2184 if (theCreateNamedWindow) {
2185 cv::namedWindow(theWindowName);
2188 aContex.windowName = theWindowName;
2189 aContex.mouse.position.x = 0;
2190 aContex.mouse.position.y = 0;
2192 internal::resetMouseButton(aContex.mouse.anyButton);
2193 internal::resetMouseButton(aContex.mouse.buttons[RIGHT_BUTTON]);
2194 internal::resetMouseButton(aContex.mouse.buttons[MIDDLE_BUTTON]);
2195 internal::resetMouseButton(aContex.mouse.buttons[LEFT_BUTTON]);
2197 internal::gContexts[theWindowName] = aContex;
2198 cv::setMouseCallback(theWindowName, handleMouse, &internal::gContexts[theWindowName]);
2201 void context(
const cv::String& theWindowName) {
2202 internal::gCurrentContext = theWindowName;
2205 void imshow(
const cv::String& theWindowName, cv::InputArray theFrame) {
2206 cvui::update(theWindowName);
2207 cv::imshow(theWindowName, theFrame);
2210 int lastKeyPressed() {
2211 return internal::gLastKeyPressed;
2214 cv::Point mouse(
const cv::String& theWindowName) {
2215 return internal::getContext(theWindowName).mouse.position;
2218 bool mouse(
int theQuery) {
2219 return mouse(
"", theQuery);
2222 bool mouse(
const cv::String& theWindowName,
int theQuery) {
2223 cvui_mouse_btn_t& aButton = internal::getContext(theWindowName).mouse.anyButton;
2224 bool aRet = internal::isMouseButton(aButton, theQuery);
2229 bool mouse(
int theButton,
int theQuery) {
2230 return mouse(
"", theButton, theQuery);
2233 bool mouse(
const cv::String& theWindowName,
int theButton,
int theQuery) {
2234 if (theButton != RIGHT_BUTTON && theButton != MIDDLE_BUTTON && theButton != LEFT_BUTTON) {
2235 internal::error(6,
"Invalid mouse button. Are you using one of the available: cvui::{RIGHT,MIDDLE,LEFT}_BUTTON ?");
2238 cvui_mouse_btn_t& aButton = internal::getContext(theWindowName).mouse.buttons[theButton];
2239 bool aRet = internal::isMouseButton(aButton, theQuery);
2244 bool button(cv::Mat& theWhere,
int theX,
int theY,
const cv::String& theLabel) {
2245 internal::gScreen.where = theWhere;
2246 return internal::button(internal::gScreen, theX, theY, theLabel);
2249 bool button(cv::Mat& theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theLabel) {
2250 internal::gScreen.where = theWhere;
2251 return internal::button(internal::gScreen, theX, theY, theWidth, theHeight, theLabel,
true);
2254 bool button(cv::Mat& theWhere,
int theX,
int theY, cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown) {
2255 internal::gScreen.where = theWhere;
2256 return internal::button(internal::gScreen, theX, theY, theIdle, theOver, theDown,
true);
2259 void image(cv::Mat& theWhere,
int theX,
int theY, cv::Mat& theImage) {
2260 internal::gScreen.where = theWhere;
2261 return internal::image(internal::gScreen, theX, theY, theImage);
2264 bool checkbox(cv::Mat& theWhere,
int theX,
int theY,
const cv::String& theLabel,
bool *theState,
unsigned int theColor) {
2265 internal::gScreen.where = theWhere;
2266 return internal::checkbox(internal::gScreen, theX, theY, theLabel, theState, theColor);
2269 void text(cv::Mat& theWhere,
int theX,
int theY,
const cv::String& theText,
double theFontScale,
unsigned int theColor) {
2270 internal::gScreen.where = theWhere;
2271 internal::text(internal::gScreen, theX, theY, theText, theFontScale, theColor,
true);
2274 void printf(cv::Mat& theWhere,
int theX,
int theY,
double theFontScale,
unsigned int theColor,
const char *theFmt, ...) {
2277 va_start(aArgs, theFmt);
2278 vsprintf_s(internal::gBuffer, theFmt, aArgs);
2281 internal::gScreen.where = theWhere;
2282 internal::text(internal::gScreen, theX, theY, internal::gBuffer, theFontScale, theColor,
true);
2285 void printf(cv::Mat& theWhere,
int theX,
int theY,
const char *theFmt, ...) {
2288 va_start(aArgs, theFmt);
2289 vsprintf_s(internal::gBuffer, theFmt, aArgs);
2292 internal::gScreen.where = theWhere;
2293 internal::text(internal::gScreen, theX, theY, internal::gBuffer, 0.4, 0xCECECE,
true);
2296 int counter(cv::Mat& theWhere,
int theX,
int theY,
int *theValue,
int theStep,
const char *theFormat) {
2297 internal::gScreen.where = theWhere;
2298 return internal::counter(internal::gScreen, theX, theY, theValue, theStep, theFormat);
2301 double counter(cv::Mat& theWhere,
int theX,
int theY,
double *theValue,
double theStep,
const char *theFormat) {
2302 internal::gScreen.where = theWhere;
2303 return internal::counter(internal::gScreen, theX, theY, theValue, theStep, theFormat);
2306 void window(cv::Mat& theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
const cv::String& theTitle) {
2307 internal::gScreen.where = theWhere;
2308 internal::window(internal::gScreen, theX, theY, theWidth, theHeight, theTitle);
2311 void rect(cv::Mat& theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theBorderColor,
unsigned int theFillingColor) {
2312 internal::gScreen.where = theWhere;
2313 internal::rect(internal::gScreen, theX, theY, theWidth, theHeight, theBorderColor, theFillingColor);
2316 void sparkline(cv::Mat& theWhere, std::vector<double>& theValues,
int theX,
int theY,
int theWidth,
int theHeight,
unsigned int theColor) {
2317 internal::gScreen.where = theWhere;
2318 internal::sparkline(internal::gScreen, theValues, theX, theY, theWidth, theHeight, theColor);
2321 int iarea(
int theX,
int theY,
int theWidth,
int theHeight) {
2322 return internal::iarea(theX, theY, theWidth, theHeight);
2325 void beginRow(cv::Mat &theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
int thePadding) {
2326 internal::begin(ROW, theWhere, theX, theY, theWidth, theHeight, thePadding);
2333 void beginColumn(cv::Mat &theWhere,
int theX,
int theY,
int theWidth,
int theHeight,
int thePadding) {
2334 internal::begin(COLUMN, theWhere, theX, theY, theWidth, theHeight, thePadding);
2338 internal::end(COLUMN);
2341 void beginRow(
int theWidth,
int theHeight,
int thePadding) {
2342 cvui_block_t& aBlock = internal::topBlock();
2343 internal::begin(ROW, aBlock.where, aBlock.anchor.x, aBlock.anchor.y, theWidth, theHeight, thePadding);
2346 void beginColumn(
int theWidth,
int theHeight,
int thePadding) {
2347 cvui_block_t& aBlock = internal::topBlock();
2348 internal::begin(COLUMN, aBlock.where, aBlock.anchor.x, aBlock.anchor.y, theWidth, theHeight, thePadding);
2351 void space(
int theValue) {
2352 cvui_block_t& aBlock = internal::topBlock();
2353 cv::Size aSize(theValue, theValue);
2355 internal::updateLayoutFlow(aBlock, aSize);
2358 bool button(
const cv::String& theLabel) {
2359 cvui_block_t& aBlock = internal::topBlock();
2360 return internal::button(aBlock, aBlock.anchor.x, aBlock.anchor.y, theLabel);
2363 bool button(
int theWidth,
int theHeight,
const cv::String& theLabel) {
2364 cvui_block_t& aBlock = internal::topBlock();
2365 return internal::button(aBlock, aBlock.anchor.x, aBlock.anchor.y, theWidth, theHeight, theLabel,
true);
2368 bool button(cv::Mat& theIdle, cv::Mat& theOver, cv::Mat& theDown) {
2369 cvui_block_t& aBlock = internal::topBlock();
2370 return internal::button(aBlock, aBlock.anchor.x, aBlock.anchor.y, theIdle, theOver, theDown,
true);
2373 void image(cv::Mat& theImage) {
2374 cvui_block_t& aBlock = internal::topBlock();
2375 return internal::image(aBlock, aBlock.anchor.x, aBlock.anchor.y, theImage);
2378 bool checkbox(
const cv::String& theLabel,
bool *theState,
unsigned int theColor) {
2379 cvui_block_t& aBlock = internal::topBlock();
2380 return internal::checkbox(aBlock, aBlock.anchor.x, aBlock.anchor.y, theLabel, theState, theColor);
2383 void text(
const cv::String& theText,
double theFontScale,
unsigned int theColor) {
2384 cvui_block_t& aBlock = internal::topBlock();
2385 internal::text(aBlock, aBlock.anchor.x, aBlock.anchor.y, theText, theFontScale, theColor,
true);
2388 void printf(
double theFontScale,
unsigned int theColor,
const char *theFmt, ...) {
2389 cvui_block_t& aBlock = internal::topBlock();
2392 va_start(aArgs, theFmt);
2393 vsprintf_s(internal::gBuffer, theFmt, aArgs);
2396 internal::text(aBlock, aBlock.anchor.x, aBlock.anchor.y, internal::gBuffer, theFontScale, theColor,
true);
2399 void printf(
const char *theFmt, ...) {
2400 cvui_block_t& aBlock = internal::topBlock();
2403 va_start(aArgs, theFmt);
2404 vsprintf_s(internal::gBuffer, theFmt, aArgs);
2407 internal::text(aBlock, aBlock.anchor.x, aBlock.anchor.y, internal::gBuffer, 0.4, 0xCECECE,
true);
2410 int counter(
int *theValue,
int theStep,
const char *theFormat) {
2411 cvui_block_t& aBlock = internal::topBlock();
2412 return internal::counter(aBlock, aBlock.anchor.x, aBlock.anchor.y, theValue, theStep, theFormat);
2415 double counter(
double *theValue,
double theStep,
const char *theFormat) {
2416 cvui_block_t& aBlock = internal::topBlock();
2417 return internal::counter(aBlock, aBlock.anchor.x, aBlock.anchor.y, theValue, theStep, theFormat);
2420 void window(
int theWidth,
int theHeight,
const cv::String& theTitle) {
2421 cvui_block_t& aBlock = internal::topBlock();
2422 internal::window(aBlock, aBlock.anchor.x, aBlock.anchor.y, theWidth, theHeight, theTitle);
2425 void rect(
int theWidth,
int theHeight,
unsigned int theBorderColor,
unsigned int theFillingColor) {
2426 cvui_block_t& aBlock = internal::topBlock();
2427 internal::rect(aBlock, aBlock.anchor.x, aBlock.anchor.y, theWidth, theHeight, theBorderColor, theFillingColor);
2430 void sparkline(std::vector<double>& theValues,
int theWidth,
int theHeight,
unsigned int theColor) {
2431 cvui_block_t& aBlock = internal::topBlock();
2432 internal::sparkline(aBlock, theValues, aBlock.anchor.x, aBlock.anchor.y, theWidth, theHeight, theColor);
2435 void update(
const cv::String& theWindowName) {
2436 cvui_context_t& aContext = internal::getContext(theWindowName);
2438 aContext.mouse.anyButton.justReleased =
false;
2439 aContext.mouse.anyButton.justPressed =
false;
2441 for (
int i = cvui::LEFT_BUTTON; i <= cvui::RIGHT_BUTTON; i++) {
2442 aContext.mouse.buttons[i].justReleased =
false;
2443 aContext.mouse.buttons[i].justPressed =
false;
2446 internal::resetRenderingBuffer(internal::gScreen);
2450 if (internal::gDelayWaitKey > 0) {
2451 internal::gLastKeyPressed = cv::waitKey(internal::gDelayWaitKey);
2454 if (!internal::blockStackEmpty()) {
2455 internal::error(2,
"Calling update() before finishing all begin*()/end*() calls. Did you forget to call a begin*() or an end*()? Check if every begin*() has an appropriate end*() call before you call update().");
2459 void handleMouse(
int theEvent,
int theX,
int theY,
int theFlags,
void* theData) {
2460 int aButtons[3] = { cvui::LEFT_BUTTON, cvui::MIDDLE_BUTTON, cvui::RIGHT_BUTTON };
2461 int aEventsDown[3] = { cv::EVENT_LBUTTONDOWN, cv::EVENT_MBUTTONDOWN, cv::EVENT_RBUTTONDOWN };
2462 int aEventsUp[3] = { cv::EVENT_LBUTTONUP, cv::EVENT_MBUTTONUP, cv::EVENT_RBUTTONUP };
2464 cvui_context_t *aContext = (cvui_context_t *)theData;
2466 for (
int i = 0; i < 3; i++) {
2467 int aBtn = aButtons[i];
2469 if (theEvent == aEventsDown[i]) {
2470 aContext->mouse.anyButton.justPressed =
true;
2471 aContext->mouse.anyButton.pressed =
true;
2472 aContext->mouse.buttons[aBtn].justPressed =
true;
2473 aContext->mouse.buttons[aBtn].pressed =
true;
2475 }
else if (theEvent == aEventsUp[i]) {
2476 aContext->mouse.anyButton.justReleased =
true;
2477 aContext->mouse.anyButton.pressed =
false;
2478 aContext->mouse.buttons[aBtn].justReleased =
true;
2479 aContext->mouse.buttons[aBtn].pressed =
false;
2483 aContext->mouse.position.x = theX;
2484 aContext->mouse.position.y = theY;
2496 const int MAX_RADIO_BUTTONS = 10;
2497 const int TRACKBAR_WIDTH = 300;
2498 const int TRACKBAR_OFFSET = 45;
2499 const int RADIOBUTTON_OFFSET = 30;
2500 const int BUTTON_OFFSET = 40;
2511 std::vector<radioStates> radio_states(MAX_RADIO_BUTTONS);
2513 int cur_trackbar = 0;
2514 int cur_button_lines = 0;
2516 template <
class T> T radioToValue(
bool * states, std::vector<T> values)
2518 for(
int i = 0; i < values.size(); i++)
2520 return values.at(i);
2522 throw "No state found as bool in cvui::radiobutton()!";
2525 template <
class T>
int radioToIndex(
bool * states, std::vector<T> values)
2527 for(
int i = 0; i < values.size(); i++)
2531 throw "No state found as bool in cvui::radiobutton()!";
2534 bool * prev_states = NULL;
2536 int getLastRadioIndex()
2538 for(
int i = 0; ; i++)
2539 if(radio_states.at(cur_radio-1).states[i])
2545 int getRadioIndex(
int ind)
2547 for(
int i = 0; ; i++)
2548 if(radio_states.at(ind).states[i])
2555 bool radioButtons(cv::Mat frame, std::string name,
const std::vector<std::string> names,
const std::vector<int> X,
int default_value)
2563 if(radio_states.at(cur_radio).states == NULL)
2566 radio_states.at(cur_radio).states =
new bool[names.size()];
2567 radio_states.at(cur_radio).prev_states =
new bool[names.size()];
2569 for(
int i = 0; i < names.size(); i++)
2571 radio_states.at(cur_radio).states[i] =
false;
2572 radio_states.at(cur_radio).prev_states[i] =
false;
2575 radio_states.at(cur_radio).states[default_value] =
true;
2576 radio_states.at(cur_radio).prev_states[default_value] =
true;
2580 cvui::text(frame, 10, 23 + TRACKBAR_OFFSET*cur_trackbar + RADIOBUTTON_OFFSET*cur_radio + BUTTON_OFFSET*cur_button_lines, name);
2582 for(
int i = 0; i < names.size(); i++)
2583 radio_states.at(cur_radio).states[i] = cvui::checkbox(frame, 130 + X.at(i), 21 + TRACKBAR_OFFSET*cur_trackbar + RADIOBUTTON_OFFSET*cur_radio + BUTTON_OFFSET*cur_button_lines, names.at(i), &radio_states.at(cur_radio).states[i]);
2585 for(
int i = 0; i < names.size(); i++)
2586 if(!radio_states.at(cur_radio).prev_states[i] && radio_states.at(cur_radio).states[i])
2594 for(
int i = 0; i < names.size(); i++)
2595 radio_states.at(cur_radio).states[i] =
false;
2597 radio_states.at(cur_radio).states[selected] =
true;
2599 for(
int i = 0; i < names.size(); i++)
2600 radio_states.at(cur_radio).prev_states[i] = radio_states.at(cur_radio).states[i];
2605 for(
int i = 0; i < names.size(); i++)
2606 radio_states.at(cur_radio).states[i] = radio_states.at(cur_radio).prev_states[i];
2611 return selected != -1;
2614 template <
class T>
bool trackbar(
const char * theName, cv::Mat &theWhere, T *theValue, T theMin, T theMax,
int theSegments = 1,
const char *theLabelFormat =
"%.1Lf",
unsigned int theOptions = 0, T theDiscreteStep = 1)
2617 bool status = cvui::trackbar(theWhere, 0, 5+TRACKBAR_OFFSET*cur_trackbar + RADIOBUTTON_OFFSET*cur_radio + BUTTON_OFFSET*cur_button_lines, TRACKBAR_WIDTH, theValue, theMin, theMax, theSegments, theLabelFormat, theOptions, theDiscreteStep);
2618 cvui::text(theWhere, 295, 21+TRACKBAR_OFFSET*cur_trackbar + RADIOBUTTON_OFFSET*cur_radio + BUTTON_OFFSET*cur_button_lines, theName);
2626 bool button(cv::Mat theWhere, std::string label,
int theX,
int button_line)
2629 if(button_line >= cur_button_lines)
2632 int button_height = TRACKBAR_OFFSET*cur_trackbar + RADIOBUTTON_OFFSET*cur_radio + BUTTON_OFFSET*button_line + 20;
2633 return cvui::button(theWhere, theX, button_height, label);
2640 cur_button_lines = 0;
2643 int estimateHeight(
int trackbars,
int radioButtons,
int button_lines)
2645 return TRACKBAR_OFFSET*trackbars + RADIOBUTTON_OFFSET*radioButtons + BUTTON_OFFSET*button_lines + 20;
2658 #define min __cvui_min
2661 #define max __cvui_max