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(NULL), m_bmp_width(0), m_bmp_height(0), timelost(0)
53 int bpp = GetDeviceCaps(GetDC(NULL), 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, NULL);
157 convertROI(I, iP, width, height);
180 convertROI(I, iP, width, height);
186 bool vpGDIRenderer::render()
190 HDC hDCScreen = BeginPaint(m_hWnd, &ps);
193 HDC hDCMem = CreateCompatibleDC(hDCScreen);
196 EnterCriticalSection(&m_criticalSection);
197 SelectObject(hDCMem, m_bmp);
200 BitBlt(hDCScreen, 0, 0, static_cast<int>(m_rwidth), static_cast<int>(m_rheight), hDCMem, 0, 0, SRCCOPY);
202 LeaveCriticalSection(&m_criticalSection);
204 DeleteObject(hDCMem);
206 EndPaint(m_hWnd, &ps);
219 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
222 for (
unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, k++) {
223 imBuffer[i + 0] = I.
bitmap[k].B;
224 imBuffer[i + 1] = I.
bitmap[k].G;
225 imBuffer[i + 2] = I.
bitmap[k].R;
226 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)ceil(iP.
get_i() / m_rscale), 0);
260 int j_min = (std::max)((
int)ceil(iP.
get_j() / m_rscale), 0);
261 int i_max = (std::min)((
int)ceil((iP.
get_i() + height) / m_rscale), (int)m_rheight);
262 int j_max = (std::min)((
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;
289 for (
int i = 0; i < h; i++) {
290 unsigned int i_ = (i_min + i) * m_rscale;
291 unsigned int ii_ = i * w;
292 for (
int j = 0; j < w; j++) {
293 vpRGBa val = I[i_][(j_min + j) * m_rscale];
294 unsigned int index_ = (ii_ + j) * 4;
295 imBuffer[index_] = val.
B;
296 imBuffer[++index_] = val.
G;
297 imBuffer[++index_] = val.
R;
298 imBuffer[++index_] = val.
A;
304 updateBitmapROI(imBuffer, i_min, j_min, w, h);
318 unsigned char *imBuffer =
new unsigned char[m_rwidth * m_rheight * 4];
321 for (
unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, k++) {
322 imBuffer[i + 0] = I.
bitmap[k];
323 imBuffer[i + 1] = I.
bitmap[k];
324 imBuffer[i + 2] = I.
bitmap[k];
328 for (
unsigned int i = 0; i < m_rheight; i++) {
329 unsigned int i_ = i * m_rscale;
330 unsigned int ii_ = i * m_rwidth;
331 for (
unsigned int j = 0; j < m_rwidth; j++) {
332 unsigned char val = I[i_][j * m_rscale];
333 unsigned int index_ = (ii_ + j) * 4;
334 imBuffer[index_] = val;
335 imBuffer[++index_] = val;
336 imBuffer[++index_] = val;
343 updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
358 int i_min = (std::max)((
int)ceil(iP.
get_i() / m_rscale), 0);
359 int j_min = (std::max)((
int)ceil(iP.
get_j() / m_rscale), 0);
360 int i_max = (std::min)((
int)ceil((iP.
get_i() + height) / m_rscale), (int)m_rheight);
361 int j_max = (std::min)((
int)ceil((iP.
get_j() + width) / m_rscale), (int)m_rwidth);
363 int h = i_max - i_min;
364 int w = j_max - j_min;
367 unsigned char *imBuffer =
new unsigned char[w * h * 4];
370 for (
int i = 0; i < h; i++) {
371 unsigned int i_ = i_min + i;
372 unsigned int ii_ = i * w;
373 for (
int j = 0; j < w; j++) {
374 unsigned char val = I[i_][j_min + j];
375 unsigned int index_ = (ii_ + j) * 4;
376 imBuffer[index_] = val;
377 imBuffer[++index_] = val;
378 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);
430 if ((hBmp = CreateBitmap(static_cast<int>(w), static_cast<int>(h), 1, 32, (
void *)imBuffer)) == NULL)
437 LeaveCriticalSection(&m_criticalSection);
451 bool vpGDIRenderer::updateBitmapROI(
unsigned char *imBuffer,
int i_min,
int j_min,
int w,
int h)
453 HBITMAP htmp = CreateBitmap(w, h, 1, 32, (
void *)imBuffer);
456 HDC hDCScreen = GetDC(m_hWnd);
457 HDC hDCMem = CreateCompatibleDC(hDCScreen);
458 HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
461 EnterCriticalSection(&m_criticalSection);
462 SelectObject(hDCMem, m_bmp);
463 SelectObject(hDCMem2, htmp);
465 BitBlt(hDCMem, j_min, i_min, w, h, hDCMem2, 0, 0, SRCCOPY);
466 LeaveCriticalSection(&m_criticalSection);
469 ReleaseDC(m_hWnd, hDCScreen);
484 HDC hDCScreen = GetDC(m_hWnd);
485 HDC hDCMem = CreateCompatibleDC(hDCScreen);
488 EnterCriticalSection(&m_criticalSection);
489 SelectObject(hDCMem, m_bmp);
494 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
500 LeaveCriticalSection(&m_criticalSection);
503 ReleaseDC(m_hWnd, hDCScreen);
514 unsigned int thickness,
int style)
516 HDC hDCScreen = NULL, hDCMem = NULL;
521 hDCScreen = GetDC(m_hWnd);
524 hDCMem = CreateCompatibleDC(hDCScreen);
526 ReleaseDC(m_hWnd, hDCScreen);
532 hPen = CreatePen(style, static_cast<int>(thickness), m_colors[color.
id]);
534 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
535 hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
539 ReleaseDC(m_hWnd, hDCScreen);
542 if (!SetBkMode(hDCMem, TRANSPARENT)) {
545 ReleaseDC(m_hWnd, hDCScreen);
550 EnterCriticalSection(&m_criticalSection);
552 if (!SelectObject(hDCMem, m_bmp)) {
553 LeaveCriticalSection(&m_criticalSection);
556 ReleaseDC(m_hWnd, hDCScreen);
561 if (!SelectObject(hDCMem, hPen)) {
562 LeaveCriticalSection(&m_criticalSection);
565 ReleaseDC(m_hWnd, hDCScreen);
573 hDCScreen = GetDC(m_hWnd);
574 hDCMem = CreateCompatibleDC(hDCScreen);
577 hPen = CreatePen(style, static_cast<int>(thickness), m_colors[color.
id]);
579 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
580 hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
582 SetBkMode(hDCMem, TRANSPARENT);
585 EnterCriticalSection(&m_criticalSection);
586 SelectObject(hDCMem, m_bmp);
589 SelectObject(hDCMem, hPen);
594 if (thickness != 1 && style != PS_SOLID) {
598 double size = 10. * m_rscale;
600 bool vertical_line = (int)ip2_.
get_j() == (int)ip1_.
get_j();
603 std::swap(ip1_, ip2_);
606 std::swap(ip1_, ip2_);
609 double diff_j = vertical_line ? 1 : ip2_.
get_j() - ip1_.
get_j();
610 double deltaj = size / length * diff_j;
611 double deltai = size / length * (ip2_.
get_i() - ip1_.
get_i());
612 double slope = (ip2_.
get_i() - ip1_.
get_i()) / diff_j;
613 double orig = ip1_.
get_i() - slope * ip1_.
get_j();
616 for (
unsigned int i = (
unsigned int)ip1_.
get_i(); i < ip2_.
get_i(); i += (
unsigned int)(2 * deltai)) {
617 double j = ip1_.
get_j();
625 for (
unsigned int j = (
unsigned int)ip1_.
get_j(); j < ip2_.
get_j(); j += (
unsigned int)(2 * deltaj)) {
626 double i = slope * j + orig;
640 LeaveCriticalSection(&m_criticalSection);
644 ReleaseDC(m_hWnd, hDCScreen);
656 void vpGDIRenderer::drawRect(
const vpImagePoint &topLeft,
unsigned int width,
unsigned int height,
const vpColor &color,
657 bool fill,
unsigned int thickness)
662 HDC hDCScreen = GetDC(m_hWnd);
663 HDC hDCMem = CreateCompatibleDC(hDCScreen);
667 COLORREF gdicolor = RGB(0, 0, 0);
670 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.
id]);
672 gdicolor = RGB(color.
R, color.
G, color.
B);
673 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
679 lBrush.lbStyle = BS_SOLID;
681 lBrush.lbColor = m_colors[color.
id];
683 lBrush.lbColor = gdicolor;
686 lBrush.lbStyle = BS_HOLLOW;
687 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
690 EnterCriticalSection(&m_criticalSection);
691 SelectObject(hDCMem, m_bmp);
694 SelectObject(hDCMem, hbrush);
696 SelectObject(hDCMem, hPen);
705 LeaveCriticalSection(&m_criticalSection);
707 DeleteObject(hbrush);
710 ReleaseDC(m_hWnd, hDCScreen);
717 void vpGDIRenderer::clear(
const vpColor &color)
722 drawRect(ip, m_rwidth, m_rheight, color,
true, 0);
733 void vpGDIRenderer::drawCircle(
const vpImagePoint ¢er,
unsigned int radius,
const vpColor &color,
bool fill,
734 unsigned int thickness)
738 HDC hDCScreen = GetDC(m_hWnd);
739 HDC hDCMem = CreateCompatibleDC(hDCScreen);
744 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.
id]);
746 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
747 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
752 lBrush.lbStyle = BS_HOLLOW;
753 HBRUSH hbrush = CreateBrushIndirect(&lBrush);
756 int radius_ = static_cast<int>(radius);
763 EnterCriticalSection(&m_criticalSection);
764 SelectObject(hDCMem, m_bmp);
767 SelectObject(hDCMem, hbrush);
769 SelectObject(hDCMem, hPen);
773 Ellipse(hDCMem, x1, y1, x2, y2);
776 while (x2 - x1 > 0) {
781 Ellipse(hDCMem, x1, y1, x2, y2);
788 LeaveCriticalSection(&m_criticalSection);
790 DeleteObject(hbrush);
793 ReleaseDC(m_hWnd, hDCScreen);
802 void vpGDIRenderer::drawText(
const vpImagePoint &ip,
const char *text,
const vpColor &color)
805 HDC hDCScreen = GetDC(m_hWnd);
806 HDC hDCMem = CreateCompatibleDC(hDCScreen);
809 EnterCriticalSection(&m_criticalSection);
810 SelectObject(hDCMem, m_bmp);
813 SelectObject(hDCMem, m_hFont);
817 SetTextColor(hDCMem, m_colors[color.
id]);
819 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
820 SetTextColor(hDCMem, gdicolor);
824 SetBkMode(hDCMem, TRANSPARENT);
827 int length = (int)strlen(text);
830 GetTextExtentPoint32(hDCMem, text, length, &size);
838 LeaveCriticalSection(&m_criticalSection);
841 ReleaseDC(m_hWnd, hDCScreen);
851 void vpGDIRenderer::drawCross(
const vpImagePoint &ip,
unsigned int size,
const vpColor &color,
unsigned int thickness)
853 int half_size = static_cast<int>(size / 2 / m_rscale);
860 HDC hDCScreen = GetDC(m_hWnd);
861 HDC hDCMem = CreateCompatibleDC(hDCScreen);
866 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.
id]);
868 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
869 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
873 EnterCriticalSection(&m_criticalSection);
874 SelectObject(hDCMem, m_bmp);
877 SelectObject(hDCMem, hPen);
893 LeaveCriticalSection(&m_criticalSection);
897 ReleaseDC(m_hWnd, hDCScreen);
911 unsigned int h,
unsigned int thickness)
913 double a = ip2.
get_i() / m_rscale - ip1.
get_i() / m_rscale;
914 double b = ip2.
get_j() / m_rscale - ip1.
get_j() / m_rscale;
924 HDC hDCScreen = GetDC(m_hWnd);
925 HDC hDCMem = CreateCompatibleDC(hDCScreen);
930 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.
id]);
932 COLORREF gdicolor = RGB(color.
R, color.
G, color.
B);
933 hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
937 EnterCriticalSection(&m_criticalSection);
938 SelectObject(hDCMem, m_bmp);
941 SelectObject(hDCMem, hPen);
943 if ((a == 0) && (b == 0)) {
988 LeaveCriticalSection(&m_criticalSection);
992 ReleaseDC(m_hWnd, hDCScreen);
1002 unsigned int size = m_rwidth * m_rheight * 4;
1003 unsigned char *imBuffer =
new unsigned char[size];
1006 GetBitmapBits(m_bmp, static_cast<LONG>(size), (
void *)imBuffer);
1009 I.
resize(m_rheight, m_rwidth);
1012 for (
unsigned int i = 0; i < size; i += 4) {
1013 I.
bitmap[i >> 2].R = imBuffer[i + 2];
1014 I.
bitmap[i >> 2].G = imBuffer[i + 1];
1015 I.
bitmap[i >> 2].B = imBuffer[i + 0];
1022 #elif !defined(VISP_BUILD_SHARED_LIBS)
1025 void dummy_vpGDIRenderer(){};