Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpGDIRenderer.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * GDI renderer for windows 32 display
32  *
33  * Authors:
34  * Bruno Renier
35  *
36  *****************************************************************************/
37 
38 #include <visp3/core/vpConfig.h>
39 #define GDI_ROBUST
40 #if ( defined(VISP_HAVE_GDI) )
41 
42 #ifndef DOXYGEN_SHOULD_SKIP_THIS
43 
44 #include <visp3/gui/vpGDIRenderer.h>
45 
49 vpGDIRenderer::vpGDIRenderer()
50  : m_bmp(NULL), m_bmp_width(0), m_bmp_height(0)
51 {
52  //if the screen depth is not 32bpp, throw an exception
53  int bpp = GetDeviceCaps(GetDC(NULL), BITSPIXEL);
54  if( bpp != 32 )
56  "vpGDIRenderer supports only 32bits depth: screen is %dbits depth!", bpp);
57 
58  InitializeCriticalSection(&m_criticalSection);
59 
60  //initialize GDI the palette
61  vpColor pcolor; // Predefined colors
62 
63  pcolor = vpColor::black;
64  m_colors[vpColor::id_black] = RGB(pcolor.R, pcolor.G, pcolor.B);
65  pcolor = vpColor::lightBlue;
66  m_colors[vpColor::id_lightBlue] = RGB(pcolor.R, pcolor.G, pcolor.B);
67  pcolor = vpColor::blue;
68  m_colors[vpColor::id_blue] = RGB(pcolor.R, pcolor.G, pcolor.B);
69  pcolor = vpColor::darkBlue;
70  m_colors[vpColor::id_darkBlue] = RGB(pcolor.R, pcolor.G, pcolor.B);
71  pcolor = vpColor::cyan;
72  m_colors[vpColor::id_cyan] = RGB(pcolor.R, pcolor.G, pcolor.B);
73  pcolor = vpColor::lightGreen;
74  m_colors[vpColor::id_lightGreen] = RGB(pcolor.R, pcolor.G, pcolor.B);
75  pcolor = vpColor::green;
76  m_colors[vpColor::id_green] = RGB(pcolor.R, pcolor.G, pcolor.B);
77  pcolor = vpColor::darkGreen;
78  m_colors[vpColor::id_darkGreen] = RGB(pcolor.R, pcolor.G, pcolor.B);
79  pcolor = vpColor::lightRed;
80  m_colors[vpColor::id_lightRed] = RGB(pcolor.R, pcolor.G, pcolor.B);
81  pcolor = vpColor::red;
82  m_colors[vpColor::id_red] = RGB(pcolor.R, pcolor.G, pcolor.B);
83  pcolor = vpColor::darkRed;
84  m_colors[vpColor::id_darkRed] = RGB(pcolor.R, pcolor.G, pcolor.B);
85  pcolor = vpColor::white;
86  m_colors[vpColor::id_white] = RGB(pcolor.R, pcolor.G, pcolor.B);
87  pcolor = vpColor::lightGray;
88  m_colors[vpColor::id_lightGray] = RGB(pcolor.R, pcolor.G, pcolor.B);
89  pcolor = vpColor::gray;
90  m_colors[vpColor::id_gray] = RGB(pcolor.R, pcolor.G, pcolor.B);
91  pcolor = vpColor::darkGray;
92  m_colors[vpColor::id_darkGray] = RGB(pcolor.R, pcolor.G, pcolor.B);
93  pcolor = vpColor::yellow;
94  m_colors[vpColor::id_yellow]= RGB(pcolor.R, pcolor.G, pcolor.B);
95  pcolor = vpColor::orange;
96  m_colors[vpColor::id_orange]= RGB(pcolor.R, pcolor.G, pcolor.B);
97  pcolor = vpColor::purple;
98  m_colors[vpColor::id_purple]= RGB(pcolor.R, pcolor.G, pcolor.B);
99 
100  m_rwidth = 0;
101  m_rheight = 0;
102 }
103 
107 vpGDIRenderer::~vpGDIRenderer()
108 {
109  //Deletes the critical section object
110  DeleteCriticalSection(&m_criticalSection);
111  //Deletes the bitmap
112  DeleteObject(m_bmp);
113  //Deletes the font object
114  DeleteObject(m_hFont);
115 }
116 
123 bool vpGDIRenderer::init(HWND hWindow, unsigned int width, unsigned int height)
124 {
125  timelost = 0.;
126  m_hWnd = hWindow;
127 
128  m_rwidth = width;
129  m_rheight = height;
130 
131  //creates the font
132  m_hFont = CreateFont(18, 0, 0, 0, FW_NORMAL, false, false, false,
133  DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
134  CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
135  DEFAULT_PITCH | FF_DONTCARE, NULL);
136  return true;
137 }
138 
143 void vpGDIRenderer::setImg(const vpImage<vpRGBa>& I)
144 {
145  //converts the image into a HBITMAP
146  convert(I, m_bmp);
147 }
148 
155 void vpGDIRenderer::setImgROI(const vpImage<vpRGBa>& I, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
156 {
157  //converts the image into a HBITMAP
158  convertROI(I, iP, width, height);
159 }
160 
165 void vpGDIRenderer::setImg(const vpImage<unsigned char>& I)
166 {
167  //converts the image into a HBITMAP
168  convert(I, m_bmp);
169 }
170 
177 void vpGDIRenderer::setImgROI(const vpImage<unsigned char>& I, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
178 {
179  //converts the image into a HBITMAP
180  convertROI(I, iP, width, height);
181 }
182 
186 bool vpGDIRenderer::render()
187 {
188  //gets the window's DC
189  PAINTSTRUCT ps;
190  HDC hDCScreen = BeginPaint(m_hWnd, &ps);
191 
192  //create a memory DC
193  HDC hDCMem = CreateCompatibleDC(hDCScreen);
194 
195  //selects this bmp in memory
196  EnterCriticalSection(&m_criticalSection);
197  SelectObject(hDCMem, m_bmp);
198 
199  //blits it on the window's DC
200  BitBlt(hDCScreen, 0, 0,
201  static_cast<int>( m_rwidth ),
202  static_cast<int>( m_rheight ),
203  hDCMem, 0, 0, SRCCOPY);
204 
205  LeaveCriticalSection(&m_criticalSection);
206  //DeleteDC(hDCMem);
207  DeleteObject(hDCMem);
208 
209  EndPaint(m_hWnd, &ps);
210 
211  return true;
212 }
213 
219 void vpGDIRenderer::convert(const vpImage<vpRGBa> &I, HBITMAP& hBmp)
220 {
221  //allocate the buffer
222  unsigned char * imBuffer = new unsigned char[m_rwidth * m_rheight * 4];
223 
224  if (m_rscale == 1) {
225  for(unsigned int i=0, k=0 ; i<m_rwidth * m_rheight * 4 ; i+=4, k++) {
226  imBuffer[i+0] = I.bitmap[k].B;
227  imBuffer[i+1] = I.bitmap[k].G;
228  imBuffer[i+2] = I.bitmap[k].R;
229  imBuffer[i+3] = I.bitmap[k].A;
230  }
231  }
232  else {
233  for (unsigned int i = 0; i < m_rheight; i++) {
234  unsigned int i_ = i*m_rscale;
235  unsigned int ii_ = i*m_rwidth;
236  for (unsigned int j = 0; j < m_rwidth; j++) {
237  vpRGBa val = I[i_][j*m_rscale];
238  unsigned int index_ = (ii_ + j) * 4;
239  imBuffer[ index_] = val.B;
240  imBuffer[++index_] = val.G;
241  imBuffer[++index_] = val.R;
242  imBuffer[++index_] = val.A;
243  }
244  }
245  }
246 
247  //updates the bitmap's pixel data
248  updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
249 
250  //we don't need this buffer anymore
251  delete [] imBuffer;
252 }
253 
260 void vpGDIRenderer::convertROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, const unsigned int width, const unsigned int height)
261 {
262  int i_min = std::max((int)ceil(iP.get_i() / m_rscale), 0);
263  int j_min = std::max((int)ceil(iP.get_j() / m_rscale), 0);
264  int i_max = std::min((int)ceil((iP.get_i() + height) / m_rscale), (int)m_rheight);
265  int j_max = std::min((int)ceil((iP.get_j() + width) / m_rscale), (int)m_rwidth);
266 
267  int h = i_max - i_min;
268  int w = j_max - j_min;
269 
270  //allocate the buffer
271  unsigned char * imBuffer = new unsigned char[w * h * 4];
272 
273  if (m_rscale == 1) {
274  vpRGBa* bitmap = I.bitmap;
275  unsigned int iwidth = I.getWidth();
276  bitmap = bitmap + (int)(i_min*iwidth + j_min);
277 
278  int k = 0;
279  for (int i=0 ; i < w * h * 4 ; i+=4)
280  {
281  imBuffer[i+0] = (bitmap+k)->B;
282  imBuffer[i+1] = (bitmap+k)->G;
283  imBuffer[i+2] = (bitmap+k)->R;
284  imBuffer[i+3] = (bitmap+k)->A;
285  //bitmap++;
286  k++;
287  if (k == w)
288  {
289  bitmap = bitmap+iwidth;
290  k = 0;
291  }
292  }
293  }
294  else {
295  for (int i = 0; i < h; i++) {
296  unsigned int i_ = (i_min + i)*m_rscale;
297  unsigned int ii_ = i*w;
298  for (int j = 0; j < w; j++) {
299  vpRGBa val = I[i_][(j_min + j)*m_rscale];
300  unsigned int index_ = (ii_ + j) * 4;
301  imBuffer[index_] = val.B;
302  imBuffer[++index_] = val.G;
303  imBuffer[++index_] = val.R;
304  imBuffer[++index_] = val.A;
305  }
306  }
307  }
308 
309  //updates the bitmap's pixel data
310  updateBitmapROI(imBuffer, i_min, j_min, w, h);
311 
312  //we don't need this buffer anymore
313  delete [] imBuffer;
314 }
315 
316 
322 void vpGDIRenderer::convert(const vpImage<unsigned char> &I, HBITMAP& hBmp)
323 {
324  //allocate the buffer
325  unsigned char * imBuffer = new unsigned char[m_rwidth * m_rheight * 4];
326 
327  if (m_rscale == 1) {
328  for (unsigned int i = 0, k = 0; i < m_rwidth * m_rheight * 4; i += 4, k++)
329  {
330  imBuffer[i + 0] = I.bitmap[k];
331  imBuffer[i + 1] = I.bitmap[k];
332  imBuffer[i + 2] = I.bitmap[k];
333  imBuffer[i + 3] = vpRGBa::alpha_default;
334  }
335  }
336  else {
337  for (unsigned int i = 0; i < m_rheight; i++) {
338  unsigned int i_ = i*m_rscale;
339  unsigned int ii_ = i*m_rwidth;
340  for (unsigned int j = 0; j < m_rwidth; j++) {
341  unsigned char val = I[i_][j*m_rscale];
342  unsigned int index_ = (ii_ + j) * 4;
343  imBuffer[index_] = val;
344  imBuffer[++index_] = val;
345  imBuffer[++index_] = val;
346  imBuffer[++index_] = vpRGBa::alpha_default;
347  }
348  }
349  }
350 
351  //updates the bitmap's pixel data
352  updateBitmap(hBmp, imBuffer, m_rwidth, m_rheight);
353 
354  //we don't need this buffer anymore
355  delete [] imBuffer;
356 }
357 
358 
365 void vpGDIRenderer::convertROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, const unsigned int width, const unsigned int height)
366 {
367  int i_min = std::max((int)ceil(iP.get_i() / m_rscale), 0);
368  int j_min = std::max((int)ceil(iP.get_j() / m_rscale), 0);
369  int i_max = std::min((int)ceil((iP.get_i() + height) / m_rscale), (int)m_rheight);
370  int j_max = std::min((int)ceil((iP.get_j() + width) / m_rscale), (int)m_rwidth);
371 
372  int h = i_max - i_min;
373  int w = j_max - j_min;
374 
375  //allocate the buffer
376  unsigned char * imBuffer = new unsigned char[w * h * 4];
377 
378  if (m_rscale == 1) {
379  for (int i = 0; i < h; i++) {
380  unsigned int i_ = i_min + i;
381  unsigned int ii_ = i*w;
382  for (int j = 0; j < w; j++) {
383  unsigned char val = I[i_][j_min + j];
384  unsigned int index_ = (ii_ + j) * 4;
385  imBuffer[index_] = val;
386  imBuffer[++index_] = val;
387  imBuffer[++index_] = val;
388  imBuffer[++index_] = vpRGBa::alpha_default;
389  }
390  }
391  }
392  else {
393  for (int i = 0; i < h; i++) {
394  unsigned int i_ = (i_min + i)*m_rscale;
395  unsigned int ii_ = i*w;
396  for (int j = 0; j < w; j++) {
397  unsigned char val = I[i_][(j_min + j)*m_rscale];
398  unsigned int index_ = (ii_ + j) * 4;
399  imBuffer[index_] = val;
400  imBuffer[++index_] = val;
401  imBuffer[++index_] = val;
402  imBuffer[++index_] = vpRGBa::alpha_default;
403  }
404  }
405  }
406 
407  //updates the bitmap's pixel data
408  updateBitmapROI(imBuffer, i_min, j_min, w, h);
409 
410  //we don't need this buffer anymore
411  delete [] imBuffer;
412 }
413 
424 bool vpGDIRenderer::updateBitmap(HBITMAP& hBmp, unsigned char * imBuffer,
425  unsigned int w, unsigned int h)
426 {
427  //the bitmap may only be accessed by one thread at the same time
428  //that's why we enter critical section
429  EnterCriticalSection(&m_criticalSection);
430 
431  //if the existing bitmap object is of the right size
432  if( (m_bmp_width == w) && (m_bmp_height == h) && w != 0 && h != 0)
433  {
434  //just replace the content
435  SetBitmapBits(hBmp, w * h * 4, imBuffer);
436  }
437  else
438  {
439  if(hBmp != NULL)
440  {
441  //delete the old BITMAP
442  DeleteObject(hBmp);
443  }
444  //create a new BITMAP from this buffer
445  if( (hBmp = CreateBitmap(static_cast<int>(w),static_cast<int>(h),
446  1,32,(void*)imBuffer)) == NULL)
447  return false;
448 
449  m_bmp_width = w;
450  m_bmp_height = h;
451  }
452 
453  LeaveCriticalSection(&m_criticalSection);
454  return true;
455 }
456 
457 
468 bool vpGDIRenderer::updateBitmapROI(unsigned char * imBuffer, int i_min, int j_min, int w, int h)
469 {
470  HBITMAP htmp = CreateBitmap(w, h, 1, 32, (void*)imBuffer);
471 
472  //get the window's DC
473  HDC hDCScreen = GetDC(m_hWnd);
474  HDC hDCMem = CreateCompatibleDC(hDCScreen);
475  HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
476 
477  //select this bmp in memory
478  EnterCriticalSection(&m_criticalSection);
479  SelectObject(hDCMem, m_bmp);
480  SelectObject(hDCMem2, htmp);
481 
482  BitBlt(hDCMem, j_min, i_min, w, h, hDCMem2, 0, 0,SRCCOPY);
483  LeaveCriticalSection(&m_criticalSection);
484 
485  DeleteDC(hDCMem);
486  ReleaseDC(m_hWnd, hDCScreen);
487  DeleteObject(htmp);
488 
489  return true;
490 }
491 
498 void vpGDIRenderer::setPixel(const vpImagePoint &iP,
499  const vpColor &color)
500 {
501  //get the window's DC
502  HDC hDCScreen = GetDC(m_hWnd);
503  HDC hDCMem = CreateCompatibleDC(hDCScreen);
504 
505  //select this bmp in memory
506  EnterCriticalSection(&m_criticalSection);
507  SelectObject(hDCMem, m_bmp);
508 
509  if (color.id < vpColor::id_unknown)
510  SetPixel(hDCMem, vpMath::round(iP.get_u() / m_rscale), vpMath::round(iP.get_v() / m_rscale),
511  m_colors[color.id]);
512  else {
513  COLORREF gdicolor = RGB(color.R, color.G, color.B);
514  SetPixel(hDCMem, vpMath::round(iP.get_u() / m_rscale), vpMath::round(iP.get_v() / m_rscale),
515  gdicolor);
516  }
517  //display the result (flush)
518  // BitBlt(hDCScreen, x, y, 1, 1, hDCMem, x, y, SRCCOPY);
519 
520  LeaveCriticalSection(&m_criticalSection);
521 
522  DeleteDC(hDCMem);
523  ReleaseDC(m_hWnd, hDCScreen);
524 }
525 
533 void vpGDIRenderer::drawLine(const vpImagePoint &ip1,
534  const vpImagePoint &ip2,
535  const vpColor &color,
536  unsigned int thickness, int style)
537 {
538  HDC hDCScreen= NULL, hDCMem = NULL;
539  HPEN hPen = NULL;
540 #ifdef GDI_ROBUST
541  double start = vpTime::measureTimeMs();
542  while(vpTime::measureTimeMs()-start<1000){
543  hDCScreen = GetDC(m_hWnd);
544  if(!hDCScreen) continue;
545  hDCMem = CreateCompatibleDC(hDCScreen);
546  if(!hDCMem){
547  ReleaseDC(m_hWnd, hDCScreen);
548  continue;
549  }
550 
551  //create the pen
552  if (color.id < vpColor::id_unknown)
553  hPen = CreatePen(style, static_cast<int>(thickness), m_colors[color.id]);
554  else {
555  COLORREF gdicolor = RGB(color.R, color.G, color.B);
556  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
557  }
558  if(!hPen){
559  DeleteDC(hDCMem);
560  ReleaseDC(m_hWnd, hDCScreen);
561  continue;
562  }
563  if(!SetBkMode(hDCMem, TRANSPARENT)){
564  DeleteObject(hPen);
565  DeleteDC(hDCMem);
566  ReleaseDC(m_hWnd, hDCScreen);
567  continue;
568  }
569 
570  //select this bmp in memory
571  EnterCriticalSection(&m_criticalSection);
572 
573  if(!SelectObject(hDCMem, m_bmp)){
574  LeaveCriticalSection(&m_criticalSection);
575  DeleteObject(hPen);
576  DeleteDC(hDCMem);
577  ReleaseDC(m_hWnd, hDCScreen);
578  continue;
579  }
580 
581  //select the pen
582  if(!SelectObject(hDCMem, hPen)){
583  LeaveCriticalSection(&m_criticalSection);
584  DeleteObject(hPen);
585  DeleteDC(hDCMem);
586  ReleaseDC(m_hWnd, hDCScreen);
587  continue;
588  }
589  break;
590  }
591  timelost+=(vpTime::measureTimeMs()-start);
592 #else
593  //get the window's DC
594  hDCScreen = GetDC(m_hWnd);
595  hDCMem = CreateCompatibleDC(hDCScreen);
596  //create the pen
597  if (color.id < vpColor::id_unknown)
598  hPen = CreatePen(style, static_cast<int>(thickness), m_colors[color.id]);
599  else {
600  COLORREF gdicolor = RGB(color.R, color.G, color.B);
601  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
602  }
603  SetBkMode(hDCMem, TRANSPARENT);
604 
605  //select this bmp in memory
606  EnterCriticalSection(&m_criticalSection);
607  SelectObject(hDCMem, m_bmp);
608 
609  //select the pen
610  SelectObject(hDCMem, hPen);
611 #endif
612  // Warning: When thickness > 1 and pen style is PS_DASHDOT, the drawing displays a solid line
613  // That's why in that case we implement the dashdot line manually drawing multiple small lines
614  if (thickness != 1 && style != PS_SOLID) {
615  double size = 10.*m_rscale;
616  double length = sqrt(vpMath::sqr(ip2.get_i() - ip1.get_i()) + vpMath::sqr(ip2.get_j() - ip1.get_j()));
617  double deltaj = size / length*(ip2.get_j() - ip1.get_j());
618  double deltai = size / length*(ip2.get_i() - ip1.get_i());
619  double slope = (ip2.get_i() - ip1.get_i()) / (ip2.get_j() - ip1.get_j());
620  double orig = ip1.get_i() - slope*ip1.get_j();
621  for (unsigned int j = (unsigned int)ip1.get_j(); j < ip2.get_j(); j += (unsigned int)(2 * deltaj)) {
622  double i = slope*j + orig;
623  //move to the starting point
624  MoveToEx(hDCMem, vpMath::round(j / m_rscale), vpMath::round(i / m_rscale), NULL);
625  //Draw the line
626  LineTo(hDCMem, vpMath::round((j + deltaj) / m_rscale), vpMath::round((i + deltai) / m_rscale));
627  }
628  }
629  else {
630  //move to the starting point
631  MoveToEx(hDCMem, vpMath::round(ip1.get_u() / m_rscale), vpMath::round(ip1.get_v() / m_rscale), NULL);
632  //Draw the line
633  LineTo(hDCMem, vpMath::round(ip2.get_u() / m_rscale), vpMath::round(ip2.get_v() / m_rscale));
634  }
635 
636  LeaveCriticalSection(&m_criticalSection);
637 
638  DeleteObject(hPen);
639  DeleteDC(hDCMem);
640  ReleaseDC(m_hWnd, hDCScreen);
641 }
642 
652 void vpGDIRenderer::drawRect(const vpImagePoint &topLeft,
653  unsigned int width, unsigned int height,
654  const vpColor &color, bool fill,
655  unsigned int thickness)
656 {
657  if (thickness == 0) thickness = 1;
658  //get the window's DC
659  HDC hDCScreen = GetDC(m_hWnd);
660  HDC hDCMem = CreateCompatibleDC(hDCScreen);
661 
662  //create the pen
663  HPEN hPen;
664  COLORREF gdicolor = RGB(0,0,0);
665 
666  if (color.id < vpColor::id_unknown)
667  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.id]);
668  else {
669  gdicolor = RGB(color.R, color.G, color.B);
670  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
671  }
672 
673  //create an hollow or solid brush (depends on boolean fill)
674  LOGBRUSH lBrush;
675  if(fill) {
676  lBrush.lbStyle = BS_SOLID;
677  if (color.id < vpColor::id_unknown)
678  lBrush.lbColor = m_colors[color.id];
679  else {
680  lBrush.lbColor = gdicolor;
681  }
682  }
683  else lBrush.lbStyle = BS_HOLLOW;
684  HBRUSH hbrush = CreateBrushIndirect(&lBrush);
685 
686  //select this bmp in memory
687  EnterCriticalSection(&m_criticalSection);
688  SelectObject(hDCMem, m_bmp);
689 
690  //select the brush
691  SelectObject(hDCMem, hbrush);
692  //select the pen
693  SelectObject(hDCMem, hPen);
694 
695  //draw the rectangle
696  Rectangle(hDCMem, vpMath::round(topLeft.get_u() / m_rscale), vpMath::round(topLeft.get_v() / m_rscale),
697  vpMath::round((topLeft.get_u() + width) / m_rscale),
698  vpMath::round((topLeft.get_v() + height) / m_rscale));
699 
700  //display the result (flush)
701  // BitBlt(hDCScreen, j, i, width, height, hDCMem, j, i, SRCCOPY);
702 
703  LeaveCriticalSection(&m_criticalSection);
704 
705  DeleteObject(hbrush);
706  DeleteObject(hPen);
707  DeleteDC(hDCMem);
708  ReleaseDC(m_hWnd, hDCScreen);
709 }
710 
715 void vpGDIRenderer::clear(const vpColor &color)
716 {
717  vpImagePoint ip;
718  ip.set_i(0);
719  ip.set_j(0);
720  drawRect(ip, m_rwidth, m_rheight, color, true, 0);
721 }
722 
723 
732 void vpGDIRenderer::drawCircle(const vpImagePoint &center, unsigned int radius,
733  const vpColor &color, bool fill, unsigned int thickness)
734 {
735 
736  //get the window's DC
737  HDC hDCScreen = GetDC(m_hWnd);
738  HDC hDCMem = CreateCompatibleDC(hDCScreen);
739 
740  //create the pen
741  HPEN hPen;
742  if (color.id < vpColor::id_unknown)
743  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.id]);
744  else {
745  COLORREF gdicolor = RGB(color.R, color.G, color.B);
746  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
747  }
748 
749  //create an hollow brush
750  LOGBRUSH lBrush;
751  lBrush.lbStyle = BS_HOLLOW;
752  HBRUSH hbrush = CreateBrushIndirect(&lBrush);
753 
754  //computes bounding rectangle
755  int radius_ = static_cast<int>(radius);
756  int x1 = vpMath::round(center.get_u() / m_rscale)-radius_ / m_rscale;
757  int y1 = vpMath::round(center.get_v() / m_rscale)-radius_ / m_rscale;
758  int x2 = vpMath::round(center.get_u() / m_rscale)+radius_ / m_rscale;
759  int y2 = vpMath::round(center.get_v() / m_rscale)+radius_ / m_rscale;
760 
761  //select this bmp in memory
762  EnterCriticalSection(&m_criticalSection);
763  SelectObject(hDCMem, m_bmp);
764 
765  //select the brush
766  SelectObject(hDCMem, hbrush);
767  //select the pen
768  SelectObject(hDCMem, hPen);
769 
770  //draw the circle
771  if (fill==false)
772  Ellipse(hDCMem, x1, y1, x2, y2);
773 
774  else
775  {
776  while (x2-x1 > 0)
777  {
778  x1++;
779  x2--;
780  y1++;
781  y2--;
782  Ellipse(hDCMem, x1, y1, x2, y2);
783  }
784  }
785 
786  //display the result (flush)
787  // BitBlt(hDCScreen, x1, y1, x2-x1, y2-y1, hDCMem, x1, y1, SRCCOPY);
788 
789  LeaveCriticalSection(&m_criticalSection);
790 
791  DeleteObject(hbrush);
792  DeleteObject(hPen);
793  DeleteDC(hDCMem);
794  ReleaseDC(m_hWnd, hDCScreen);
795 }
796 
797 
804 void vpGDIRenderer::drawText(const vpImagePoint &ip, const char * text,
805  const vpColor &color)
806 {
807  //get the window's DC
808  HDC hDCScreen = GetDC(m_hWnd);
809  HDC hDCMem = CreateCompatibleDC(hDCScreen);
810 
811  //select this bmp in memory
812  EnterCriticalSection(&m_criticalSection);
813  SelectObject(hDCMem, m_bmp);
814 
815  //Select the font
816  SelectObject(hDCMem, m_hFont);
817 
818  //set the text color
819  if (color.id < vpColor::id_unknown)
820  SetTextColor(hDCMem, m_colors[color.id]);
821  else {
822  COLORREF gdicolor = RGB(color.R, color.G, color.B);
823  SetTextColor(hDCMem, gdicolor);
824  }
825 
826  //we don't use the bkColor
827  SetBkMode(hDCMem, TRANSPARENT);
828 
829  SIZE size;
830  int length = (int) strlen(text);
831 
832  //get the displayed string dimensions
833  GetTextExtentPoint32(hDCMem, text, length, &size);
834 
835  //displays the string
836  TextOut(hDCMem, vpMath::round(ip.get_u() / m_rscale), vpMath::round(ip.get_v() / m_rscale), text, length);
837 
838  //display the result (flush)
839  // BitBlt(hDCScreen, j, i, size.cx, size.cy, hDCMem, j, i, SRCCOPY);
840 
841  LeaveCriticalSection(&m_criticalSection);
842 
843  DeleteDC(hDCMem);
844  ReleaseDC(m_hWnd, hDCScreen);
845 }
846 
847 
848 
856 void vpGDIRenderer::drawCross(const vpImagePoint &ip, unsigned int size,
857  const vpColor &color, unsigned int thickness)
858 {
859  /* unsigned */ int half_size = static_cast<int>( size/2 / m_rscale);
860 
861  // if half_size is equal to zero, nothing is displayed with the code
862  // just below. So, if half_size is equal to zero we just draw the
863  // pixel.
864  if (half_size) {
865  //get the window's DC
866  HDC hDCScreen = GetDC(m_hWnd);
867  HDC hDCMem = CreateCompatibleDC(hDCScreen);
868 
869  //create the pen
870  HPEN hPen;
871  if (color.id < vpColor::id_unknown)
872  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.id]);
873  else {
874  COLORREF gdicolor = RGB(color.R, color.G, color.B);
875  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
876  }
877 
878  //select this bmp in memory
879  EnterCriticalSection(&m_criticalSection);
880  SelectObject(hDCMem, m_bmp);
881 
882  //select the pen
883  SelectObject(hDCMem, hPen);
884 
885  //move to the starting point
886  MoveToEx(hDCMem, vpMath::round(ip.get_u() / m_rscale)-half_size, vpMath::round(ip.get_v() / m_rscale), NULL);
887  //Draw the first line (horizontal)
888  LineTo(hDCMem, vpMath::round(ip.get_u() / m_rscale)+half_size, vpMath::round(ip.get_v() / m_rscale));
889 
890  //move to the starting point
891  MoveToEx(hDCMem, vpMath::round(ip.get_u() / m_rscale), vpMath::round(ip.get_v() / m_rscale)-half_size, NULL);
892  //Draw the second line (vertical)
893  LineTo(hDCMem, vpMath::round(ip.get_u() / m_rscale), vpMath::round(ip.get_v() / m_rscale)+half_size);
894 
895  //display the result (flush)
896  // BitBlt(hDCScreen, j-(size/2), i-(size/2), size, size,
897  // hDCMem, j-(size/2), i-(size/2), SRCCOPY);
898 
899  LeaveCriticalSection(&m_criticalSection);
900 
901  DeleteObject(hPen);
902  DeleteDC(hDCMem);
903  ReleaseDC(m_hWnd, hDCScreen);
904  }
905  else {
906  setPixel(ip, color);
907  }
908 }
909 
917 void vpGDIRenderer::drawArrow(const vpImagePoint &ip1,
918  const vpImagePoint &ip2,
919  const vpColor &color,
920  unsigned int w,unsigned int h, unsigned int thickness)
921 {
922  double a = ip2.get_i() / m_rscale - ip1.get_i() / m_rscale;
923  double b = ip2.get_j() / m_rscale - ip1.get_j() / m_rscale;
924  double lg = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
925 
926  //computes the coordinates of the rectangle to blit later
927  // unsigned int x = (j2 >= j1) ? j1 : j2;
928  // unsigned int y = (i2 >= i1) ? i1 : i2;
929  // unsigned int w = (j2 >= j1) ? j2-j1 : j1-j2;
930  // unsigned int h = (i2 >= i1) ? i2-i1 : i1-i2;
931 
932  //get the window's DC
933  HDC hDCScreen = GetDC(m_hWnd);
934  HDC hDCMem = CreateCompatibleDC(hDCScreen);
935 
936  //create the pen
937  HPEN hPen;
938  if (color.id < vpColor::id_unknown)
939  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), m_colors[color.id]);
940  else {
941  COLORREF gdicolor = RGB(color.R, color.G, color.B);
942  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
943  }
944 
945  //select this bmp in memory
946  EnterCriticalSection(&m_criticalSection);
947  SelectObject(hDCMem, m_bmp);
948 
949  //select the pen
950  SelectObject(hDCMem, hPen);
951 
952 
953  if ((a==0)&&(b==0))
954  {
955  // DisplayCrossLarge(i1,j1,3,col) ;
956  }
957  else
958  {
959  a /= lg ;
960  b /= lg ;
961 
962  vpImagePoint ip3;
963  ip3.set_i( ip2.get_i() / m_rscale - w*a );
964  ip3.set_j( ip2.get_j() / m_rscale - w*b );
965 
966 
967  vpImagePoint ip4;
968 
969  //double t = 0 ;
970  //while (t<=_l)
971  {
972  ip4.set_i( ip3.get_i() - b*h );
973  ip4.set_j( ip3.get_j() + a*h );
974 
975  if (lg > 2*vpImagePoint::distance(ip2 / m_rscale, ip4) ) {
976  MoveToEx(hDCMem, vpMath::round(ip2.get_u() / m_rscale), vpMath::round(ip2.get_v() / m_rscale), NULL);
977  LineTo(hDCMem, vpMath::round(ip4.get_u()), vpMath::round(ip4.get_v()));
978  }
979  // t+=0.1 ;
980  }
981 
982  //t = 0 ;
983  //while (t>= -_l)
984  {
985  ip4.set_i( ip3.get_i() + b*h );
986  ip4.set_j( ip3.get_j() - a*h );
987 
988  if (lg > 2*vpImagePoint::distance(ip2 / m_rscale, ip4) ) {
989  MoveToEx(hDCMem, vpMath::round(ip2.get_u() / m_rscale), vpMath::round(ip2.get_v() / m_rscale), NULL);
990  LineTo(hDCMem, vpMath::round(ip4.get_u()), vpMath::round(ip4.get_v()));
991  }
992 
993  // t-=0.1 ;
994  }
995  MoveToEx(hDCMem, vpMath::round(ip1.get_u() / m_rscale), vpMath::round(ip1.get_v() / m_rscale), NULL);
996  LineTo(hDCMem, vpMath::round(ip2.get_u() / m_rscale), vpMath::round(ip2.get_v() / m_rscale));
997  }
998 
999  //display the result (flush)
1000  // BitBlt(hDCScreen, x, y, w, h, hDCMem, x, y, SRCCOPY);
1001 
1002  LeaveCriticalSection(&m_criticalSection);
1003 
1004  DeleteObject(hPen);
1005  DeleteDC(hDCMem);
1006  ReleaseDC(m_hWnd, hDCScreen);
1007 }
1008 
1013 void vpGDIRenderer::getImage(vpImage<vpRGBa> &I)
1014 {
1015  //size of image buffer : m_rwidth*m_rheight*4
1016  unsigned int size = m_rwidth*m_rheight *4;
1017  unsigned char * imBuffer = new unsigned char[size];
1018 
1019  //gets the hbitmap's bitmap
1020  GetBitmapBits(m_bmp, static_cast<LONG>(size), (void *)imBuffer);
1021 
1022  //resize the destination image as needed
1023  I.resize(m_rheight, m_rwidth);
1024 
1025  //copy the content
1026  for(unsigned int i=0 ; i<size ; i+=4)
1027  {
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];
1031  I.bitmap[i>>2].A = vpRGBa::alpha_default; // default opacity
1032  }
1033 
1034  delete [] imBuffer;
1035 }
1036 #endif
1037 #elif !defined(VISP_BUILD_SHARED_LIBS)
1038 // Work arround to avoid warning: libvisp_core.a(vpGDIRenderer.cpp.o) has no symbols
1039 void dummy_vpGDIRenderer() {};
1040 #endif
double get_v() const
Definition: vpImagePoint.h:268
double get_i() const
Definition: vpImagePoint.h:199
unsigned int getWidth() const
Definition: vpImage.h:226
unsigned char B
Blue component.
Definition: vpRGBa.h:155
Type * bitmap
points toward the bitmap
Definition: vpImage.h:134
static const vpColor black
Definition: vpColor.h:157
static const vpColor darkRed
Definition: vpColor.h:164
Class to define colors available for display functionnalities.
Definition: vpColor.h:121
double get_u() const
Definition: vpImagePoint.h:257
static const vpColor lightGray
Definition: vpColor.h:159
static const vpColor darkBlue
Definition: vpColor.h:170
unsigned char G
Green component.
Definition: vpRGBa.h:154
static const vpColor green
Definition: vpColor.h:166
static int round(const double x)
Definition: vpMath.h:249
double get_j() const
Definition: vpImagePoint.h:210
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:93
static const vpColor lightRed
Definition: vpColor.h:162
Definition: vpRGBa.h:66
static const vpColor red
Definition: vpColor.h:163
static const vpColor orange
Definition: vpColor.h:173
vpColorIdentifier id
Definition: vpColor.h:152
void set_i(const double ii)
Definition: vpImagePoint.h:163
static const vpColor cyan
Definition: vpColor.h:172
static const vpColor lightGreen
Definition: vpColor.h:165
static double sqr(double x)
Definition: vpMath.h:110
unsigned char A
Additionnal component.
Definition: vpRGBa.h:156
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:903
static const vpColor gray
Definition: vpColor.h:160
static const vpColor darkGray
Definition: vpColor.h:161
void set_j(const double jj)
Definition: vpImagePoint.h:174
Error that can be emited by the vpDisplay class and its derivates.
unsigned char R
Red component.
Definition: vpRGBa.h:153
static const vpColor darkGreen
Definition: vpColor.h:167
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
static const vpColor yellow
Definition: vpColor.h:171
static const vpColor lightBlue
Definition: vpColor.h:168
static const vpColor purple
Definition: vpColor.h:174
static const vpColor white
Definition: vpColor.h:158
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
Definition: vpImagePoint.h:279
static const vpColor blue
Definition: vpColor.h:169