ViSP  2.10.0
vpGDIRenderer.cpp
1 /****************************************************************************
2  *
3  * $Id: vpGDIRenderer.cpp 4733 2014-05-19 20:44:05Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 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>& I)
147 {
148  //converts the image into a HBITMAP
149  convert(I, bmp);
150  //updates the size of the image
151  nbCols=I.getWidth();
152  nbRows=I.getHeight();
153 }
154 
161 void vpGDIRenderer::setImgROI(const vpImage<vpRGBa>& I, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
162 {
163  //converts the image into a HBITMAP
164  convertROI(I, iP, width, height);
165  //updates the size of the image
166  nbCols=I.getWidth();
167  nbRows=I.getHeight();
168 }
169 
174 void vpGDIRenderer::setImg(const vpImage<unsigned char>& I)
175 {
176  //converts the image into a HBITMAP
177  convert(I, bmp);
178  //updates the size of the image
179  nbCols=I.getWidth();
180  nbRows=I.getHeight();
181 }
182 
189 void vpGDIRenderer::setImgROI(const vpImage<unsigned char>& I, const vpImagePoint &iP, const unsigned int width, const unsigned int height )
190 {
191  //converts the image into a HBITMAP
192  convertROI(I, iP, width, height);
193  //updates the size of the image
194  nbCols=I.getWidth();
195  nbRows=I.getHeight();
196 }
197 
201 bool vpGDIRenderer::render()
202 {
203  //gets the window's DC
204  PAINTSTRUCT ps;
205  HDC hDCScreen = BeginPaint(hWnd, &ps);
206 
207  //create a memory DC
208  HDC hDCMem = CreateCompatibleDC(hDCScreen);
209 
210  //selects this bmp in memory
211  EnterCriticalSection(&CriticalSection);
212  SelectObject(hDCMem, bmp);
213 
214 
215  //blits it on the window's DC
216  BitBlt(hDCScreen, 0, 0,
217  static_cast<int>( nbCols ),
218  static_cast<int>( nbRows ),
219  hDCMem, 0, 0, SRCCOPY);
220 
221  LeaveCriticalSection(&CriticalSection);
222  //DeleteDC(hDCMem);
223  DeleteObject(hDCMem);
224 
225  EndPaint(hWnd, &ps);
226 
227  return true;
228 }
229 
235 void vpGDIRenderer::convert(const vpImage<vpRGBa> &I, HBITMAP& hBmp)
236 {
237  //get the image's width and height
238  unsigned int w = I.getWidth();
239  unsigned int h = I.getHeight();
240 
241  //each line of a HBITMAP needs to be word aligned
242  //we need padding if the width is an odd number
243  bool needPad = ((w%2) == 0) ? false : true;
244  unsigned int newW = w;
245 
246  //in case of padding, the new width is width+1
247  newW = (needPad) ? (w+1) : w;
248 
249  //allocate the buffer
250  unsigned char * imBuffer = new unsigned char[newW * h * 4];
251 
252  //if we need padding (width needs to be a multiple of 2)
253  if(needPad)
254  {
255  unsigned int j = 0;
256  for(unsigned int i=0, k=0 ; i<newW * h * 4; i+=4, k++)
257  {
258  //end of a line = padding = inserts 0s
259  if(j==w && needPad)
260  {
261  imBuffer[i+0] = 0;
262  imBuffer[i+1] = 0;
263  imBuffer[i+2] = 0;
264  imBuffer[i+3] = 0;
265  j = 0;
266  k --;
267  }
268  else
269  {
270  //RGBA -> BGRA
271  imBuffer[i+0] = I.bitmap[k].B;
272  imBuffer[i+1] = I.bitmap[k].G;
273  imBuffer[i+2] = I.bitmap[k].R;
274  imBuffer[i+3] = I.bitmap[k].A;
275  j++;
276  }
277  }
278  }
279  else
280  //Simple conversion (no padding)
281  {
282  for(unsigned int i=0, k=0 ; i<w * h * 4 ; i+=4, k++)
283  {
284  imBuffer[i+0] = I.bitmap[k].B;
285  imBuffer[i+1] = I.bitmap[k].G;
286  imBuffer[i+2] = I.bitmap[k].R;
287  imBuffer[i+3] = I.bitmap[k].A;
288  }
289  }
290 
291  //updates the bitmap's pixel data
292  updateBitmap(hBmp,imBuffer, newW, h);
293 
294  //we don't need this buffer anymore
295  delete [] imBuffer;
296 }
297 
304 void vpGDIRenderer::convertROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, const unsigned int width, const unsigned int height)
305 {
306  //get the image's width and height
307  unsigned int w = width;
308  unsigned int h = height;
309 
310  //each line of a HBITMAP needs to be word aligned
311  //we need padding if the width is an odd number
312  bool needPad = ((w%2) == 0) ? false : true;
313  unsigned int newW = w;
314 
315  //in case of padding, the new width is width+1
316  newW = (needPad) ? (w+1) : w;
317 
318  //allocate the buffer
319  unsigned char * imBuffer = new unsigned char[newW * h * 4];
320 
321  vpRGBa* bitmap = I.bitmap;
322  unsigned int iwidth = I.getWidth();
323  bitmap = bitmap + (int)(iP.get_i()*iwidth+ iP.get_j());
324 
325  //if we need padding (width needs to be a multiple of 2)
326  if(needPad)
327  {
328  unsigned int j = 0;
329  unsigned int k = 0;
330  for(unsigned int i=0 ; i<newW * h * 4; i+=4)
331  {
332  //end of a line = padding = inserts 0s
333  if(j==w && needPad)
334  {
335  imBuffer[i+0] = 0;
336  imBuffer[i+1] = 0;
337  imBuffer[i+2] = 0;
338  imBuffer[i+3] = 0;
339  j = 0;
340  }
341  else
342  {
343  //RGBA -> BGRA
344  imBuffer[i+0] = (bitmap+k)->B;
345  imBuffer[i+1] = (bitmap+k)->G;
346  imBuffer[i+2] = (bitmap+k)->R;
347  imBuffer[i+3] = (bitmap+k)->A;
348  //bitmap++;
349  j++;
350  k++;
351  }
352  if (k == newW)
353  {
354  bitmap = bitmap+iwidth;
355  k = 0;
356  }
357  }
358  }
359  else
360  //Simple conversion (no padding)
361  {
362  unsigned int k = 0;
363  for (unsigned int i=0 ; i < w * h * 4 ; i+=4)
364  {
365  imBuffer[i+0] = (bitmap+k)->B;
366  imBuffer[i+1] = (bitmap+k)->G;
367  imBuffer[i+2] = (bitmap+k)->R;
368  imBuffer[i+3] = (bitmap+k)->A;
369  //bitmap++;
370  k++;
371  if (k == newW)
372  {
373  bitmap = bitmap+iwidth;
374  k = 0;
375  }
376  }
377  }
378 
379  //updates the bitmap's pixel data
380  updateBitmapROI(imBuffer,iP, newW, h);
381 
382  //we don't need this buffer anymore
383  delete [] imBuffer;
384 }
385 
386 
392 void vpGDIRenderer::convert(const vpImage<unsigned char> &I, HBITMAP& hBmp)
393 {
394  //get the image's width and height
395  unsigned int w = I.getWidth();
396  unsigned int h = I.getHeight();
397 
398  //each line of a HBITMAP needs to be word aligned
399  //we need padding if the width is an odd number
400  bool needPad = ((w%2) == 0) ? false : true;
401  unsigned int newW = w;
402 
403  //in case of padding, the new width is width+1
404  newW = (needPad) ? (w+1) : w;
405 
406  //allocate the buffer
407  unsigned char * imBuffer = new unsigned char[newW * h * 4];
408 
409  //if we need padding
410  if(needPad)
411  {
412  unsigned int j = 0;
413  for(unsigned int i=0, k=0 ; i<newW * h * 4; i+=4, k++)
414  {
415  //end of a line = padding = inserts 0s
416  if(j==w && needPad)
417  {
418  imBuffer[i+0] = 0;
419  imBuffer[i+1] = 0;
420  imBuffer[i+2] = 0;
421  imBuffer[i+3] = 0;
422  j = 0;
423  k --;
424  }
425  else
426  {
427  imBuffer[i+0] = I.bitmap[k];
428  imBuffer[i+1] = I.bitmap[k];
429  imBuffer[i+2] = I.bitmap[k];
430  imBuffer[i+3] = I.bitmap[k];
431  j++;
432  }
433  }
434  }
435  else
436  //Simple conversion
437  {
438  for(unsigned int i=0, k=0 ; i<w * h * 4 ; i+=4, k++)
439  {
440  imBuffer[i+0] = I.bitmap[k];
441  imBuffer[i+1] = I.bitmap[k];
442  imBuffer[i+2] = I.bitmap[k];
443  imBuffer[i+3] = I.bitmap[k];
444  }
445  }
446 
447  //updates the bitmap's pixel data
448  updateBitmap(hBmp,imBuffer, newW, h);
449 
450  //we don't need this buffer anymore
451  delete [] imBuffer;
452 }
453 
454 
461 void vpGDIRenderer::convertROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, const unsigned int width, const unsigned int height)
462 {
463  //get the image's width and height
464  unsigned int w = width;
465  unsigned int h = height;
466 
467  //each line of a HBITMAP needs to be word aligned
468  //we need padding if the width is an odd number
469  bool needPad = ((w%2) == 0) ? false : true;
470  unsigned int newW = w;
471 
472  //in case of padding, the new width is width+1
473  newW = (needPad) ? (w+1) : w;
474 
475  //allocate the buffer
476  unsigned char * imBuffer = new unsigned char[newW * h * 4];
477 
478  unsigned char* bitmap = I.bitmap;
479  unsigned int iwidth = I.getWidth();
480  bitmap = bitmap + (int)(iP.get_i()*iwidth+ iP.get_j());
481 
482  //if we need padding (width needs to be a multiple of 2)
483  if(needPad)
484  {
485  unsigned int j = 0;
486  unsigned int k = 0;
487  for(unsigned int i=0 ; i<newW * h * 4; i+=4)
488  {
489  //end of a line = padding = inserts 0s
490  if(j==w && needPad)
491  {
492  imBuffer[i+0] = 0;
493  imBuffer[i+1] = 0;
494  imBuffer[i+2] = 0;
495  imBuffer[i+3] = 0;
496  j = 0;
497  }
498  else
499  {
500  //RGBA -> BGRA
501  imBuffer[i+0] = *(bitmap+k);
502  imBuffer[i+1] = *(bitmap+k);
503  imBuffer[i+2] = *(bitmap+k);
504  imBuffer[i+3] = *(bitmap+k);
505  //bitmap++;
506  j++;
507  k++;
508  }
509  if (k == newW)
510  {
511  bitmap = bitmap+iwidth;
512  k = 0;
513  }
514  }
515  }
516  else
517  //Simple conversion (no padding)
518  {
519  unsigned int k = 0;
520  for (unsigned int i=0 ; i < w * h * 4 ; i+=4)
521  {
522  imBuffer[i+0] = *(bitmap+k);
523  imBuffer[i+1] = *(bitmap+k);
524  imBuffer[i+2] = *(bitmap+k);
525  imBuffer[i+3] = *(bitmap+k);
526  //bitmap++;
527  k++;
528  if (k == newW)
529  {
530  bitmap = bitmap+iwidth;
531  k = 0;
532  }
533  }
534  }
535 
536  //updates the bitmap's pixel data
537  updateBitmapROI(imBuffer,iP, newW, h);
538 
539  //we don't need this buffer anymore
540  delete [] imBuffer;
541 }
542 
553 bool vpGDIRenderer::updateBitmap(HBITMAP& hBmp, unsigned char * imBuffer,
554  unsigned int w, unsigned int h)
555 {
556  //the bitmap may only be accessed by one thread at the same time
557  //that's why we enter critical section
558  EnterCriticalSection(&CriticalSection);
559 
560  //if the existing bitmap object is of the right size
561  if( (nbCols==w) && (nbRows==h) )
562  {
563  //just replace the content
564  SetBitmapBits(hBmp, w * h * 4, imBuffer);
565  }
566  else
567  {
568  if(hBmp != NULL)
569  {
570  //delete the old BITMAP
571  DeleteObject(hBmp);
572  }
573  //create a new BITMAP from this buffer
574  if( (hBmp = CreateBitmap(static_cast<int>(w),static_cast<int>(h),
575  1,32,(void*)imBuffer)) == NULL)
576  return false;
577  }
578 
579  LeaveCriticalSection(&CriticalSection);
580  return true;
581 }
582 
583 
594 bool vpGDIRenderer::updateBitmapROI(unsigned char * imBuffer, const vpImagePoint &iP,
595  unsigned int w, unsigned int h)
596 {
597  int w_ = static_cast<int>(w);
598  int h_ = static_cast<int>(h);
599  HBITMAP htmp = CreateBitmap(w_,h_,1,32,(void*)imBuffer);
600 
601  //get the window's DC
602  HDC hDCScreen = GetDC(hWnd);
603  HDC hDCMem = CreateCompatibleDC(hDCScreen);
604  HDC hDCMem2 = CreateCompatibleDC(hDCScreen);
605 
606  //select this bmp in memory
607  EnterCriticalSection(&CriticalSection);
608  SelectObject(hDCMem, bmp);
609  SelectObject(hDCMem2, htmp);
610 
611  BitBlt(hDCMem,(int)iP.get_u(),(int)iP.get_v(),w_,h_, hDCMem2, 0, 0,SRCCOPY);
612  LeaveCriticalSection(&CriticalSection);
613 
614  DeleteDC(hDCMem);
615  ReleaseDC(hWnd, hDCScreen);
616  DeleteObject(htmp);
617 
618  return true;
619 }
620 
627 void vpGDIRenderer::setPixel(const vpImagePoint &iP,
628  const vpColor &color)
629 {
630  //get the window's DC
631  HDC hDCScreen = GetDC(hWnd);
632  HDC hDCMem = CreateCompatibleDC(hDCScreen);
633 
634  //select this bmp in memory
635  EnterCriticalSection(&CriticalSection);
636  SelectObject(hDCMem, bmp);
637 
638  if (color.id < vpColor::id_unknown)
639  SetPixel(hDCMem, vpMath::round(iP.get_u()), vpMath::round(iP.get_v()),
640  colors[color.id]);
641  else {
642  COLORREF gdicolor = RGB(color.R, color.G, color.B);
643  SetPixel(hDCMem, vpMath::round(iP.get_u()), vpMath::round(iP.get_v()),
644  gdicolor);
645  }
646  //display the result (flush)
647  // BitBlt(hDCScreen, x, y, 1, 1, hDCMem, x, y, SRCCOPY);
648 
649  LeaveCriticalSection(&CriticalSection);
650 
651  DeleteDC(hDCMem);
652  ReleaseDC(hWnd, hDCScreen);
653 }
654 
662 void vpGDIRenderer::drawLine(const vpImagePoint &ip1,
663  const vpImagePoint &ip2,
664  const vpColor &color,
665  unsigned int thickness, int style)
666 {
667  HDC hDCScreen= NULL, hDCMem = NULL;
668  HPEN hPen = NULL;
669 #ifdef GDI_ROBUST
670  double start = vpTime::measureTimeMs();
671  while(vpTime::measureTimeMs()-start<1000){
672  hDCScreen = GetDC(hWnd);
673  if(!hDCScreen) continue;
674  hDCMem = CreateCompatibleDC(hDCScreen);
675  if(!hDCMem){
676  ReleaseDC(hWnd, hDCScreen);
677  continue;
678  }
679 
680  //create the pen
681  if (color.id < vpColor::id_unknown)
682  hPen = CreatePen(style, static_cast<int>(thickness), colors[color.id]);
683  else {
684  COLORREF gdicolor = RGB(color.R, color.G, color.B);
685  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
686  }
687  if(!hPen){
688  DeleteDC(hDCMem);
689  ReleaseDC(hWnd, hDCScreen);
690  continue;
691  }
692  if(!SetBkMode(hDCMem, TRANSPARENT)){
693  DeleteObject(hPen);
694  DeleteDC(hDCMem);
695  ReleaseDC(hWnd, hDCScreen);
696  continue;
697  }
698 
699  //select this bmp in memory
700  EnterCriticalSection(&CriticalSection);
701 
702  if(!SelectObject(hDCMem, bmp)){
703  LeaveCriticalSection(&CriticalSection);
704  DeleteObject(hPen);
705  DeleteDC(hDCMem);
706  ReleaseDC(hWnd, hDCScreen);
707  continue;
708  }
709 
710  //select the pen
711  if(!SelectObject(hDCMem, hPen)){
712  LeaveCriticalSection(&CriticalSection);
713  DeleteObject(hPen);
714  DeleteDC(hDCMem);
715  ReleaseDC(hWnd, hDCScreen);
716  continue;
717  }
718  break;
719  }
720  timelost+=(vpTime::measureTimeMs()-start);
721 #else
722  //get the window's DC
723  hDCScreen = GetDC(hWnd);
724  hDCMem = CreateCompatibleDC(hDCScreen);
725 
726  //create the pen
727  if (color.id < vpColor::id_unknown)
728  hPen = CreatePen(style, static_cast<int>(thickness), colors[color.id]);
729  else {
730  COLORREF gdicolor = RGB(color.R, color.G, color.B);
731  hPen = CreatePen(style, static_cast<int>(thickness), gdicolor);
732  }
733  SetBkMode(hDCMem, TRANSPARENT);
734 
735  //select this bmp in memory
736  EnterCriticalSection(&CriticalSection);
737  SelectObject(hDCMem, bmp);
738 
739  //select the pen
740  SelectObject(hDCMem, hPen);
741 #endif
742  //move to the starting point
743  MoveToEx(hDCMem, vpMath::round(ip1.get_u()), vpMath::round(ip1.get_v()), NULL);
744  //Draw the line
745  LineTo(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()));
746 
747  //computes the coordinates of the rectangle to blit
748 // int x = (j2 >= j1) ? j1 : j2;
749 // int y = (i2 >= i1) ? i1 : i2;
750 // int w = (j2 >= j1) ? j2-j1 : j1-j2;
751 // int h = (i2 >= i1) ? i2-i1 : i1-i2;
752 
753  //display the result (flush)
754  // BitBlt(hDCScreen, x, y, w, h, hDCMem, x, y, SRCCOPY);
755 
756  LeaveCriticalSection(&CriticalSection);
757 
758  DeleteObject(hPen);
759  DeleteDC(hDCMem);
760  ReleaseDC(hWnd, hDCScreen);
761 
762 }
763 
773 void vpGDIRenderer::drawRect(const vpImagePoint &topLeft,
774  unsigned int width, unsigned int height,
775  const vpColor &color, bool fill,
776  unsigned int thickness)
777 {
778  if (thickness == 0) thickness = 1;
779  //get the window's DC
780  HDC hDCScreen = GetDC(hWnd);
781  HDC hDCMem = CreateCompatibleDC(hDCScreen);
782 
783  //create the pen
784  HPEN hPen;
785  COLORREF gdicolor = RGB(0,0,0);
786 
787  if (color.id < vpColor::id_unknown)
788  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
789  else {
790  gdicolor = RGB(color.R, color.G, color.B);
791  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
792  }
793 
794  //create an hollow or solid brush (depends on boolean fill)
795  LOGBRUSH lBrush;
796  if(fill) {
797  lBrush.lbStyle = BS_SOLID;
798  if (color.id < vpColor::id_unknown)
799  lBrush.lbColor = colors[color.id];
800  else {
801  lBrush.lbColor = gdicolor;
802  }
803  }
804  else lBrush.lbStyle = BS_HOLLOW;
805  HBRUSH hbrush = CreateBrushIndirect(&lBrush);
806 
807  //select this bmp in memory
808  EnterCriticalSection(&CriticalSection);
809  SelectObject(hDCMem, bmp);
810 
811  //select the brush
812  SelectObject(hDCMem, hbrush);
813  //select the pen
814  SelectObject(hDCMem, hPen);
815 
816  //draw the rectangle
817  Rectangle(hDCMem, vpMath::round(topLeft.get_u()), vpMath::round(topLeft.get_v()),
818  vpMath::round(topLeft.get_u())+static_cast<int>(width),
819  vpMath::round(topLeft.get_v())+static_cast<int>(height));
820 
821  //display the result (flush)
822 // BitBlt(hDCScreen, j, i, width, height, hDCMem, j, i, SRCCOPY);
823 
824  LeaveCriticalSection(&CriticalSection);
825 
826  DeleteObject(hbrush);
827  DeleteObject(hPen);
828  DeleteDC(hDCMem);
829  ReleaseDC(hWnd, hDCScreen);
830 
831 }
832 
837 void vpGDIRenderer::clear(const vpColor &color)
838 {
839  vpImagePoint ip;
840  ip.set_i(0);
841  ip.set_j(0);
842  drawRect(ip, nbCols, nbRows, color, true, 0);
843 }
844 
845 
854 void vpGDIRenderer::drawCircle(const vpImagePoint &center, unsigned int radius,
855  const vpColor &color, bool fill, unsigned int thickness)
856 {
857 
858  //get the window's DC
859  HDC hDCScreen = GetDC(hWnd);
860  HDC hDCMem = CreateCompatibleDC(hDCScreen);
861 
862  //create the pen
863  HPEN hPen;
864  if (color.id < vpColor::id_unknown)
865  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
866  else {
867  COLORREF gdicolor = RGB(color.R, color.G, color.B);
868  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
869  }
870 
871  //create an hollow brush
872  LOGBRUSH lBrush;
873  lBrush.lbStyle = BS_HOLLOW;
874  HBRUSH hbrush = CreateBrushIndirect(&lBrush);
875 
876  //computes bounding rectangle
877  int radius_ = static_cast<int>(radius);
878  int x1 = vpMath::round(center.get_u())-radius_;
879  int y1 = vpMath::round(center.get_v())-radius_;
880  int x2 = vpMath::round(center.get_u())+radius_;
881  int y2 = vpMath::round(center.get_v())+radius_;
882 
883  //select this bmp in memory
884  EnterCriticalSection(&CriticalSection);
885  SelectObject(hDCMem, bmp);
886 
887  //select the brush
888  SelectObject(hDCMem, hbrush);
889  //select the pen
890  SelectObject(hDCMem, hPen);
891 
892  //draw the circle
893  if (fill==false)
894  Ellipse(hDCMem, x1, y1, x2, y2);
895 
896  else
897  {
898  while (x2-x1 > 0)
899  {
900  x1++;
901  x2--;
902  y1++;
903  y2--;
904  Ellipse(hDCMem, x1, y1, x2, y2);
905  }
906  }
907 
908  //display the result (flush)
909  // BitBlt(hDCScreen, x1, y1, x2-x1, y2-y1, hDCMem, x1, y1, SRCCOPY);
910 
911  LeaveCriticalSection(&CriticalSection);
912 
913  DeleteObject(hbrush);
914  DeleteObject(hPen);
915  DeleteDC(hDCMem);
916  ReleaseDC(hWnd, hDCScreen);
917 }
918 
919 
926 void vpGDIRenderer::drawText(const vpImagePoint &ip, const char * text,
927  const vpColor &color)
928 {
929  //get the window's DC
930  HDC hDCScreen = GetDC(hWnd);
931  HDC hDCMem = CreateCompatibleDC(hDCScreen);
932 
933  //select this bmp in memory
934  EnterCriticalSection(&CriticalSection);
935  SelectObject(hDCMem, bmp);
936 
937  //Select the font
938  SelectObject(hDCMem, hFont);
939 
940  //set the text color
941  if (color.id < vpColor::id_unknown)
942  SetTextColor(hDCMem, colors[color.id]);
943  else {
944  COLORREF gdicolor = RGB(color.R, color.G, color.B);
945  SetTextColor(hDCMem, gdicolor);
946  }
947 
948  //we don't use the bkColor
949  SetBkMode(hDCMem, TRANSPARENT);
950 
951  SIZE size;
952  int length = (int) strlen(text);
953 
954  //get the displayed string dimensions
955  GetTextExtentPoint32(hDCMem, text, length, &size);
956 
957  //displays the string
958  TextOut(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v()), text, length);
959 
960  //display the result (flush)
961  // BitBlt(hDCScreen, j, i, size.cx, size.cy, hDCMem, j, i, SRCCOPY);
962 
963  LeaveCriticalSection(&CriticalSection);
964 
965  DeleteDC(hDCMem);
966  ReleaseDC(hWnd, hDCScreen);
967 }
968 
969 
970 
978 void vpGDIRenderer::drawCross(const vpImagePoint &ip, unsigned int size,
979  const vpColor &color, unsigned int thickness)
980 {
981  /* unsigned */ int half_size = static_cast<int>( size/2 );
982 
983  // if half_size is equal to zero, nothing is displayed with the code
984  // just below. So, if half_size is equal to zero we just draw the
985  // pixel.
986  if (half_size) {
987  //get the window's DC
988  HDC hDCScreen = GetDC(hWnd);
989  HDC hDCMem = CreateCompatibleDC(hDCScreen);
990 
991  //create the pen
992  HPEN hPen;
993  if (color.id < vpColor::id_unknown)
994  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
995  else {
996  COLORREF gdicolor = RGB(color.R, color.G, color.B);
997  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
998  }
999 
1000  //select this bmp in memory
1001  EnterCriticalSection(&CriticalSection);
1002  SelectObject(hDCMem, bmp);
1003 
1004  //select the pen
1005  SelectObject(hDCMem, hPen);
1006 
1007  //move to the starting point
1008  MoveToEx(hDCMem, vpMath::round(ip.get_u())-half_size, vpMath::round(ip.get_v()), NULL);
1009  //Draw the first line (horizontal)
1010  LineTo(hDCMem, vpMath::round(ip.get_u())+half_size, vpMath::round(ip.get_v()));
1011 
1012  //move to the starting point
1013  MoveToEx(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v())-half_size, NULL);
1014  //Draw the second line (vertical)
1015  LineTo(hDCMem, vpMath::round(ip.get_u()), vpMath::round(ip.get_v())+half_size);
1016 
1017  //display the result (flush)
1018  // BitBlt(hDCScreen, j-(size/2), i-(size/2), size, size,
1019 // hDCMem, j-(size/2), i-(size/2), SRCCOPY);
1020 
1021  LeaveCriticalSection(&CriticalSection);
1022 
1023  DeleteObject(hPen);
1024  DeleteDC(hDCMem);
1025  ReleaseDC(hWnd, hDCScreen);
1026  }
1027  else {
1028  setPixel(ip, color);
1029  }
1030 
1031 
1032 }
1033 
1041 void vpGDIRenderer::drawArrow(const vpImagePoint &ip1,
1042  const vpImagePoint &ip2,
1043  const vpColor &color,
1044  unsigned int w,unsigned int h, unsigned int thickness)
1045 {
1046  double a = ip2.get_i() - ip1.get_i() ;
1047  double b = ip2.get_j() - ip1.get_j() ;
1048  double lg = sqrt(vpMath::sqr(a)+vpMath::sqr(b)) ;
1049 
1050  //computes the coordinates of the rectangle to blit later
1051 // unsigned int x = (j2 >= j1) ? j1 : j2;
1052 // unsigned int y = (i2 >= i1) ? i1 : i2;
1053 // unsigned int w = (j2 >= j1) ? j2-j1 : j1-j2;
1054 // unsigned int h = (i2 >= i1) ? i2-i1 : i1-i2;
1055 
1056  //get the window's DC
1057  HDC hDCScreen = GetDC(hWnd);
1058  HDC hDCMem = CreateCompatibleDC(hDCScreen);
1059 
1060  //create the pen
1061  HPEN hPen;
1062  if (color.id < vpColor::id_unknown)
1063  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), colors[color.id]);
1064  else {
1065  COLORREF gdicolor = RGB(color.R, color.G, color.B);
1066  hPen = CreatePen(PS_SOLID, static_cast<int>(thickness), gdicolor);
1067  }
1068 
1069  //select this bmp in memory
1070  EnterCriticalSection(&CriticalSection);
1071  SelectObject(hDCMem, bmp);
1072 
1073  //select the pen
1074  SelectObject(hDCMem, hPen);
1075 
1076 
1077  if ((a==0)&&(b==0))
1078  {
1079  // DisplayCrossLarge(i1,j1,3,col) ;
1080  }
1081  else
1082  {
1083  a /= lg ;
1084  b /= lg ;
1085 
1086  vpImagePoint ip3;
1087  ip3.set_i( ip2.get_i() - w*a );
1088  ip3.set_j( ip2.get_j() - w*b );
1089 
1090 
1091  vpImagePoint ip4;
1092 
1093  //double t = 0 ;
1094  //while (t<=_l)
1095  {
1096  ip4.set_i( ip3.get_i() - b*h );
1097  ip4.set_j( ip3.get_j() + a*h );
1098 
1099  if (lg > 2*vpImagePoint::distance(ip2, ip4) ) {
1100  MoveToEx(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()), NULL);
1101  LineTo(hDCMem, vpMath::round(ip4.get_u()), vpMath::round(ip4.get_v()));
1102  }
1103  // t+=0.1 ;
1104  }
1105 
1106  //t = 0 ;
1107  //while (t>= -_l)
1108  {
1109  ip4.set_i( ip3.get_i() + b*h );
1110  ip4.set_j( ip3.get_j() - a*h );
1111 
1112  if (lg > 2*vpImagePoint::distance(ip2, ip4) ) {
1113  MoveToEx(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()), NULL);
1114  LineTo(hDCMem, vpMath::round(ip4.get_u()), vpMath::round(ip4.get_v()));
1115  }
1116 
1117  // t-=0.1 ;
1118  }
1119  MoveToEx(hDCMem, vpMath::round(ip1.get_u()), vpMath::round(ip1.get_v()), NULL);
1120  LineTo(hDCMem, vpMath::round(ip2.get_u()), vpMath::round(ip2.get_v()));
1121 
1122  }
1123 
1124 
1125  //display the result (flush)
1126 // BitBlt(hDCScreen, x, y, w, h, hDCMem, x, y, SRCCOPY);
1127 
1128  LeaveCriticalSection(&CriticalSection);
1129 
1130  DeleteObject(hPen);
1131  DeleteDC(hDCMem);
1132  ReleaseDC(hWnd, hDCScreen);
1133 }
1134 
1139 void vpGDIRenderer::getImage(vpImage<vpRGBa> &I)
1140 {
1141  //size of image buffer : nbCols*nbRows*4
1142  unsigned int size = nbCols*nbRows*4;
1143  unsigned char * imBuffer = new unsigned char[size];
1144 
1145  //gets the hbitmap's bitmap
1146  GetBitmapBits(bmp, static_cast<LONG>(size), (void *)imBuffer);
1147 
1148  //resize the destination image as needed
1149  I.resize(nbRows, nbCols);
1150 
1151  //copy the content
1152  for(unsigned int i=0 ; i<size ; i+=4)
1153  {
1154  I.bitmap[i>>2].R = imBuffer[i+2];
1155  I.bitmap[i>>2].G = imBuffer[i+1];
1156  I.bitmap[i>>2].B = imBuffer[i+0];
1157  I.bitmap[i>>2].A = 0xFF; //255 = maximum opacity
1158  }
1159 
1160  delete [] imBuffer;
1161 }
1162 #endif
1163 #endif
double get_v() const
Definition: vpImagePoint.h:264
double get_i() const
Definition: vpImagePoint.h:195
unsigned int getWidth() const
Definition: vpImage.h:161
unsigned char B
Blue component.
Definition: vpRGBa.h:148
Type * bitmap
points toward the bitmap
Definition: vpImage.h:120
static const vpColor black
Definition: vpColor.h:161
static const vpColor darkRed
Definition: vpColor.h:168
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
double get_u() const
Definition: vpImagePoint.h:253
static const vpColor lightGray
Definition: vpColor.h:163
static double measureTimeMs()
Definition: vpTime.cpp:86
static const vpColor darkBlue
Definition: vpColor.h:174
unsigned char G
Green component.
Definition: vpRGBa.h:147
static const vpColor green
Definition: vpColor.h:170
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:206
static const vpColor lightRed
Definition: vpColor.h:166
Class that defines a RGB 32 bits structure.
Definition: vpRGBa.h:68
static const vpColor red
Definition: vpColor.h:167
static const vpColor orange
Definition: vpColor.h:177
vpColorIdentifier id
Definition: vpColor.h:156
void set_i(const double ii)
Definition: vpImagePoint.h:159
static const vpColor cyan
Definition: vpColor.h:176
static const vpColor lightGreen
Definition: vpColor.h:169
static double sqr(double x)
Definition: vpMath.h:106
unsigned char A
Additionnal component.
Definition: vpRGBa.h:149
void resize(const unsigned int h, const unsigned int w)
set the size of the image without initializing it.
Definition: vpImage.h:536
static const vpColor gray
Definition: vpColor.h:164
static const vpColor darkGray
Definition: vpColor.h:165
void set_j(const double jj)
Definition: vpImagePoint.h:170
Error that can be emited by the vpDisplay class and its derivates.
unsigned char R
Red component.
Definition: vpRGBa.h:146
unsigned int getHeight() const
Definition: vpImage.h:152
static const vpColor darkGreen
Definition: vpColor.h:171
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:93
static const vpColor yellow
Definition: vpColor.h:175
static const vpColor lightBlue
Definition: vpColor.h:172
static const vpColor purple
Definition: vpColor.h:178
static const vpColor white
Definition: vpColor.h:162
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
Definition: vpImagePoint.h:275
static const vpColor blue
Definition: vpColor.h:173