39 #include <visp3/core/vpConfig.h>
41 #if (defined(VISP_HAVE_GDI))
43 #ifndef DOXYGEN_SHOULD_SKIP_THIS
45 #include <visp3/gui/vpGDIRenderer.h>
50 vpGDIRenderer::vpGDIRenderer() : m_bmp(nullptr), m_bmp_width(0), m_bmp_height(0), timelost(0)
53 int bpp = GetDeviceCaps(GetDC(
nullptr), BITSPIXEL);
56 "vpGDIRenderer supports only 32bits depth: screen is %dbits depth!", bpp);
58 InitializeCriticalSection(&m_criticalSection);
107 vpGDIRenderer::~vpGDIRenderer()
110 DeleteCriticalSection(&m_criticalSection);
114 DeleteObject(m_hFont);
123 bool vpGDIRenderer::init(HWND hWindow,
unsigned int width,
unsigned int height)
132 m_hFont = CreateFont(18, 0, 0, 0, FW_NORMAL,
false,
false,
false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
133 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
nullptr);
156 convertROI(I, iP, width, height);
179 convertROI(I, iP, width, height);
185 bool vpGDIRenderer::render()
189 HDC hDCScreen = BeginPaint(m_hWnd, &ps);
192 HDC hDCMem = CreateCompatibleDC(hDCScreen);
195 EnterCriticalSection(&m_criticalSection);
196 SelectObject(hDCMem, m_bmp);
199 BitBlt(hDCScreen, 0, 0,
static_cast<int>(m_rwidth),
static_cast<int>(m_rheight), hDCMem, 0, 0, SRCCOPY);
201 LeaveCriticalSection(&m_criticalSection);
203 DeleteObject(hDCMem);
205 EndPaint(m_hWnd, &ps);
218 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
221 for (
unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, ++k) {
222 imBuffer[i + 0] = I.
bitmap[k].B;
223 imBuffer[i + 1] = I.
bitmap[k].G;
224 imBuffer[i + 2] = I.
bitmap[k].R;
225 imBuffer[i + 3] = I.
bitmap[k].A;
229 for (
unsigned int i = 0; i < m_rheight; ++i) {
230 unsigned int i_ = i * m_rscale;
231 unsigned int ii_ = i * m_rwidth;
232 for (
unsigned int j = 0; j < m_rwidth; ++j) {
233 vpRGBa val = I[i_][j * m_rscale];
234 unsigned int index_ = (ii_ + j) * 4;
235 imBuffer[index_] = val.
B;
236 imBuffer[++index_] = val.
G;
237 imBuffer[++index_] = val.
R;
238 imBuffer[++index_] = val.
A;
244 updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
259 int i_min = std::max<int>((
int)ceil(iP.
get_i() / m_rscale), 0);
260 int j_min = std::max<int>((
int)ceil(iP.
get_j() / m_rscale), 0);
261 int i_max = std::min<int>((
int)ceil((iP.
get_i() + height) / m_rscale), (
int)m_rheight);
262 int j_max = std::min<int>((
int)ceil((iP.
get_j() + width) / m_rscale), (
int)m_rwidth);
264 int h = i_max - i_min;
265 int w = j_max - j_min;
268 unsigned char *imBuffer =
new unsigned char[w * h * 4];
273 bitmap = bitmap + (int)(i_min * iwidth + j_min);
276 for (
int i = 0; i < w * h * 4; i += 4) {
277 imBuffer[i + 0] = (bitmap + k)->B;
278 imBuffer[i + 1] = (bitmap + k)->G;
279 imBuffer[i + 2] = (bitmap + k)->R;
280 imBuffer[i + 3] = (bitmap + k)->A;
284 bitmap = bitmap + iwidth;
290 for (
int i = 0; i < h; ++i) {
291 unsigned int i_ = (i_min + i) * m_rscale;
292 unsigned int ii_ = i * w;
293 for (
int j = 0; j < w; ++j) {
294 vpRGBa val = I[i_][(j_min + j) * m_rscale];
295 unsigned int index_ = (ii_ + j) * 4;
296 imBuffer[index_] = val.
B;
297 imBuffer[++index_] = val.
G;
298 imBuffer[++index_] = val.
R;
299 imBuffer[++index_] = val.
A;
305 updateBitmapROI(imBuffer, i_min, j_min, w, h);
319 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
322 for (
unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, ++k) {
323 imBuffer[i + 0] = I.
bitmap[k];
324 imBuffer[i + 1] = I.
bitmap[k];
325 imBuffer[i + 2] = I.
bitmap[k];
330 for (
unsigned int i = 0; i < m_rheight; ++i) {
331 unsigned int i_ = i * m_rscale;
332 unsigned int ii_ = i * m_rwidth;
333 for (
unsigned int j = 0; j < m_rwidth; ++j) {
334 unsigned char val = I[i_][j * m_rscale];
335 unsigned int index_ = (ii_ + j) * 4;
336 imBuffer[index_] = val;
337 imBuffer[++index_] = val;
338 imBuffer[++index_] = val;
345 updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
360 int i_min = std::max<int>((
int)ceil(iP.
get_i() / m_rscale), 0);
361 int j_min = std::max<int>((
int)ceil(iP.
get_j() / m_rscale), 0);
362 int i_max = std::min<int>((
int)ceil((iP.
get_i() + height) / m_rscale), (
int)m_rheight);
363 int j_max = std::min<int>((
int)ceil((iP.
get_j() + width) / m_rscale), (
int)m_rwidth);
365 int h = i_max - i_min;
366 int w = j_max - j_min;
369 unsigned char *imBuffer =
new unsigned char[w * h * 4];
372 for (
int i = 0; i < h; ++i) {
373 unsigned int i_ = i_min + i;
374 unsigned int ii_ = i * w;
375 for (
int j = 0; j < w; ++j) {
376 unsigned char val = I[i_][j_min + j];
377 unsigned int index_ = (ii_ + j) * 4;
378 imBuffer[index_] = val;
379 imBuffer[++index_] = val;
380 imBuffer[++index_] = val;
386 for (
int i = 0; i < h; ++i) {
387 unsigned int i_ = (i_min + i) * m_rscale;
388 unsigned int ii_ = i * w;
389 for (
int j = 0; j < w; ++j) {
390 unsigned char val = I[i_][(j_min + j) * m_rscale];
391 unsigned int index_ = (ii_ + j) * 4;
392 imBuffer[index_] = val;
393 imBuffer[++index_] = val;
394 imBuffer[++index_] = val;
401 updateBitmapROI(imBuffer, i_min, j_min, w, h);
417 bool vpGDIRenderer::updateBitmap(HBITMAP &hBmp,
unsigned char *imBuffer,
unsigned int w,
unsigned int h)
421 EnterCriticalSection(&m_criticalSection);
424 if ((m_bmp_width == w) && (m_bmp_height == h) && w != 0 && h != 0) {
426 SetBitmapBits(hBmp, w * h * 4, imBuffer);
429 if (hBmp !=
nullptr) {
434 if ((hBmp = CreateBitmap(
static_cast<int>(w),
static_cast<int>(h), 1, 32, (
void *)imBuffer)) ==
nullptr)
441 LeaveCriticalSection(&m_criticalSection);
455 bool vpGDIRenderer::updateBitmapROI(
unsigned char *imBuffer,
int i_min,
int j_min,
int w,
int h)
457 HBITMAP htmp = CreateBitmap(w, h, 1, 32, (
void *)imBuffer);
460 HDC hDCScreen = GetDC(m_hWnd);
461 HDC hDCMem = CreateCompatibleDC(hDCScreen);
462 HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
465 EnterCriticalSection(&m_criticalSection);
466 SelectObject(hDCMem, m_bmp);
467 SelectObject(hDCMem2, htmp);
469 BitBlt(hDCMem, j_min, i_min, w, h, hDCMem2, 0, 0, SRCCOPY);
470 LeaveCriticalSection(&m_criticalSection);
473 ReleaseDC(m_hWnd, hDCScreen);
488 HDC hDCScreen = GetDC(m_hWnd);
489 HDC hDCMem = CreateCompatibleDC(hDCScreen);
492 EnterCriticalSection(&m_criticalSection);
493 SelectObject(hDCMem, m_bmp);
498 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
504 LeaveCriticalSection(&m_criticalSection);
507 ReleaseDC(m_hWnd, hDCScreen);
518 unsigned int thickness,
int style)
520 HDC hDCScreen =
nullptr, hDCMem =
nullptr;
525 hDCScreen = GetDC(m_hWnd);
528 hDCMem = CreateCompatibleDC(hDCScreen);
530 ReleaseDC(m_hWnd, hDCScreen);
536 hPen = CreatePen(style,
static_cast<int>(thickness), m_colors[color.
id]);
538 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
539 hPen = CreatePen(style,
static_cast<int>(thickness), gdicolor);
543 ReleaseDC(m_hWnd, hDCScreen);
546 if (!SetBkMode(hDCMem, TRANSPARENT)) {
549 ReleaseDC(m_hWnd, hDCScreen);
554 EnterCriticalSection(&m_criticalSection);
556 if (!SelectObject(hDCMem, m_bmp)) {
557 LeaveCriticalSection(&m_criticalSection);
560 ReleaseDC(m_hWnd, hDCScreen);
565 if (!SelectObject(hDCMem, hPen)) {
566 LeaveCriticalSection(&m_criticalSection);
569 ReleaseDC(m_hWnd, hDCScreen);
577 hDCScreen = GetDC(m_hWnd);
578 hDCMem = CreateCompatibleDC(hDCScreen);
581 hPen = CreatePen(style,
static_cast<int>(thickness), m_colors[color.
id]);
583 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
584 hPen = CreatePen(style,
static_cast<int>(thickness), gdicolor);
586 SetBkMode(hDCMem, TRANSPARENT);
589 EnterCriticalSection(&m_criticalSection);
590 SelectObject(hDCMem, m_bmp);
593 SelectObject(hDCMem, hPen);
598 if (thickness != 1 && style != PS_SOLID) {
602 double size = 10. * m_rscale;
604 bool vertical_line = (int)ip2_.
get_j() == (int)ip1_.
get_j();
607 std::swap(ip1_, ip2_);
611 std::swap(ip1_, ip2_);
614 double diff_j = vertical_line ? 1 : ip2_.
get_j() - ip1_.
get_j();
615 double deltaj = size / length * diff_j;
616 double deltai = size / length * (ip2_.
get_i() - ip1_.
get_i());
617 double slope = (ip2_.
get_i() - ip1_.
get_i()) / diff_j;
618 double orig = ip1_.
get_i() - slope * ip1_.
get_j();
621 for (
unsigned int i = (
unsigned int)ip1_.
get_i(); i < ip2_.
get_i(); i += (
unsigned int)(2 * deltai)) {
622 double j = ip1_.
get_j();
631 for (
unsigned int j = (
unsigned int)ip1_.
get_j(); j < ip2_.
get_j(); j += (
unsigned int)(2 * deltaj)) {
632 double i = slope * j + orig;
647 LeaveCriticalSection(&m_criticalSection);
651 ReleaseDC(m_hWnd, hDCScreen);
663 void vpGDIRenderer::drawRect(
const vpImagePoint &topLeft,
unsigned int width,
unsigned int height,
const vpColor &color,
664 bool fill,
unsigned int thickness)
669 HDC hDCScreen = GetDC(m_hWnd);
670 HDC hDCMem = CreateCompatibleDC(hDCScreen);
674 COLORREF gdicolor = RGB(0, 0, 0);
677 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
679 gdicolor = RGB(color.
R, color.
G, color.
B);
680 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
686 lBrush.lbStyle = BS_SOLID;
688 lBrush.lbColor = m_colors[color.
id];
690 lBrush.lbColor = gdicolor;
694 lBrush.lbStyle = BS_HOLLOW;
695 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
698 EnterCriticalSection(&m_criticalSection);
699 SelectObject(hDCMem, m_bmp);
702 SelectObject(hDCMem, hbrush);
704 SelectObject(hDCMem, hPen);
713 LeaveCriticalSection(&m_criticalSection);
715 DeleteObject(hbrush);
718 ReleaseDC(m_hWnd, hDCScreen);
725 void vpGDIRenderer::clear(
const vpColor &color)
730 drawRect(ip, m_rwidth, m_rheight, color,
true, 0);
741 void vpGDIRenderer::drawCircle(
const vpImagePoint ¢er,
unsigned int radius,
const vpColor &color,
bool fill,
742 unsigned int thickness)
746 HDC hDCScreen = GetDC(m_hWnd);
747 HDC hDCMem = CreateCompatibleDC(hDCScreen);
752 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
754 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
755 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
760 lBrush.lbStyle = BS_HOLLOW;
761 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
764 int radius_ =
static_cast<int>(radius);
771 EnterCriticalSection(&m_criticalSection);
772 SelectObject(hDCMem, m_bmp);
775 SelectObject(hDCMem, hbrush);
777 SelectObject(hDCMem, hPen);
781 Ellipse(hDCMem, x1, y1, x2, y2);
784 while (x2 - x1 > 0) {
789 Ellipse(hDCMem, x1, y1, x2, y2);
796 LeaveCriticalSection(&m_criticalSection);
798 DeleteObject(hbrush);
801 ReleaseDC(m_hWnd, hDCScreen);
810 void vpGDIRenderer::drawText(
const vpImagePoint &ip,
const char *text,
const vpColor &color)
813 HDC hDCScreen = GetDC(m_hWnd);
814 HDC hDCMem = CreateCompatibleDC(hDCScreen);
817 EnterCriticalSection(&m_criticalSection);
818 SelectObject(hDCMem, m_bmp);
821 SelectObject(hDCMem, m_hFont);
825 SetTextColor(hDCMem, m_colors[color.
id]);
827 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
828 SetTextColor(hDCMem, gdicolor);
832 SetBkMode(hDCMem, TRANSPARENT);
835 int length = (int)strlen(text);
838 GetTextExtentPoint32(hDCMem, text, length, &size);
846 LeaveCriticalSection(&m_criticalSection);
849 ReleaseDC(m_hWnd, hDCScreen);
859 void vpGDIRenderer::drawCross(
const vpImagePoint &ip,
unsigned int size,
const vpColor &color,
unsigned int thickness)
861 int half_size =
static_cast<int>(size / 2 / m_rscale);
868 HDC hDCScreen = GetDC(m_hWnd);
869 HDC hDCMem = CreateCompatibleDC(hDCScreen);
874 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
876 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
877 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
881 EnterCriticalSection(&m_criticalSection);
882 SelectObject(hDCMem, m_bmp);
885 SelectObject(hDCMem, hPen);
900 LeaveCriticalSection(&m_criticalSection);
904 ReleaseDC(m_hWnd, hDCScreen);
919 unsigned int h,
unsigned int thickness)
921 double a = ip2.
get_i() / m_rscale - ip1.
get_i() / m_rscale;
922 double b = ip2.
get_j() / m_rscale - ip1.
get_j() / m_rscale;
932 HDC hDCScreen = GetDC(m_hWnd);
933 HDC hDCMem = CreateCompatibleDC(hDCScreen);
938 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
940 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
941 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
945 EnterCriticalSection(&m_criticalSection);
946 SelectObject(hDCMem, m_bmp);
949 SelectObject(hDCMem, hPen);
951 if ((a == 0) && (b == 0)) {
997 LeaveCriticalSection(&m_criticalSection);
1001 ReleaseDC(m_hWnd, hDCScreen);
1011 unsigned int size = m_rwidth * m_rheight * 4;
1012 unsigned char *imBuffer =
new unsigned char[size];
1015 GetBitmapBits(m_bmp,
static_cast<LONG
>(size), (
void *)imBuffer);
1018 I.
resize(m_rheight, m_rwidth);
1021 for (
unsigned int i = 0; i < size; i += 4) {
1022 I.
bitmap[i >> 2].R = imBuffer[i + 2];
1023 I.
bitmap[i >> 2].G = imBuffer[i + 1];
1024 I.
bitmap[i >> 2].B = imBuffer[i + 0];
1031 #elif !defined(VISP_BUILD_SHARED_LIBS)
1033 void dummy_vpGDIRenderer() { };
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.
@ depthNotSupportedError
Color depth not supported.
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
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Type * bitmap
points toward the bitmap
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.
VISP_EXPORT double measureTimeMs()