ViSP  2.6.2
vpGDIRenderer.cpp
1 /****************************************************************************
2  *
3  * $Id: vpGDIRenderer.cpp 3682 2012-04-11 14:28:29Z fnovotny $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2012 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * GDI renderer for windows 32 display
36  *
37  * Authors:
38  * Bruno Renier
39  *
40  *****************************************************************************/
41 
42 #include <visp/vpConfig.h>
43 #define GDI_ROBUST
44 #if ( defined(VISP_HAVE_GDI) )
45 
46 
47 #ifndef DOXYGEN_SHOULD_SKIP_THIS
48 
49 #include <visp/vpGDIRenderer.h>
50 
54 vpGDIRenderer::vpGDIRenderer()
55 {
56  //if the screen depth is not 32bpp, throw an exception
57  if( GetDeviceCaps(GetDC(NULL),BITSPIXEL) != 32 )
59  "Only works in 32bits mode!");
60 
61  InitializeCriticalSection(&CriticalSection);
62 
63  //initialize GDI the palette
64  vpColor pcolor; // Predefined colors
65 
66  pcolor = vpColor::black;
67  colors[vpColor::id_black] = RGB(pcolor.R, pcolor.G, pcolor.B);
68  pcolor = vpColor::lightBlue;
69  colors[vpColor::id_lightBlue] = RGB(pcolor.R, pcolor.G, pcolor.B);
70  pcolor = vpColor::blue;
71  colors[vpColor::id_blue] = RGB(pcolor.R, pcolor.G, pcolor.B);
72  pcolor = vpColor::darkBlue;
73  colors[vpColor::id_darkBlue] = RGB(pcolor.R, pcolor.G, pcolor.B);
74  pcolor = vpColor::cyan;
75  colors[vpColor::id_cyan] = RGB(pcolor.R, pcolor.G, pcolor.B);
76  pcolor = vpColor::lightGreen;
77  colors[vpColor::id_lightGreen] = RGB(pcolor.R, pcolor.G, pcolor.B);
78  pcolor = vpColor::green;
79  colors[vpColor::id_green] = RGB(pcolor.R, pcolor.G, pcolor.B);
80  pcolor = vpColor::darkGreen;
81  colors[vpColor::id_darkGreen] = RGB(pcolor.R, pcolor.G, pcolor.B);
82  pcolor = vpColor::lightRed;
83  colors[vpColor::id_lightRed] = RGB(pcolor.R, pcolor.G, pcolor.B);
84  pcolor = vpColor::red;
85  colors[vpColor::id_red] = RGB(pcolor.R, pcolor.G, pcolor.B);
86  pcolor = vpColor::darkRed;
87  colors[vpColor::id_darkRed] = RGB(pcolor.R, pcolor.G, pcolor.B);
88  pcolor = vpColor::white;
89  colors[vpColor::id_white] = RGB(pcolor.R, pcolor.G, pcolor.B);
90  pcolor = vpColor::lightGray;
91  colors[vpColor::id_lightGray] = RGB(pcolor.R, pcolor.G, pcolor.B);
92  pcolor = vpColor::gray;
93  colors[vpColor::id_gray] = RGB(pcolor.R, pcolor.G, pcolor.B);
94  pcolor = vpColor::darkGray;
95  colors[vpColor::id_darkGray] = RGB(pcolor.R, pcolor.G, pcolor.B);
96  pcolor = vpColor::yellow;
97  colors[vpColor::id_yellow]= RGB(pcolor.R, pcolor.G, pcolor.B);
98  pcolor = vpColor::orange;
99  colors[vpColor::id_orange]= RGB(pcolor.R, pcolor.G, pcolor.B);
100  pcolor = vpColor::purple;
101  colors[vpColor::id_purple]= RGB(pcolor.R, pcolor.G, pcolor.B);
102 
103  nbCols = 0;
104  nbRows = 0;
105  bmp = NULL;
106 }
107 
111 vpGDIRenderer::~vpGDIRenderer()
112 {
113  //Deletes the critical section object
114  DeleteCriticalSection(&CriticalSection);
115  //Deletes the bitmap
116  DeleteObject(bmp);
117  //Deletes the font object
118  DeleteObject(hFont);
119 }
120 
127 bool vpGDIRenderer::init(HWND hWindow, unsigned int width, unsigned int height)
128 {
129  timelost = 0.;
130  hWnd = hWindow;
131  nbCols = width;
132  nbRows = height;
133 
134  //creates the font
135  hFont = CreateFont(18, 0, 0, 0, FW_NORMAL, false, false, false,
136  DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
137  CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
138  DEFAULT_PITCH | FF_DONTCARE, NULL);
139  return true;
140 }
141 
146 void vpGDIRenderer::setImg(const vpImage<vpRGBa>& im)
147 {
148  //converts the image into a HBITMAP
149  convert(im, bmp);
150  //updates the size of the image
151  nbCols=im.getWidth();
152  nbRows=im.getHeight();
153 }
154 
159 void vpGDIRenderer::setImgROI(const vpImage<vpRGBa>& im, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
160 {
161  //converts the image into a HBITMAP
162  convertROI(im, bmp, iP, width, height);
163  //updates the size of the image
164  nbCols=im.getWidth();
165  nbRows=im.getHeight();
166 }
167 
172 void vpGDIRenderer::setImg(const vpImage<unsigned char>& im)
173 {
174  //converts the image into a HBITMAP
175  convert(im, bmp);
176  //updates the size of the image
177  nbCols=im.getWidth();
178  nbRows=im.getHeight();
179 }
180 
185 void vpGDIRenderer::setImgROI(const vpImage<unsigned char>& im, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
186 {
187  //converts the image into a HBITMAP
188  convertROI(im, bmp, iP, width, height);
189  //updates the size of the image
190  nbCols=im.getWidth();
191  nbRows=im.getHeight();
192 }
193 
197 bool vpGDIRenderer::render()
198 {
199  //gets the window's DC
200  PAINTSTRUCT ps;
201  HDC hDCScreen = BeginPaint(hWnd, &ps);
202 
203  //create a memory DC
204  HDC hDCMem = CreateCompatibleDC(hDCScreen);
205 
206  //selects this bmp in memory
207  EnterCriticalSection(&CriticalSection);
208  SelectObject(hDCMem, bmp);
209 
210 
211  //blits it on the window's DC
212  BitBlt(hDCScreen, 0, 0,
213  static_cast<int>( nbCols ),
214  static_cast<int>( nbRows ),
215  hDCMem, 0, 0, SRCCOPY);
216 
217  LeaveCriticalSection(&CriticalSection);
218  //DeleteDC(hDCMem);
219  DeleteObject(hDCMem);
220 
221  EndPaint(hWnd, &ps);
222 
223  return true;
224 }
225 
231 void vpGDIRenderer::convert(const vpImage<vpRGBa> &I, HBITMAP& hBmp)
232 {
233  //get the image's width and height
234  unsigned int w = I.getWidth();
235  unsigned int h = I.getHeight();
236 
237  //each line of a HBITMAP needs to be word aligned
238  //we need padding if the width is an odd number
239  bool needPad = ((w%2) == 0) ? false : true;
240  unsigned int newW = w;
241 
242  //in case of padding, the new width is width+1
243  newW = (needPad) ? (w+1) : w;
244 
245  //allocate the buffer
246  unsigned char * imBuffer = new unsigned char[newW * h * 4];
247 
248  //if we need padding (width needs to be a multiple of 2)
249  if(needPad)
250  {
251  unsigned int j = 0;
252  for(unsigned int i=0, k=0 ; i<newW * h * 4; i+=4, k++)
253  {
254  //end of a line = padding = inserts 0s
255  if(j==w && needPad)
256  {
257  imBuffer[i+0] = 0;
258  imBuffer[i+1] = 0;
259  imBuffer[i+2] = 0;
260  imBuffer[i+3] = 0;
261  j = 0;
262  k --;
263  }
264  else
265  {
266  //RGBA -> BGRA
267  imBuffer[i+0] = I.bitmap[k].B;
268  imBuffer[i+1] = I.bitmap[k].G;
269  imBuffer[i+2] = I.bitmap[k].R;
270  imBuffer[i+3] = I.bitmap[k].A;
271  j++;
272  }
273  }
274  }
275  else
276  //Simple conversion (no padding)
277  {
278  for(unsigned int i=0, k=0 ; i<w * h * 4 ; i+=4, k++)
279  {
280  imBuffer[i+0] = I.bitmap[k].B;
281  imBuffer[i+1] = I.bitmap[k].G;
282  imBuffer[i+2] = I.bitmap[k].R;
283  imBuffer[i+3] = I.bitmap[k].A;
284  }
285  }
286 
287  //updates the bitmap's pixel data
288  updateBitmap(hBmp,imBuffer, newW, h);
289 
290  //we don't need this buffer anymore
291  delete [] imBuffer;
292 }
293 
299 void vpGDIRenderer::convertROI(const vpImage<vpRGBa> &I, HBITMAP& hBmp, const vpImagePoint &iP, const unsigned int width, const unsigned int height)
300 {
301  //get the image's width and height
302  unsigned int w = width;
303  unsigned int h = height;
304 
305  //each line of a HBITMAP needs to be word aligned
306  //we need padding if the width is an odd number
307  bool needPad = ((w%2) == 0) ? false : true;
308  unsigned int newW = w;
309 
310  //in case of padding, the new width is width+1
311  newW = (needPad) ? (w+1) : w;
312 
313  //allocate the buffer
314  unsigned char * imBuffer = new unsigned char[newW * h * 4];
315 
316  vpRGBa* bitmap = I.bitmap;
317  unsigned int iwidth = I.getWidth();
318  bitmap = bitmap + (int)(iP.get_i()*iwidth+ iP.get_j());
319 
320  //if we need padding (width needs to be a multiple of 2)
321  if(needPad)
322  {
323  unsigned int j = 0;
324  unsigned int k = 0;
325  for(unsigned int i=0 ; i<newW * h * 4; i+=4)
326  {
327  //end of a line = padding = inserts 0s
328  if(j==w && needPad)
329  {
330  imBuffer[i+0] = 0;
331  imBuffer[i+1] = 0;
332  imBuffer[i+2] = 0;
333  imBuffer[i+3] = 0;
334  j = 0;
335  }
336  else
337  {
338  //RGBA -> BGRA
339  imBuffer[i+0] = (bitmap+k)->B;
340  imBuffer[i+1] = (bitmap+k)->G;
341  imBuffer[i+2] = (bitmap+k)->R;
342  imBuffer[i+3] = (bitmap+k)->A;
343  //bitmap++;
344  j++;
345  k++;
346  }
347  if (k == newW)
348  {
349  bitmap = bitmap+iwidth;
350  k = 0;
351  }
352  }
353  }
354  else
355  //Simple conversion (no padding)
356  {
357  unsigned int k = 0;
358  for (unsigned int i=0 ; i < w * h * 4 ; i+=4)
359  {
360  imBuffer[i+0] = (bitmap+k)->B;
361  imBuffer[i+1] = (bitmap+k)->G;
362  imBuffer[i+2] = (bitmap+k)->R;
363  imBuffer[i+3] = (bitmap+k)->A;
364  //bitmap++;
365  k++;
366  if (k == newW)
367  {
368  bitmap = bitmap+iwidth;
369  k = 0;
370  }
371  }
372  }
373 
374  //updates the bitmap's pixel data
375  updateBitmapROI(hBmp,imBuffer,iP, newW, h);
376 
377  //we don't need this buffer anymore
378  delete [] imBuffer;
379 }
380 
381 
387 void vpGDIRenderer::convert(const vpImage<unsigned char> &I, HBITMAP& hBmp)
388 {
389  //get the image's width and height
390  unsigned int w = I.getWidth();
391  unsigned int h = I.getHeight();
392 
393  //each line of a HBITMAP needs to be word aligned
394  //we need padding if the width is an odd number
395  bool needPad = ((w%2) == 0) ? false : true;
396  unsigned int newW = w;
397 
398  //in case of padding, the new width is width+1
399  newW = (needPad) ? (w+1) : w;
400 
401  //allocate the buffer
402  unsigned char * imBuffer = new unsigned char[newW * h * 4];
403 
404  //if we need padding
405  if(needPad)
406  {
407  unsigned int j = 0;
408  for(unsigned int i=0, k=0 ; i<newW * h * 4; i+=4, k++)
409  {
410  //end of a line = padding = inserts 0s
411  if(j==w && needPad)
412  {
413  imBuffer[i+0] = 0;
414  imBuffer[i+1] = 0;
415  imBuffer[i+2] = 0;
416  imBuffer[i+3] = 0;
417  j = 0;
418  k --;
419  }
420  else
421  {
422  imBuffer[i+0] = I.bitmap[k];
423  imBuffer[i+1] = I.bitmap[k];
424  imBuffer[i+2] = I.bitmap[k];
425  imBuffer[i+3] = I.bitmap[k];
426  j++;
427  }
428  }
429  }
430  else
431  //Simple conversion
432  {
433  for(unsigned int i=0, k=0 ; i<w * h * 4 ; i+=4, k++)
434  {
435  imBuffer[i+0] = I.bitmap[k];
436  imBuffer[i+1] = I.bitmap[k];
437  imBuffer[i+2] = I.bitmap[k];
438  imBuffer[i+3] = I.bitmap[k];
439  }
440  }
441 
442  //updates the bitmap's pixel data
443  updateBitmap(hBmp,imBuffer, newW, h);
444 
445  //we don't need this buffer anymore
446  delete [] imBuffer;
447 }
448 
449 
455 void vpGDIRenderer::convertROI(const vpImage<unsigned char> &I, HBITMAP& hBmp, const vpImagePoint &iP, const unsigned int width, const unsigned int height)
456 {
457  //get the image's width and height
458  unsigned int w = width;
459  unsigned int h = height;
460 
461  //each line of a HBITMAP needs to be word aligned
462  //we need padding if the width is an odd number
463  bool needPad = ((w%2) == 0) ? false : true;
464  unsigned int newW = w;
465 
466  //in case of padding, the new width is width+1
467  newW = (needPad) ? (w+1) : w;
468 
469  //allocate the buffer
470  unsigned char * imBuffer = new unsigned char[newW * h * 4];
471 
472  unsigned char* bitmap = I.bitmap;
473  unsigned int iwidth = I.getWidth();
474  bitmap = bitmap + (int)(iP.get_i()*iwidth+ iP.get_j());
475 
476  //if we need padding (width needs to be a multiple of 2)
477  if(needPad)
478  {
479  unsigned int j = 0;
480  unsigned int k = 0;
481  for(unsigned int i=0 ; i<newW * h * 4; i+=4)
482  {
483  //end of a line = padding = inserts 0s
484  if(j==w && needPad)
485  {
486  imBuffer[i+0] = 0;
487  imBuffer[i+1] = 0;
488  imBuffer[i+2] = 0;
489  imBuffer[i+3] = 0;
490  j = 0;
491  }
492  else
493  {
494  //RGBA -> BGRA
495  imBuffer[i+0] = *(bitmap+k);
496  imBuffer[i+1] = *(bitmap+k);
497  imBuffer[i+2] = *(bitmap+k);
498  imBuffer[i+3] = *(bitmap+k);
499  //bitmap++;
500  j++;
501  k++;
502  }
503  if (k == newW)
504  {
505  bitmap = bitmap+iwidth;
506  k = 0;
507  }
508  }
509  }
510  else
511  //Simple conversion (no padding)
512  {
513  unsigned int k = 0;
514  for (unsigned int i=0 ; i < w * h * 4 ; i+=4)
515  {
516  imBuffer[i+0] = *(bitmap+k);
517  imBuffer[i+1] = *(bitmap+k);
518  imBuffer[i+2] = *(bitmap+k);
519  imBuffer[i+3] = *(bitmap+k);
520  //bitmap++;
521  k++;
522  if (k == newW)
523  {
524  bitmap = bitmap+iwidth;
525  k = 0;
526  }
527  }
528  }
529 
530  //updates the bitmap's pixel data
531  updateBitmapROI(hBmp,imBuffer,iP, newW, h);
532 
533  //we don't need this buffer anymore
534  delete [] imBuffer;
535 }
536 
547 bool vpGDIRenderer::updateBitmap(HBITMAP& hBmp, unsigned char * imBuffer,
548  unsigned int w, unsigned int h)
549 {
550  //the bitmap may only be accessed by one thread at the same time
551  //that's why we enter critical section
552  EnterCriticalSection(&CriticalSection);
553 
554  //if the existing bitmap object is of the right size
555  if( (nbCols==w) && (nbRows==h) )
556  {
557  //just replace the content
558  SetBitmapBits(hBmp, w * h * 4, imBuffer);
559  }
560  else
561  {
562  if(hBmp != NULL)
563  {
564  //delete the old BITMAP
565  DeleteObject(hBmp);
566  }
567  //create a new BITMAP from this buffer
568  if( (hBmp = CreateBitmap(static_cast<int>(w),static_cast<int>(h),
569  1,32,(void*)imBuffer)) == NULL)
570  return false;
571  }
572 
573  LeaveCriticalSection(&CriticalSection);
574  return true;
575 }
576 
577 
589 bool vpGDIRenderer::updateBitmapROI(HBITMAP& hBmp, unsigned char * imBuffer, const vpImagePoint &iP,
590  unsigned int w, unsigned int h)
591 {
592  int w_ = static_cast<int>(w);
593  int h_ = static_cast<int>(h);
594  HBITMAP htmp = CreateBitmap(w_,h_,1,32,(void*)imBuffer);
595 
596  //get the window's DC
597  HDC hDCScreen = GetDC(hWnd);
598  HDC hDCMem = CreateCompatibleDC(hDCScreen);
599  HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
600 
601  //select this bmp in memory
602  EnterCriticalSection(&CriticalSection);
603  SelectObject(hDCMem, bmp);
604  SelectObject(hDCMem2, htmp);
605 
606  BitBlt(hDCMem,(int)iP.get_u(),(int)iP.get_v(),w_,h_, hDCMem2, 0, 0,SRCCOPY);
607  LeaveCriticalSection(&CriticalSection);
608 
609  DeleteDC(hDCMem);
610  ReleaseDC(hWnd, hDCScreen);
611  DeleteObject(htmp);
612 
613  return true;
614 }
615 
622 void vpGDIRenderer::setPixel(const vpImagePoint &iP,
623  const vpColor &color)
624 {
625  //get the window's DC
626  HDC hDCScreen = GetDC(hWnd);
627  HDC hDCMem = CreateCompatibleDC(hDCScreen);
628 
629  //select this bmp in memory
630  EnterCriticalSection(&CriticalSection);
631  SelectObject(hDCMem, bmp);
632 
633  if (color.id < vpColor::id_unknown)
634  SetPixel(hDCMem, vpMath::round(iP.get_u()), vpMath::round(iP.get_v()),
635  colors[color.id]);
636  else {
637  COLORREF gdicolor = RGB(color.R, color.G, color.B);
638  SetPixel(hDCMem, vpMath::round(iP.get_u()), vpMath::round(iP.get_v()),
639  gdicolor);
640  }
641  //display the result (flush)
642  // BitBlt(hDCScreen, x, y, 1, 1, hDCMem, x, y, SRCCOPY);
643 
644  LeaveCriticalSection(&CriticalSection);
645 
646  DeleteDC(hDCMem);
647  ReleaseDC(hWnd, hDCScreen);
648 }
649 
657 void vpGDIRenderer::drawLine(const vpImagePoint &ip1,
658  const vpImagePoint &ip2,
659  const vpColor &color,
660  unsigned int thickness, int style)
661 {
662 HDC hDCScreen,hDCMem;
663 HPEN hPen;
664 #ifdef GDI_ROBUST
665  double start = vpTime::measureTimeMs();
666  while(vpTime::measureTimeMs()-start<1000){
667  hDCScreen = GetDC(hWnd);
668  if(!hDCScreen) continue;
669  hDCMem = CreateCompatibleDC(hDCScreen);
670  if(!hDCMem){
671  ReleaseDC(hWnd, hDCScreen);
672  continue;
673  }
674 
675  //create the pen
676  if (color.id < vpColor::id_unknown)
677  hPen = CreatePen(style, static_cast<int>(thickness), colors[color.id]);
678  else {
679  COLORREF gdicolor = RGB(color.R, color.G, color.B);
680  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
681  }
682  if(!hPen){
683  DeleteDC(hDCMem);
684  ReleaseDC(hWnd, hDCScreen);
685  continue;
686  }
687  if(!SetBkMode(hDCMem, TRANSPARENT)){
688  DeleteObject(hPen);
689  DeleteDC(hDCMem);
690  ReleaseDC(hWnd, hDCScreen);
691  continue;
692  }
693 
694  //select this bmp in memory
695  EnterCriticalSection(&CriticalSection);
696 
697  if(!SelectObject(hDCMem, bmp)){
698  LeaveCriticalSection(&CriticalSection);
699  DeleteObject(hPen);
700  DeleteDC(hDCMem);
701  ReleaseDC(hWnd, hDCScreen);
702  continue;
703  }
704 
705  //select the pen
706  if(!SelectObject(hDCMem, hPen)){
707  LeaveCriticalSection(&CriticalSection);
708  DeleteObject(hPen);
709  DeleteDC(hDCMem);
710  ReleaseDC(hWnd, hDCScreen);
711  continue;
712  }
713  break;
714  }
715  timelost+=(vpTime::measureTimeMs()-start);
716 #else
717  //get the window's DC
718  hDCScreen = GetDC(hWnd);
719  hDCMem = CreateCompatibleDC(hDCScreen);
720 
721  //create the pen
722  hPen;
723  if (color.id < vpColor::id_unknown)
724  hPen = CreatePen(style, static_cast<int>(thickness), colors[color.id]);
725  else {
726  COLORREF gdicolor = RGB(color.R, color.G, color.B);
727  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
728  }
729  SetBkMode(hDCMem, TRANSPARENT);
730 
731  //select this bmp in memory
732  EnterCriticalSection(&CriticalSection);
733  SelectObject(hDCMem, bmp);
734 
735  //select the pen
736  SelectObject(hDCMem, hPen);
737 #endif
738  //move to the starting point
739  MoveToEx(hDCMem, vpMath::round(ip1.get_u()), vpMath::round(ip1.get_v()), NULL);
740  //Draw the line
741  LineTo(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()));
742 
743  //computes the coordinates of the rectangle to blit
744 // int x = (j2 >= j1) ? j1 : j2;
745 // int y = (i2 >= i1) ? i1 : i2;
746 // int w = (j2 >= j1) ? j2-j1 : j1-j2;
747 // int h = (i2 >= i1) ? i2-i1 : i1-i2;
748 
749  //display the result (flush)
750  // BitBlt(hDCScreen, x, y, w, h, hDCMem, x, y, SRCCOPY);
751 
752  LeaveCriticalSection(&CriticalSection);
753 
754  DeleteObject(hPen);
755  DeleteDC(hDCMem);
756  ReleaseDC(hWnd, hDCScreen);
757 
758 }
759 
769 void vpGDIRenderer::drawRect(const vpImagePoint &topLeft,
770  unsigned int width, unsigned int height,
771  const vpColor &color, bool fill,
772  unsigned int thickness)
773 {
774  if (thickness == 0) thickness = 1;
775  //get the window's DC
776  HDC hDCScreen = GetDC(hWnd);
777  HDC hDCMem = CreateCompatibleDC(hDCScreen);
778 
779  //create the pen
780  HPEN hPen;
781  COLORREF gdicolor = RGB(0,0,0);
782 
783  if (color.id < vpColor::id_unknown)
784  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
785  else {
786  gdicolor = RGB(color.R, color.G, color.B);
787  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
788  }
789 
790  //create an hollow or solid brush (depends on boolean fill)
791  LOGBRUSH lBrush;
792  if(fill) {
793  lBrush.lbStyle = BS_SOLID;
794  if (color.id < vpColor::id_unknown)
795  lBrush.lbColor = colors[color.id];
796  else {
797  lBrush.lbColor = gdicolor;
798  }
799  }
800  else lBrush.lbStyle = BS_HOLLOW;
801  HBRUSH hbrush = CreateBrushIndirect(&lBrush);
802 
803  //select this bmp in memory
804  EnterCriticalSection(&CriticalSection);
805  SelectObject(hDCMem, bmp);
806 
807  //select the brush
808  SelectObject(hDCMem, hbrush);
809  //select the pen
810  SelectObject(hDCMem, hPen);
811 
812  //draw the rectangle
813  Rectangle(hDCMem, vpMath::round(topLeft.get_u()), vpMath::round(topLeft.get_v()),
814  vpMath::round(topLeft.get_u())+static_cast<int>(width),
815  vpMath::round(topLeft.get_v())+static_cast<int>(height));
816 
817  //display the result (flush)
818 // BitBlt(hDCScreen, j, i, width, height, hDCMem, j, i, SRCCOPY);
819 
820  LeaveCriticalSection(&CriticalSection);
821 
822  DeleteObject(hbrush);
823  DeleteObject(hPen);
824  DeleteDC(hDCMem);
825  ReleaseDC(hWnd, hDCScreen);
826 
827 }
828 
833 void vpGDIRenderer::clear(const vpColor &color)
834 {
835  vpImagePoint ip;
836  ip.set_i(0);
837  ip.set_j(0);
838  drawRect(ip, nbCols, nbRows, color, true, 0);
839 }
840 
841 
850 void vpGDIRenderer::drawCircle(const vpImagePoint &center, unsigned int radius,
851  const vpColor &color, bool fill, unsigned int thickness)
852 {
853 
854  //get the window's DC
855  HDC hDCScreen = GetDC(hWnd);
856  HDC hDCMem = CreateCompatibleDC(hDCScreen);
857 
858  //create the pen
859  HPEN hPen;
860  if (color.id < vpColor::id_unknown)
861  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
862  else {
863  COLORREF gdicolor = RGB(color.R, color.G, color.B);
864  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
865  }
866 
867  //create an hollow brush
868  LOGBRUSH lBrush;
869  lBrush.lbStyle = BS_HOLLOW;
870  HBRUSH hbrush = CreateBrushIndirect(&lBrush);
871 
872  //computes bounding rectangle
873  int radius_ = static_cast<int>(radius);
874  int x1 = vpMath::round(center.get_u())-radius_;
875  int y1 = vpMath::round(center.get_v())-radius_;
876  int x2 = vpMath::round(center.get_u())+radius_;
877  int y2 = vpMath::round(center.get_v())+radius_;
878 
879  //select this bmp in memory
880  EnterCriticalSection(&CriticalSection);
881  SelectObject(hDCMem, bmp);
882 
883  //select the brush
884  SelectObject(hDCMem, hbrush);
885  //select the pen
886  SelectObject(hDCMem, hPen);
887 
888  //draw the circle
889  if (fill==false)
890  Ellipse(hDCMem, x1, y1, x2, y2);
891 
892  else
893  {
894  while (x2-x1 > 0)
895  {
896  x1++;
897  x2--;
898  y1++;
899  y2--;
900  Ellipse(hDCMem, x1, y1, x2, y2);
901  }
902  }
903 
904  //display the result (flush)
905  // BitBlt(hDCScreen, x1, y1, x2-x1, y2-y1, hDCMem, x1, y1, SRCCOPY);
906 
907  LeaveCriticalSection(&CriticalSection);
908 
909  DeleteObject(hbrush);
910  DeleteObject(hPen);
911  DeleteDC(hDCMem);
912  ReleaseDC(hWnd, hDCScreen);
913 }
914 
915 
922 void vpGDIRenderer::drawText(const vpImagePoint &ip, const char * text,
923  const vpColor &color)
924 {
925  //get the window's DC
926  HDC hDCScreen = GetDC(hWnd);
927  HDC hDCMem = CreateCompatibleDC(hDCScreen);
928 
929  //select this bmp in memory
930  EnterCriticalSection(&CriticalSection);
931  SelectObject(hDCMem, bmp);
932 
933  //Select the font
934  SelectObject(hDCMem, hFont);
935 
936  //set the text color
937  if (color.id < vpColor::id_unknown)
938  SetTextColor(hDCMem, colors[color.id]);
939  else {
940  COLORREF gdicolor = RGB(color.R, color.G, color.B);
941  SetTextColor(hDCMem, gdicolor);
942  }
943 
944  //we don't use the bkColor
945  SetBkMode(hDCMem, TRANSPARENT);
946 
947  SIZE size;
948  int length = (int) strlen(text);
949 
950  //get the displayed string dimensions
951  GetTextExtentPoint32(hDCMem, text, length, &size);
952 
953  //displays the string
954  TextOut(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v()), text, length);
955 
956  //display the result (flush)
957  // BitBlt(hDCScreen, j, i, size.cx, size.cy, hDCMem, j, i, SRCCOPY);
958 
959  LeaveCriticalSection(&CriticalSection);
960 
961  DeleteDC(hDCMem);
962  ReleaseDC(hWnd, hDCScreen);
963 }
964 
965 
966 
974 void vpGDIRenderer::drawCross(const vpImagePoint &ip, unsigned int size,
975  const vpColor &color, unsigned int thickness)
976 {
977  /* unsigned */ int half_size = static_cast<int>( size/2 );
978 
979  // if half_size is equal to zero, nothing is displayed with the code
980  // just below. So, if half_size is equal to zero we just draw the
981  // pixel.
982  if (half_size) {
983  //get the window's DC
984  HDC hDCScreen = GetDC(hWnd);
985  HDC hDCMem = CreateCompatibleDC(hDCScreen);
986 
987  //create the pen
988  HPEN hPen;
989  if (color.id < vpColor::id_unknown)
990  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
991  else {
992  COLORREF gdicolor = RGB(color.R, color.G, color.B);
993  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
994  }
995 
996  //select this bmp in memory
997  EnterCriticalSection(&CriticalSection);
998  SelectObject(hDCMem, bmp);
999 
1000  //select the pen
1001  SelectObject(hDCMem, hPen);
1002 
1003  //move to the starting point
1004  MoveToEx(hDCMem, vpMath::round(ip.get_u())-half_size, vpMath::round(ip.get_v()), NULL);
1005  //Draw the first line (horizontal)
1006  LineTo(hDCMem, vpMath::round(ip.get_u())+half_size, vpMath::round(ip.get_v()));
1007 
1008  //move to the starting point
1009  MoveToEx(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v())-half_size, NULL);
1010  //Draw the second line (vertical)
1011  LineTo(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v())+half_size);
1012 
1013  //display the result (flush)
1014  // BitBlt(hDCScreen, j-(size/2), i-(size/2), size, size,
1015 // hDCMem, j-(size/2), i-(size/2), SRCCOPY);
1016 
1017  LeaveCriticalSection(&CriticalSection);
1018 
1019  DeleteObject(hPen);
1020  DeleteDC(hDCMem);
1021  ReleaseDC(hWnd, hDCScreen);
1022  }
1023  else {
1024  setPixel(ip, color);
1025  }
1026 
1027 
1028 }
1029 
1037 void vpGDIRenderer::drawArrow(const vpImagePoint &ip1,
1038  const vpImagePoint &ip2,
1039  const vpColor &color,
1040  unsigned int w,unsigned int h, unsigned int thickness)
1041 {
1042  double a = ip2.get_i() - ip1.get_i() ;
1043  double b = ip2.get_j() - ip1.get_j() ;
1044  double lg = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
1045 
1046  //computes the coordinates of the rectangle to blit later
1047 // unsigned int x = (j2 >= j1) ? j1 : j2;
1048 // unsigned int y = (i2 >= i1) ? i1 : i2;
1049 // unsigned int w = (j2 >= j1) ? j2-j1 : j1-j2;
1050 // unsigned int h = (i2 >= i1) ? i2-i1 : i1-i2;
1051 
1052  //get the window's DC
1053  HDC hDCScreen = GetDC(hWnd);
1054  HDC hDCMem = CreateCompatibleDC(hDCScreen);
1055 
1056  //create the pen
1057  HPEN hPen;
1058  if (color.id < vpColor::id_unknown)
1059  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
1060  else {
1061  COLORREF gdicolor = RGB(color.R, color.G, color.B);
1062  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
1063  }
1064 
1065  //select this bmp in memory
1066  EnterCriticalSection(&CriticalSection);
1067  SelectObject(hDCMem, bmp);
1068 
1069  //select the pen
1070  SelectObject(hDCMem, hPen);
1071 
1072 
1073  if ((a==0)&&(b==0))
1074  {
1075  // DisplayCrossLarge(i1,j1,3,col) ;
1076  }
1077  else
1078  {
1079  a /= lg ;
1080  b /= lg ;
1081 
1082  vpImagePoint ip3;
1083  ip3.set_i( ip2.get_i() - w*a );
1084  ip3.set_j( ip2.get_j() - w*b );
1085 
1086 
1087  vpImagePoint ip4;
1088 
1089  //double t = 0 ;
1090  //while (t<=_l)
1091  {
1092  ip4.set_i( ip3.get_i() - b*h );
1093  ip4.set_j( ip3.get_j() + a*h );
1094 
1095  MoveToEx(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()), NULL);
1096  LineTo(hDCMem, vpMath::round(ip4.get_u()), vpMath::round(ip4.get_v()));
1097 
1098  // t+=0.1 ;
1099  }
1100 
1101  //t = 0 ;
1102  //while (t>= -_l)
1103  {
1104  ip4.set_i( ip3.get_i() + b*h );
1105  ip4.set_j( ip3.get_j() - a*h );
1106 
1107  MoveToEx(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()), NULL);
1108  LineTo(hDCMem, vpMath::round(ip4.get_u()), vpMath::round(ip4.get_v()));
1109 
1110  // t-=0.1 ;
1111  }
1112  MoveToEx(hDCMem, vpMath::round(ip1.get_u()), vpMath::round(ip1.get_v()), NULL);
1113  LineTo(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()));
1114 
1115  }
1116 
1117 
1118  //display the result (flush)
1119 // BitBlt(hDCScreen, x, y, w, h, hDCMem, x, y, SRCCOPY);
1120 
1121  LeaveCriticalSection(&CriticalSection);
1122 
1123  DeleteObject(hPen);
1124  DeleteDC(hDCMem);
1125  ReleaseDC(hWnd, hDCScreen);
1126 }
1127 
1132 void vpGDIRenderer::getImage(vpImage<vpRGBa> &I)
1133 {
1134  //size of image buffer : nbCols*nbRows*4
1135  unsigned int size = nbCols*nbRows*4;
1136  unsigned char * imBuffer = new unsigned char[size];
1137 
1138  //gets the hbitmap's bitmap
1139  GetBitmapBits(bmp, static_cast<LONG>(size), (void *)imBuffer);
1140 
1141  //resize the destination image as needed
1142  I.resize(nbRows, nbCols);
1143 
1144  //copy the content
1145  for(unsigned int i=0 ; i<size ; i+=4)
1146  {
1147  I.bitmap[i>>2].R = imBuffer[i+2];
1148  I.bitmap[i>>2].G = imBuffer[i+1];
1149  I.bitmap[i>>2].B = imBuffer[i+0];
1150  I.bitmap[i>>2].A = 0xFF; //255 = maximum opacity
1151  }
1152 
1153  delete [] imBuffer;
1154 }
1155 #endif
1156 #endif
void set_j(const double j)
Definition: vpImagePoint.h:156
double get_v() const
Definition: vpImagePoint.h:250
double get_i() const
Definition: vpImagePoint.h:181
unsigned int getWidth() const
Definition: vpImage.h:154
unsigned char B
Blue component.
Definition: vpRGBa.h:155
Type * bitmap
points toward the bitmap
Definition: vpImage.h:115
static const vpColor black
Definition: vpColor.h:159
static const vpColor darkRed
Definition: vpColor.h:166
Class to define colors available for display functionnalities.
Definition: vpColor.h:123
double get_u() const
Definition: vpImagePoint.h:239
void resize(const unsigned int height, const unsigned int width)
set the size of the image
Definition: vpImage.h:530
void set_i(const double i)
Definition: vpImagePoint.h:145
static const vpColor lightGray
Definition: vpColor.h:161
static double measureTimeMs()
Definition: vpTime.cpp:86
static const vpColor darkBlue
Definition: vpColor.h:172
unsigned char G
Green component.
Definition: vpRGBa.h:154
static const vpColor green
Definition: vpColor.h:168
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:192
static const vpColor lightRed
Definition: vpColor.h:164
Class that defines a RGB 32 bits structure.
Definition: vpRGBa.h:68
static const vpColor red
Definition: vpColor.h:165
static const vpColor orange
Definition: vpColor.h:175
vpColorIdentifier id
Definition: vpColor.h:154
static const vpColor cyan
Definition: vpColor.h:174
static const vpColor lightGreen
Definition: vpColor.h:167
static double sqr(double x)
Definition: vpMath.h:106
unsigned char A
Additionnal component.
Definition: vpRGBa.h:156
static const vpColor gray
Definition: vpColor.h:162
static const vpColor darkGray
Definition: vpColor.h:163
Error that can be emited by the vpDisplay class and its derivates.
unsigned char R
Red component.
Definition: vpRGBa.h:153
unsigned int getHeight() const
Definition: vpImage.h:145
static const vpColor darkGreen
Definition: vpColor.h:169
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
static const vpColor yellow
Definition: vpColor.h:173
static const vpColor lightBlue
Definition: vpColor.h:170
static const vpColor purple
Definition: vpColor.h:176
static const vpColor white
Definition: vpColor.h:160
static const vpColor blue
Definition: vpColor.h:171