34#include <visp3/core/vpConfig.h>
36#if (defined(VISP_HAVE_GDI))
38#ifndef DOXYGEN_SHOULD_SKIP_THIS
40#include <visp3/gui/vpGDIRenderer.h>
47vpGDIRenderer::vpGDIRenderer() : m_bmp(nullptr), m_bmp_width(0), m_bmp_height(0), timelost(0)
50 int bpp = GetDeviceCaps(GetDC(
nullptr), BITSPIXEL);
53 "vpGDIRenderer supports only 32bits depth: screen is %dbits depth!", bpp);
55 InitializeCriticalSection(&m_criticalSection);
104vpGDIRenderer::~vpGDIRenderer()
107 DeleteCriticalSection(&m_criticalSection);
111 DeleteObject(m_hFont);
120bool vpGDIRenderer::init(HWND hWindow,
unsigned int width,
unsigned int height)
129 m_hFont = CreateFont(18, 0, 0, 0, FW_NORMAL,
false,
false,
false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
130 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
nullptr);
154 convertROI(I, iP, width, height);
178 convertROI(I, iP, width, height);
184bool vpGDIRenderer::render()
188 HDC hDCScreen = BeginPaint(m_hWnd, &ps);
191 HDC hDCMem = CreateCompatibleDC(hDCScreen);
194 EnterCriticalSection(&m_criticalSection);
195 SelectObject(hDCMem, m_bmp);
198 BitBlt(hDCScreen, 0, 0,
static_cast<int>(m_rwidth),
static_cast<int>(m_rheight), hDCMem, 0, 0, SRCCOPY);
200 LeaveCriticalSection(&m_criticalSection);
202 DeleteObject(hDCMem);
204 EndPaint(m_hWnd, &ps);
217 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
220 for (
unsigned int i = 0, k = 0;
i < m_rwidth * m_rheight * 4;
i += 4, ++k) {
221 imBuffer[
i + 0] = I.bitmap[k].B;
222 imBuffer[
i + 1] = I.bitmap[k].G;
223 imBuffer[
i + 2] = I.bitmap[k].R;
224 imBuffer[
i + 3] = I.bitmap[k].A;
228 for (
unsigned int i = 0;
i < m_rheight; ++
i) {
229 unsigned int i_ =
i * m_rscale;
230 unsigned int ii_ =
i * m_rwidth;
231 for (
unsigned int j = 0;
j < m_rwidth; ++
j) {
232 vpRGBa val = I[i_][
j * m_rscale];
233 unsigned int index_ = (ii_ +
j) * 4;
234 imBuffer[index_] = val.
B;
235 imBuffer[++index_] = val.
G;
236 imBuffer[++index_] = val.
R;
237 imBuffer[++index_] = val.
A;
243 updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
259 int i_min = std::max<int>(
static_cast<int>(ceil(iP.
get_i() / m_rscale)), 0);
260 int j_min = std::max<int>(
static_cast<int>(ceil(iP.
get_j() / m_rscale)), 0);
261 int i_max = std::min<int>(
static_cast<int>(ceil((iP.
get_i() + height) / m_rscale)),
static_cast<int>(m_rheight));
262 int j_max = std::min<int>(
static_cast<int>(ceil((iP.
get_j() + width) / m_rscale)),
static_cast<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];
271 vpRGBa *bitmap = I.bitmap;
272 unsigned int iwidth = I.getWidth();
273 bitmap = bitmap +
static_cast<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);
361 int i_min = std::max<int>(
static_cast<int>(ceil(iP.
get_i() / m_rscale)), 0);
362 int j_min = std::max<int>(
static_cast<int>(ceil(iP.
get_j() / m_rscale)), 0);
363 int i_max = std::min<int>(
static_cast<int>(ceil((iP.
get_i() + height) / m_rscale)),
static_cast<int>(m_rheight));
364 int j_max = std::min<int>(
static_cast<int>(ceil((iP.
get_j() + width) / m_rscale)),
static_cast<int>(m_rwidth));
366 int h = i_max - i_min;
367 int w = j_max - j_min;
370 unsigned char *imBuffer =
new unsigned char[
w *
h * 4];
373 for (
int i = 0;
i <
h; ++
i) {
374 unsigned int i_ = i_min +
i;
375 unsigned int ii_ =
i *
w;
376 for (
int j = 0;
j <
w; ++
j) {
377 unsigned char val = I[i_][j_min +
j];
378 unsigned int index_ = (ii_ +
j) * 4;
379 imBuffer[index_] = val;
380 imBuffer[++index_] = val;
381 imBuffer[++index_] = val;
387 for (
int i = 0;
i <
h; ++
i) {
388 unsigned int i_ = (i_min +
i) * m_rscale;
389 unsigned int ii_ =
i *
w;
390 for (
int j = 0;
j <
w; ++
j) {
391 unsigned char val = I[i_][(j_min +
j) * m_rscale];
392 unsigned int index_ = (ii_ +
j) * 4;
393 imBuffer[index_] = val;
394 imBuffer[++index_] = val;
395 imBuffer[++index_] = val;
402 updateBitmapROI(imBuffer, i_min, j_min, w, h);
418bool vpGDIRenderer::updateBitmap(HBITMAP &hBmp,
unsigned char *imBuffer,
unsigned int w,
unsigned int h)
422 EnterCriticalSection(&m_criticalSection);
425 if ((m_bmp_width == w) && (m_bmp_height == h) && w != 0 && h != 0) {
427 SetBitmapBits(hBmp, w * h * 4, imBuffer);
430 if (hBmp !=
nullptr) {
435 if ((hBmp = CreateBitmap(
static_cast<int>(w),
static_cast<int>(h), 1, 32, (
void *)imBuffer)) ==
nullptr)
442 LeaveCriticalSection(&m_criticalSection);
457bool vpGDIRenderer::updateBitmapROI(
unsigned char *imBuffer,
int i_min,
int j_min,
int w,
int h)
459 HBITMAP htmp = CreateBitmap(w, h, 1, 32, (
void *)imBuffer);
462 HDC hDCScreen = GetDC(m_hWnd);
463 HDC hDCMem = CreateCompatibleDC(hDCScreen);
464 HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
467 EnterCriticalSection(&m_criticalSection);
468 SelectObject(hDCMem, m_bmp);
469 SelectObject(hDCMem2, htmp);
471 BitBlt(hDCMem, j_min, i_min, w, h, hDCMem2, 0, 0, SRCCOPY);
472 LeaveCriticalSection(&m_criticalSection);
475 ReleaseDC(m_hWnd, hDCScreen);
490 HDC hDCScreen = GetDC(m_hWnd);
491 HDC hDCMem = CreateCompatibleDC(hDCScreen);
494 EnterCriticalSection(&m_criticalSection);
495 SelectObject(hDCMem, m_bmp);
506 LeaveCriticalSection(&m_criticalSection);
509 ReleaseDC(m_hWnd, hDCScreen);
521 unsigned int thickness,
int style)
523 HDC hDCScreen =
nullptr, hDCMem =
nullptr;
528 hDCScreen = GetDC(m_hWnd);
532 hDCMem = CreateCompatibleDC(hDCScreen);
534 ReleaseDC(m_hWnd, hDCScreen);
540 hPen = CreatePen(style,
static_cast<int>(thickness), m_colors[
color.id]);
543 hPen = CreatePen(style,
static_cast<int>(thickness), gdicolor);
547 ReleaseDC(m_hWnd, hDCScreen);
550 if (!SetBkMode(hDCMem, TRANSPARENT)) {
553 ReleaseDC(m_hWnd, hDCScreen);
558 EnterCriticalSection(&m_criticalSection);
560 if (!SelectObject(hDCMem, m_bmp)) {
561 LeaveCriticalSection(&m_criticalSection);
564 ReleaseDC(m_hWnd, hDCScreen);
569 if (!SelectObject(hDCMem, hPen)) {
570 LeaveCriticalSection(&m_criticalSection);
573 ReleaseDC(m_hWnd, hDCScreen);
581 hDCScreen = GetDC(m_hWnd);
582 hDCMem = CreateCompatibleDC(hDCScreen);
585 hPen = CreatePen(style,
static_cast<int>(thickness), m_colors[
color.id]);
588 hPen = CreatePen(style,
static_cast<int>(thickness), gdicolor);
590 SetBkMode(hDCMem, TRANSPARENT);
593 EnterCriticalSection(&m_criticalSection);
594 SelectObject(hDCMem, m_bmp);
597 SelectObject(hDCMem, hPen);
602 if (thickness != 1 && style != PS_SOLID) {
606 double size = 10. * m_rscale;
608 bool vertical_line =
static_cast<int>(ip2_.
get_j()) ==
static_cast<int>(ip1_.
get_j());
611 std::swap(ip1_, ip2_);
615 std::swap(ip1_, ip2_);
618 double diff_j = vertical_line ? 1 : ip2_.
get_j() - ip1_.
get_j();
619 double deltaj = size / length * diff_j;
620 double deltai = size / length * (ip2_.
get_i() - ip1_.
get_i());
621 double slope = (ip2_.
get_i() - ip1_.
get_i()) / diff_j;
622 double orig = ip1_.
get_i() - slope * ip1_.
get_j();
625 for (
unsigned int i =
static_cast<unsigned int>(ip1_.
get_i()); i < ip2_.
get_i(); i +=
static_cast<unsigned int>(2 * deltai)) {
635 for (
unsigned int j =
static_cast<unsigned int>(ip1_.
get_j()); j < ip2_.
get_j(); j +=
static_cast<unsigned int>(2 * deltaj)) {
636 double i = slope *
j + orig;
651 LeaveCriticalSection(&m_criticalSection);
655 ReleaseDC(m_hWnd, hDCScreen);
667void vpGDIRenderer::drawRect(
const vpImagePoint &topLeft,
unsigned int width,
unsigned int height,
const vpColor &color,
668 bool fill,
unsigned int thickness)
673 HDC hDCScreen = GetDC(m_hWnd);
674 HDC hDCMem = CreateCompatibleDC(hDCScreen);
678 COLORREF gdicolor = RGB(0, 0, 0);
681 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[
color.id]);
684 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
690 lBrush.lbStyle = BS_SOLID;
692 lBrush.lbColor = m_colors[
color.id];
694 lBrush.lbColor = gdicolor;
698 lBrush.lbStyle = BS_HOLLOW;
699 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
702 EnterCriticalSection(&m_criticalSection);
703 SelectObject(hDCMem, m_bmp);
706 SelectObject(hDCMem, hbrush);
708 SelectObject(hDCMem, hPen);
717 LeaveCriticalSection(&m_criticalSection);
719 DeleteObject(hbrush);
722 ReleaseDC(m_hWnd, hDCScreen);
729void vpGDIRenderer::clear(
const vpColor &color)
734 drawRect(ip, m_rwidth, m_rheight, color,
true, 0);
745void vpGDIRenderer::drawCircle(
const vpImagePoint ¢er,
unsigned int radius,
const vpColor &color,
bool fill,
746 unsigned int thickness)
750 HDC hDCScreen = GetDC(m_hWnd);
751 HDC hDCMem = CreateCompatibleDC(hDCScreen);
756 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[
color.id]);
759 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
764 lBrush.lbStyle = BS_HOLLOW;
765 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
768 int radius_ =
static_cast<int>(radius);
775 EnterCriticalSection(&m_criticalSection);
776 SelectObject(hDCMem, m_bmp);
779 SelectObject(hDCMem, hbrush);
781 SelectObject(hDCMem, hPen);
785 Ellipse(hDCMem, x1, y1, x2, y2);
788 while (x2 - x1 > 0) {
793 Ellipse(hDCMem, x1, y1, x2, y2);
800 LeaveCriticalSection(&m_criticalSection);
802 DeleteObject(hbrush);
805 ReleaseDC(m_hWnd, hDCScreen);
814void vpGDIRenderer::drawText(
const vpImagePoint &ip,
const char *text,
const vpColor &color)
817 HDC hDCScreen = GetDC(m_hWnd);
818 HDC hDCMem = CreateCompatibleDC(hDCScreen);
821 EnterCriticalSection(&m_criticalSection);
822 SelectObject(hDCMem, m_bmp);
825 SelectObject(hDCMem, m_hFont);
829 SetTextColor(hDCMem, m_colors[
color.id]);
832 SetTextColor(hDCMem, gdicolor);
836 SetBkMode(hDCMem, TRANSPARENT);
839 int length =
static_cast<int>(strlen(text));
842 GetTextExtentPoint32(hDCMem, text, length, &size);
850 LeaveCriticalSection(&m_criticalSection);
853 ReleaseDC(m_hWnd, hDCScreen);
863void vpGDIRenderer::drawCross(
const vpImagePoint &ip,
unsigned int size,
const vpColor &color,
unsigned int thickness)
865 int half_size =
static_cast<int>(size / 2 / m_rscale);
872 HDC hDCScreen = GetDC(m_hWnd);
873 HDC hDCMem = CreateCompatibleDC(hDCScreen);
878 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[
color.id]);
881 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
885 EnterCriticalSection(&m_criticalSection);
886 SelectObject(hDCMem, m_bmp);
889 SelectObject(hDCMem, hPen);
904 LeaveCriticalSection(&m_criticalSection);
908 ReleaseDC(m_hWnd, hDCScreen);
925 unsigned int h,
unsigned int thickness)
927 double a = ip2.
get_i() / m_rscale - ip1.
get_i() / m_rscale;
928 double b = ip2.
get_j() / m_rscale - ip1.
get_j() / m_rscale;
938 HDC hDCScreen = GetDC(m_hWnd);
939 HDC hDCMem = CreateCompatibleDC(hDCScreen);
944 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[
color.id]);
947 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
951 EnterCriticalSection(&m_criticalSection);
952 SelectObject(hDCMem, m_bmp);
955 SelectObject(hDCMem, hPen);
957 if ((a == 0) && (b == 0)) {
1003 LeaveCriticalSection(&m_criticalSection);
1007 ReleaseDC(m_hWnd, hDCScreen);
1017 unsigned int size = m_rwidth * m_rheight * 4;
1018 unsigned char *imBuffer =
new unsigned char[size];
1021 GetBitmapBits(m_bmp,
static_cast<LONG
>(size), (
void *)imBuffer);
1024 I.resize(m_rheight, m_rwidth);
1027 for (
unsigned int i = 0;
i < size;
i += 4) {
1028 I.bitmap[
i >> 2].R = imBuffer[
i + 2];
1029 I.bitmap[
i >> 2].G = imBuffer[
i + 1];
1030 I.bitmap[
i >> 2].B = imBuffer[
i + 0];
1039#elif !defined(VISP_BUILD_SHARED_LIBS)
1041void dummy_vpGDIRenderer() { }
Class to define RGB colors available for display functionalities.
static const vpColor white
static const vpColor darkGray
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 black
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)
Definition of the vpImage class member functions.
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
Additional component.
VISP_EXPORT double measureTimeMs()