34 #include <visp3/core/vpConfig.h>
36 #if (defined(VISP_HAVE_GDI))
38 #ifndef DOXYGEN_SHOULD_SKIP_THIS
40 #include <visp3/gui/vpGDIRenderer.h>
47 vpGDIRenderer::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);
104 vpGDIRenderer::~vpGDIRenderer()
107 DeleteCriticalSection(&m_criticalSection);
111 DeleteObject(m_hFont);
120 bool 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);
153 convertROI(I, iP, width, height);
176 convertROI(I, iP, width, height);
182 bool vpGDIRenderer::render()
186 HDC hDCScreen = BeginPaint(m_hWnd, &ps);
189 HDC hDCMem = CreateCompatibleDC(hDCScreen);
192 EnterCriticalSection(&m_criticalSection);
193 SelectObject(hDCMem, m_bmp);
196 BitBlt(hDCScreen, 0, 0,
static_cast<int>(m_rwidth),
static_cast<int>(m_rheight), hDCMem, 0, 0, SRCCOPY);
198 LeaveCriticalSection(&m_criticalSection);
200 DeleteObject(hDCMem);
202 EndPaint(m_hWnd, &ps);
215 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
218 for (
unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, ++k) {
219 imBuffer[i + 0] = I.
bitmap[k].B;
220 imBuffer[i + 1] = I.
bitmap[k].G;
221 imBuffer[i + 2] = I.
bitmap[k].R;
222 imBuffer[i + 3] = I.
bitmap[k].A;
226 for (
unsigned int i = 0; i < m_rheight; ++i) {
227 unsigned int i_ = i * m_rscale;
228 unsigned int ii_ = i * m_rwidth;
229 for (
unsigned int j = 0; j < m_rwidth; ++j) {
230 vpRGBa val = I[i_][j * m_rscale];
231 unsigned int index_ = (ii_ + j) * 4;
232 imBuffer[index_] = val.
B;
233 imBuffer[++index_] = val.
G;
234 imBuffer[++index_] = val.
R;
235 imBuffer[++index_] = val.
A;
241 updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
256 int i_min = std::max<int>((
int)ceil(iP.
get_i() / m_rscale), 0);
257 int j_min = std::max<int>((
int)ceil(iP.
get_j() / m_rscale), 0);
258 int i_max = std::min<int>((
int)ceil((iP.
get_i() + height) / m_rscale), (
int)m_rheight);
259 int j_max = std::min<int>((
int)ceil((iP.
get_j() + width) / m_rscale), (
int)m_rwidth);
261 int h = i_max - i_min;
262 int w = j_max - j_min;
265 unsigned char *imBuffer =
new unsigned char[w * h * 4];
270 bitmap = bitmap + (int)(i_min * iwidth + j_min);
273 for (
int i = 0; i < w * h * 4; i += 4) {
274 imBuffer[i + 0] = (bitmap + k)->B;
275 imBuffer[i + 1] = (bitmap + k)->G;
276 imBuffer[i + 2] = (bitmap + k)->R;
277 imBuffer[i + 3] = (bitmap + k)->A;
281 bitmap = bitmap + iwidth;
287 for (
int i = 0; i < h; ++i) {
288 unsigned int i_ = (i_min + i) * m_rscale;
289 unsigned int ii_ = i * w;
290 for (
int j = 0; j < w; ++j) {
291 vpRGBa val = I[i_][(j_min + j) * m_rscale];
292 unsigned int index_ = (ii_ + j) * 4;
293 imBuffer[index_] = val.
B;
294 imBuffer[++index_] = val.
G;
295 imBuffer[++index_] = val.
R;
296 imBuffer[++index_] = val.
A;
302 updateBitmapROI(imBuffer, i_min, j_min, w, h);
316 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
319 for (
unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, ++k) {
320 imBuffer[i + 0] = I.
bitmap[k];
321 imBuffer[i + 1] = I.
bitmap[k];
322 imBuffer[i + 2] = I.
bitmap[k];
327 for (
unsigned int i = 0; i < m_rheight; ++i) {
328 unsigned int i_ = i * m_rscale;
329 unsigned int ii_ = i * m_rwidth;
330 for (
unsigned int j = 0; j < m_rwidth; ++j) {
331 unsigned char val = I[i_][j * m_rscale];
332 unsigned int index_ = (ii_ + j) * 4;
333 imBuffer[index_] = val;
334 imBuffer[++index_] = val;
335 imBuffer[++index_] = val;
342 updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
357 int i_min = std::max<int>((
int)ceil(iP.
get_i() / m_rscale), 0);
358 int j_min = std::max<int>((
int)ceil(iP.
get_j() / m_rscale), 0);
359 int i_max = std::min<int>((
int)ceil((iP.
get_i() + height) / m_rscale), (
int)m_rheight);
360 int j_max = std::min<int>((
int)ceil((iP.
get_j() + width) / m_rscale), (
int)m_rwidth);
362 int h = i_max - i_min;
363 int w = j_max - j_min;
366 unsigned char *imBuffer =
new unsigned char[w * h * 4];
369 for (
int i = 0; i < h; ++i) {
370 unsigned int i_ = i_min + i;
371 unsigned int ii_ = i * w;
372 for (
int j = 0; j < w; ++j) {
373 unsigned char val = I[i_][j_min + j];
374 unsigned int index_ = (ii_ + j) * 4;
375 imBuffer[index_] = val;
376 imBuffer[++index_] = val;
377 imBuffer[++index_] = val;
383 for (
int i = 0; i < h; ++i) {
384 unsigned int i_ = (i_min + i) * m_rscale;
385 unsigned int ii_ = i * w;
386 for (
int j = 0; j < w; ++j) {
387 unsigned char val = I[i_][(j_min + j) * m_rscale];
388 unsigned int index_ = (ii_ + j) * 4;
389 imBuffer[index_] = val;
390 imBuffer[++index_] = val;
391 imBuffer[++index_] = val;
398 updateBitmapROI(imBuffer, i_min, j_min, w, h);
414 bool vpGDIRenderer::updateBitmap(HBITMAP &hBmp,
unsigned char *imBuffer,
unsigned int w,
unsigned int h)
418 EnterCriticalSection(&m_criticalSection);
421 if ((m_bmp_width == w) && (m_bmp_height == h) && w != 0 && h != 0) {
423 SetBitmapBits(hBmp, w * h * 4, imBuffer);
426 if (hBmp !=
nullptr) {
431 if ((hBmp = CreateBitmap(
static_cast<int>(w),
static_cast<int>(h), 1, 32, (
void *)imBuffer)) ==
nullptr)
438 LeaveCriticalSection(&m_criticalSection);
452 bool vpGDIRenderer::updateBitmapROI(
unsigned char *imBuffer,
int i_min,
int j_min,
int w,
int h)
454 HBITMAP htmp = CreateBitmap(w, h, 1, 32, (
void *)imBuffer);
457 HDC hDCScreen = GetDC(m_hWnd);
458 HDC hDCMem = CreateCompatibleDC(hDCScreen);
459 HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
462 EnterCriticalSection(&m_criticalSection);
463 SelectObject(hDCMem, m_bmp);
464 SelectObject(hDCMem2, htmp);
466 BitBlt(hDCMem, j_min, i_min, w, h, hDCMem2, 0, 0, SRCCOPY);
467 LeaveCriticalSection(&m_criticalSection);
470 ReleaseDC(m_hWnd, hDCScreen);
485 HDC hDCScreen = GetDC(m_hWnd);
486 HDC hDCMem = CreateCompatibleDC(hDCScreen);
489 EnterCriticalSection(&m_criticalSection);
490 SelectObject(hDCMem, m_bmp);
495 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
501 LeaveCriticalSection(&m_criticalSection);
504 ReleaseDC(m_hWnd, hDCScreen);
515 unsigned int thickness,
int style)
517 HDC hDCScreen =
nullptr, hDCMem =
nullptr;
522 hDCScreen = GetDC(m_hWnd);
526 hDCMem = CreateCompatibleDC(hDCScreen);
528 ReleaseDC(m_hWnd, hDCScreen);
534 hPen = CreatePen(style,
static_cast<int>(thickness), m_colors[color.
id]);
536 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
537 hPen = CreatePen(style,
static_cast<int>(thickness), gdicolor);
541 ReleaseDC(m_hWnd, hDCScreen);
544 if (!SetBkMode(hDCMem, TRANSPARENT)) {
547 ReleaseDC(m_hWnd, hDCScreen);
552 EnterCriticalSection(&m_criticalSection);
554 if (!SelectObject(hDCMem, m_bmp)) {
555 LeaveCriticalSection(&m_criticalSection);
558 ReleaseDC(m_hWnd, hDCScreen);
563 if (!SelectObject(hDCMem, hPen)) {
564 LeaveCriticalSection(&m_criticalSection);
567 ReleaseDC(m_hWnd, hDCScreen);
575 hDCScreen = GetDC(m_hWnd);
576 hDCMem = CreateCompatibleDC(hDCScreen);
579 hPen = CreatePen(style,
static_cast<int>(thickness), m_colors[color.
id]);
581 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
582 hPen = CreatePen(style,
static_cast<int>(thickness), gdicolor);
584 SetBkMode(hDCMem, TRANSPARENT);
587 EnterCriticalSection(&m_criticalSection);
588 SelectObject(hDCMem, m_bmp);
591 SelectObject(hDCMem, hPen);
596 if (thickness != 1 && style != PS_SOLID) {
600 double size = 10. * m_rscale;
602 bool vertical_line = (int)ip2_.
get_j() == (int)ip1_.
get_j();
605 std::swap(ip1_, ip2_);
609 std::swap(ip1_, ip2_);
612 double diff_j = vertical_line ? 1 : ip2_.
get_j() - ip1_.
get_j();
613 double deltaj = size / length * diff_j;
614 double deltai = size / length * (ip2_.
get_i() - ip1_.
get_i());
615 double slope = (ip2_.
get_i() - ip1_.
get_i()) / diff_j;
616 double orig = ip1_.
get_i() - slope * ip1_.
get_j();
619 for (
unsigned int i = (
unsigned int)ip1_.
get_i(); i < ip2_.
get_i(); i += (
unsigned int)(2 * deltai)) {
620 double j = ip1_.
get_j();
629 for (
unsigned int j = (
unsigned int)ip1_.
get_j(); j < ip2_.
get_j(); j += (
unsigned int)(2 * deltaj)) {
630 double i = slope * j + orig;
645 LeaveCriticalSection(&m_criticalSection);
649 ReleaseDC(m_hWnd, hDCScreen);
661 void vpGDIRenderer::drawRect(
const vpImagePoint &topLeft,
unsigned int width,
unsigned int height,
const vpColor &color,
662 bool fill,
unsigned int thickness)
667 HDC hDCScreen = GetDC(m_hWnd);
668 HDC hDCMem = CreateCompatibleDC(hDCScreen);
672 COLORREF gdicolor = RGB(0, 0, 0);
675 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
677 gdicolor = RGB(color.
R, color.
G, color.
B);
678 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
684 lBrush.lbStyle = BS_SOLID;
686 lBrush.lbColor = m_colors[color.
id];
688 lBrush.lbColor = gdicolor;
692 lBrush.lbStyle = BS_HOLLOW;
693 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
696 EnterCriticalSection(&m_criticalSection);
697 SelectObject(hDCMem, m_bmp);
700 SelectObject(hDCMem, hbrush);
702 SelectObject(hDCMem, hPen);
711 LeaveCriticalSection(&m_criticalSection);
713 DeleteObject(hbrush);
716 ReleaseDC(m_hWnd, hDCScreen);
723 void vpGDIRenderer::clear(
const vpColor &color)
728 drawRect(ip, m_rwidth, m_rheight, color,
true, 0);
739 void vpGDIRenderer::drawCircle(
const vpImagePoint ¢er,
unsigned int radius,
const vpColor &color,
bool fill,
740 unsigned int thickness)
744 HDC hDCScreen = GetDC(m_hWnd);
745 HDC hDCMem = CreateCompatibleDC(hDCScreen);
750 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
752 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
753 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
758 lBrush.lbStyle = BS_HOLLOW;
759 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
762 int radius_ =
static_cast<int>(radius);
769 EnterCriticalSection(&m_criticalSection);
770 SelectObject(hDCMem, m_bmp);
773 SelectObject(hDCMem, hbrush);
775 SelectObject(hDCMem, hPen);
779 Ellipse(hDCMem, x1, y1, x2, y2);
782 while (x2 - x1 > 0) {
787 Ellipse(hDCMem, x1, y1, x2, y2);
794 LeaveCriticalSection(&m_criticalSection);
796 DeleteObject(hbrush);
799 ReleaseDC(m_hWnd, hDCScreen);
808 void vpGDIRenderer::drawText(
const vpImagePoint &ip,
const char *text,
const vpColor &color)
811 HDC hDCScreen = GetDC(m_hWnd);
812 HDC hDCMem = CreateCompatibleDC(hDCScreen);
815 EnterCriticalSection(&m_criticalSection);
816 SelectObject(hDCMem, m_bmp);
819 SelectObject(hDCMem, m_hFont);
823 SetTextColor(hDCMem, m_colors[color.
id]);
825 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
826 SetTextColor(hDCMem, gdicolor);
830 SetBkMode(hDCMem, TRANSPARENT);
833 int length = (int)strlen(text);
836 GetTextExtentPoint32(hDCMem, text, length, &size);
844 LeaveCriticalSection(&m_criticalSection);
847 ReleaseDC(m_hWnd, hDCScreen);
857 void vpGDIRenderer::drawCross(
const vpImagePoint &ip,
unsigned int size,
const vpColor &color,
unsigned int thickness)
859 int half_size =
static_cast<int>(size / 2 / m_rscale);
866 HDC hDCScreen = GetDC(m_hWnd);
867 HDC hDCMem = CreateCompatibleDC(hDCScreen);
872 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
874 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
875 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
879 EnterCriticalSection(&m_criticalSection);
880 SelectObject(hDCMem, m_bmp);
883 SelectObject(hDCMem, hPen);
898 LeaveCriticalSection(&m_criticalSection);
902 ReleaseDC(m_hWnd, hDCScreen);
917 unsigned int h,
unsigned int thickness)
919 double a = ip2.
get_i() / m_rscale - ip1.
get_i() / m_rscale;
920 double b = ip2.
get_j() / m_rscale - ip1.
get_j() / m_rscale;
930 HDC hDCScreen = GetDC(m_hWnd);
931 HDC hDCMem = CreateCompatibleDC(hDCScreen);
936 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), m_colors[color.
id]);
938 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
939 hPen = CreatePen(PS_SOLID,
static_cast<int>(thickness), gdicolor);
943 EnterCriticalSection(&m_criticalSection);
944 SelectObject(hDCMem, m_bmp);
947 SelectObject(hDCMem, hPen);
949 if ((a == 0) && (b == 0)) {
995 LeaveCriticalSection(&m_criticalSection);
999 ReleaseDC(m_hWnd, hDCScreen);
1009 unsigned int size = m_rwidth * m_rheight * 4;
1010 unsigned char *imBuffer =
new unsigned char[size];
1013 GetBitmapBits(m_bmp,
static_cast<LONG
>(size), (
void *)imBuffer);
1016 I.
resize(m_rheight, m_rwidth);
1019 for (
unsigned int i = 0; i < size; i += 4) {
1020 I.
bitmap[i >> 2].R = imBuffer[i + 2];
1021 I.
bitmap[i >> 2].G = imBuffer[i + 1];
1022 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 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)
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()