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