MRPT  2.0.2
CCanvas.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "img-precomp.h" // Precompiled headers
11 
13 #include <mrpt/core/round.h>
14 #include <mrpt/img/CCanvas.h>
15 #include <mrpt/img/CImage.h>
16 #include <mrpt/io/zip.h>
17 #include <mrpt/math/CMatrixFixed.h>
18 #include <mrpt/system/os.h>
20 #include <Eigen/Dense>
21 #include <cstring> // memcpy
22 #include <map>
23 
24 // Include the MRPT bitmap fonts:
25 #include "mrpt_font_10x20.h"
26 #include "mrpt_font_5x7.h"
27 #include "mrpt_font_6x13.h"
28 #include "mrpt_font_6x13B.h"
29 #include "mrpt_font_6x13O.h"
30 #include "mrpt_font_9x15.h"
31 #include "mrpt_font_9x15B.h"
32 
33 // Japanese fonts?
34 #if MRPT_HAS_ASIAN_FONTS
35 #include "mrpt_font_18x18ja.h"
36 #endif
37 
38 // Each font has a block a data with this header (It's actually zip-compressed
39 // since mrpt >0.6.5)
40 // const uint32_t mrpt_font_9x15B [] = {
41 // 9,15, /* width, height */
42 // 0x0000,0x00FF, /* UNICODE characters range: */
43 
44 using namespace mrpt;
45 using namespace mrpt::img;
46 using namespace std;
47 
48 struct FontData
49 {
50  std::vector<uint8_t> data;
51  bool prepared_to_big_endian = false;
52 };
53 
54 // Each vector is the target place where to uncompress each font.
55 map<string, FontData> list_registered_fonts;
56 bool list_fonts_init = false;
57 
59 {
60  if (!list_fonts_init)
61  {
62  list_registered_fonts.clear();
63 
64 // This was used only once
65 #if 0
66 #define SAVE_COMPRESSED(ARR) \
67  { \
68  list_registered_fonts[#ARR].resize(sizeof(mrpt_font_##ARR)); \
69  memcpy( \
70  &list_registered_fonts[#ARR][0], mrpt_font_##ARR, \
71  sizeof(mrpt_font_##ARR)); \
72  cout << #ARR << " -> " << sizeof(mrpt_font_##ARR) << endl; \
73  CFileGZOutputStream f( \
74  string("mrpt_font_") + string(#ARR) + string(".gz")); \
75  f.WriteBuffer(mrpt_font_##ARR, sizeof(mrpt_font_##ARR)); \
76  /*mrpt::compress::zip::compress( list_registered_fonts[#ARR], f ); */ \
77  }
78 
79  SAVE_COMPRESSED(5x7)
80 // SAVE_COMPRESSED(6x13)
81 // SAVE_COMPRESSED(6x13B)
82 // SAVE_COMPRESSED(6x13O)
83 // SAVE_COMPRESSED(9x15)
84 // SAVE_COMPRESSED(9x15B)
85 // SAVE_COMPRESSED(10x20)
86 
87 #if MRPT_HAS_ASIAN_FONTS
88 // SAVE_COMPRESSED(18x18ja)
89 #endif
90 
91 #endif
92 
93 #if 1 // Normal operation: Load fonts and uncompress them:
94 
95 #define LOAD_FONT(FONTNAME) \
96  { \
97  std::vector<uint8_t> tmpBuf(sizeof(mrpt_font_gz_##FONTNAME)); \
98  memcpy( \
99  &tmpBuf[0], mrpt_font_gz_##FONTNAME, \
100  sizeof(mrpt_font_gz_##FONTNAME)); \
101  mrpt::io::zip::decompress_gz_data_block( \
102  tmpBuf, list_registered_fonts[#FONTNAME].data); \
103  }
104 
105  LOAD_FONT(5x7)
106  LOAD_FONT(6x13)
107  LOAD_FONT(6x13B)
108  LOAD_FONT(6x13O)
109  LOAD_FONT(9x15)
110  LOAD_FONT(9x15B)
111  LOAD_FONT(10x20)
112 #if MRPT_HAS_ASIAN_FONTS
113  LOAD_FONT(18x18ja)
114 #endif
115 
116 #endif
117 
118  list_fonts_init = true;
119  }
120 }
121 
122 /*---------------------------------------------------------------
123  line
124 ---------------------------------------------------------------*/
126  int x0, int y0, int x1, int y1, const mrpt::img::TColor color,
127  [[maybe_unused]] unsigned int width, [[maybe_unused]] TPenStyle penStyle)
128 {
129  float x, y;
130 
131  auto Ax = (float)(x1 - x0);
132  auto Ay = (float)(y1 - y0);
133 
134  // In this cases, there is nothing to do!
135  if (Ax == 0 && Ay == 0) return;
136  if (x0 < 0 && x1 < 0) return;
137  if (y0 < 0 && y1 < 0) return;
138  if (x0 >= (int)getWidth() && x1 >= (int)getWidth()) return;
139  if (y0 >= (int)getHeight() && y1 >= (int)getHeight()) return;
140 
141  float dist = sqrt(square(Ax) + square(Ay));
142  int i, N = (int)ceil(dist);
143 
144  // The N steps to perform next:
145  Ax /= N;
146  Ay /= N;
147  x = (float)x0;
148  y = (float)y0;
149 
150  for (i = 0; i < N; i++)
151  {
152  x += Ax;
153  y += Ay;
154  setPixel((int)x, (int)y, color);
155  } // end for i
156 }
157 
158 /*---------------------------------------------------------------
159  rectangle
160 ---------------------------------------------------------------*/
162  int x0, int y0, int x1, int y1, const mrpt::img::TColor color,
163  unsigned int width)
164 {
165  int w_min = (int)-ceil(((float)width) / 2);
166  int w_max = (int)floor(((float)width) / 2);
167  // Draw "width" rectangles one into another:
168  for (int w = w_min; w <= w_max; w++)
169  {
170  line(x0 - w, y0 - w, x1 + w, y0 - w, color);
171  line(x1 + w, y0 - w, x1 + w, y1 + w, color);
172  line(x1 + w, y1 + w, x0 - w, y1 + w, color);
173  line(x0 - w, y1 + w, x0 - w, y0 - w, color);
174  } // end for "w"
175 }
176 
177 /*****************************************************AJOGD***************************************************/
178 /*---------------------------------------------------------------
179  triangle
180 ---------------------------------------------------------------*/
182  int x0, int y0, int size, const mrpt::img::TColor color, bool inferior,
183  unsigned int width)
184 {
185  int ts = round(0.866 * size);
186  int tc = round(0.5 * size);
187  if (inferior)
188  {
189  line(x0, y0 + size, x0 + ts, y0 - tc, color, width);
190  line(x0, y0 + size, x0 - ts, y0 - tc, color, width);
191  line(x0 + ts, y0 - tc, x0 - ts, y0 - tc, color, width);
192  }
193  else
194  {
195  line(x0, y0 - size, x0 + ts, y0 + tc, color, width);
196  line(x0, y0 - size, x0 - ts, y0 + tc, color, width);
197  line(x0 + ts, y0 + tc, x0 - ts, y0 + tc, color, width);
198  }
199 }
200 /************************************************************************************************************/
201 
202 /*---------------------------------------------------------------
203  filledRectangle
204 ---------------------------------------------------------------*/
206  int x0, int y0, int x1, int y1, const mrpt::img::TColor color)
207 {
208  int x_min = max(x0, 0);
209  int x_max = min(x1, (int)getWidth() - 1);
210  int y_min = max(y0, 0);
211  int y_max = min(y1, (int)getHeight() - 1);
212 
213  for (int y = y_min; y <= y_max; y++)
214  for (int x = x_min; x <= x_max; x++) setPixel(x, y, color);
215 }
216 
217 /*---------------------------------------------------------------
218  selectTextFont
219 ---------------------------------------------------------------*/
220 void CCanvas::selectTextFont(const std::string& fontName)
221 {
222  init_fonts_list();
223 
224  // Assure list name is in the list:
225  auto it = list_registered_fonts.find(fontName);
226  if (it == list_registered_fonts.end())
227  {
228  // Error
229  cerr << "[CCanvas::selectTextFont] Warning: Unknown font: " << fontName
230  << endl;
231  return;
232  }
233  else
234  {
235  FontData& fd = it->second;
236  m_selectedFontBitmaps = reinterpret_cast<const uint32_t*>(&fd.data[0]);
237  m_selectedFont = fontName;
238 
239 #if MRPT_IS_BIG_ENDIAN
240  // Fix endianness of char tables:
241  if (!fd.prepared_to_big_endian)
242  {
243  fd.prepared_to_big_endian = true; // Only do once
244  uint32_t* ptr = reinterpret_cast<uint32_t*>(&fd.data[0]);
245  for (size_t i = 0; i < fd.data.size() / sizeof(uint32_t); i++)
247  }
248 #endif
249  }
250 }
251 
252 /*---------------------------------------------------------------
253  drawImage
254 ---------------------------------------------------------------*/
255 void CCanvas::drawImage(int x, int y, const mrpt::img::CImage& img)
256 {
257  MRPT_START
259 
260  int img_lx = img.getWidth();
261  int img_ly = img.getHeight();
262 
263  if (img.isColor())
264  {
265  for (int xx = 0; xx < img_lx; xx++)
266  for (int yy = 0; yy < img_ly; yy++)
267  {
268  auto ptr = img(xx, yy);
269  const int p = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16);
270  setPixel(x + xx, y + yy, p);
271  }
272  }
273  else
274  {
275  unsigned char c;
276  int col;
277  for (int xx = 0; xx < img_lx; xx++)
278  for (int yy = 0; yy < img_ly; yy++)
279  {
280  c = *((unsigned char*)img(xx, yy));
281  col = c | (c << 8) | (c << 16);
282  setPixel(x + xx, y + yy, col);
283  }
284  }
285 
286  MRPT_END
287 }
288 
289 /*---------------------------------------------------------------
290  drawImage
291 ---------------------------------------------------------------*/
292 void CCanvas::drawImage(
293  [[maybe_unused]] int x, [[maybe_unused]] int y,
294  [[maybe_unused]] const mrpt::img::CImage& img,
295  [[maybe_unused]] float rotation, [[maybe_unused]] float scale)
296 {
297  MRPT_START
298 
299  THROW_EXCEPTION("Not implemented yet!! Try yourself! ;-)");
300 
301  MRPT_END
302 }
303 
305  int x0, int y0, const mrpt::img::TColor color, char type, int size,
306  unsigned int width)
307 {
308  switch (type)
309  {
310  case '+':
311  line(x0 - size, y0, x0 + size, y0, color, width);
312  line(x0, y0 - size, x0, y0 + size, color, width);
313  break;
314  case 's':
315  line(x0 - size, y0 - size, x0 + size, y0 - size, color, width);
316  line(x0 + size, y0 - size, x0 + size, y0 + size, color, width);
317  line(x0 - size, y0 + size, x0 + size, y0 + size, color, width);
318  line(x0 - size, y0 - size, x0 - size, y0 + size, color, width);
319  break;
320  case 'x':
321  line(x0 - size, y0 - size, x0 + size, y0 + size, color, width);
322  line(x0 + size, y0 - size, x0 - size, y0 + size, color, width);
323  break;
324  case ':':
325  line(x0 - size, y0, x0 - 2, y0, color, width);
326  line(x0 + 2, y0, x0 + size, y0, color, width);
327  line(x0, y0 - size, x0, y0 - 2, color, width);
328  line(x0, y0 + 2, x0, y0 + size, color, width);
329  break;
330  default:
331  THROW_EXCEPTION("Unexpected 'type' of cross to be drawn");
332  }
333 }
334 
335 /*---------------------------------------------------------------
336  drawCircle
337 ---------------------------------------------------------------*/
339  int x, int y, int radius, const mrpt::img::TColor& color,
340  unsigned int width)
341 {
342  if (radius < 0) radius = -radius;
343 
344  int nSegments;
345 
346  if (radius == 0)
347  {
348  nSegments = 2;
349  }
350  else
351  {
352  nSegments = int(M_2PI * radius);
353  }
354 
355  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
356  double ang, Aa = M_2PI / (nSegments - 1);
357  int i;
358 
359  for (i = 0, ang = 0; i < nSegments; i++, ang += Aa)
360  {
361  x2 = round(x + radius * cos(ang));
362  y2 = round(y + radius * sin(ang));
363 
364  if (i > 0) line(x1, y1, x2, y2, color, width);
365 
366  x1 = x2;
367  y1 = y2;
368  } // end for points on ellipse
369 }
370 
371 /*---------------------------------------------------------------
372  textOut
373 ---------------------------------------------------------------*/
375  int x0, int y0, const std::string& str, const mrpt::img::TColor color)
376 {
377  MRPT_START
378 
379  if (!m_selectedFontBitmaps) // First call: load fonts
380  this->selectTextFont("9x15");
381 
382  // Am I an image?
383  bool y_axis_reversed = false;
384  auto* im_image = dynamic_cast<CImage*>(this);
385  if (im_image) y_axis_reversed = !im_image->isOriginTopLeft();
386 
387  // Decode UNICODE string:
388  std::vector<uint16_t> uniStr;
389  mrpt::system::decodeUTF8(str, uniStr);
390 
391  int px = x0;
392  int py = y0;
393 
394  // Char size:
395  int char_w = m_selectedFontBitmaps[0];
396  int char_h = m_selectedFontBitmaps[1];
397 
398  for (unsigned short unichar : uniStr)
399  {
400  // look for the character in the table:
401  const uint32_t* table_ptr = m_selectedFontBitmaps + 2;
402  uint32_t charset_ini = table_ptr[0];
403  uint32_t charset_end = table_ptr[1];
404 
405  while (charset_end)
406  {
407  // Is in this range?
408  if (unichar <= charset_end && unichar >= charset_ini)
409  {
410  // Draw this character:
411  int pyy = y_axis_reversed ? (py + char_h - 1) : py;
412 
413  const uint32_t* char_bitmap =
414  table_ptr + 2 + char_h * (unichar - charset_ini);
415 
416  for (int y = 0; y < char_h;
417  y++, pyy += y_axis_reversed ? -1 : 1)
418  {
419  // Use memcpy() here since directly dereferencing is an
420  // invalid operation in architectures (S390X) where
421  // unaligned accesses are forbiden:
422  uint32_t row;
423  memcpy(&row, char_bitmap, sizeof(row));
424  char_bitmap++;
425  for (int x = 0, pxx = px; x < char_w; x++, pxx++)
426  if (!!(row & (1 << x))) setPixel(pxx, pyy, color);
427  }
428 
429  // Advance the raster cursor:
430  px += char_w;
431 
432  // Next char!
433  break;
434  }
435  else
436  {
437  // No: Move to the next block and keep searching:
438  uint32_t n_chars = charset_end - charset_ini + 1;
439  table_ptr += 2 /* Header */ + n_chars * char_h;
440 
441  // get new block header:
442  charset_ini = table_ptr[0];
443  charset_end = table_ptr[1];
444  }
445  }
446  // Char not in the font!
447  }
448 
449  MRPT_END
450 }
451 
453  const mrpt::math::CMatrixFixed<double, 2, 2>& cov2D, const double mean_x,
454  const double mean_y, double confIntervalStds,
455  const mrpt::img::TColor& color, unsigned int width, int nEllipsePoints)
456 {
457  MRPT_START
458  int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
459  double ang;
461  std::vector<double> eVals;
462  int i;
463 
464  // Compute the eigen-vectors & values:
465  cov2D.eig(eigVec, eVals);
466  eigVals.setDiagonal(eVals);
467 
468  eigVals.asEigen() = eigVals.array().sqrt().matrix();
469 
471  M.asEigen() = eigVals.asEigen() * eigVec.transpose();
472 
473  // Compute the points of the 2D ellipse:
474  for (i = 0, ang = 0; i < nEllipsePoints;
475  i++, ang += (M_2PI / (nEllipsePoints - 1)))
476  {
477  double ccos = cos(ang);
478  double ssin = sin(ang);
479 
480  x2 = round(
481  mean_x + confIntervalStds * (ccos * M(0, 0) + ssin * M(1, 0)));
482  y2 = round(
483  mean_y + confIntervalStds * (ccos * M(0, 1) + ssin * M(1, 1)));
484 
485  if (i > 0) line(x1, y1, x2, y2, color, width);
486 
487  x1 = x2;
488  y1 = y2;
489  } // end for points on ellipse
490 
491  MRPT_END_WITH_CLEAN_UP(std::cout << "Covariance matrix leading to error is:"
492  << std::endl
493  << cov2D << std::endl;);
494 }
bool eig(CMatrixFixed< T, ROWS, COLS > &eVecs, std::vector< T > &eVals, bool sorted=true) const
Computes the eigenvectors and eigenvalues for a square, general matrix.
virtual void drawCircle(int x, int y, int radius, const mrpt::img::TColor &color=mrpt::img::TColor(255, 255, 255), unsigned int width=1)
Draws a circle of a given radius.
Definition: CCanvas.cpp:338
A compile-time fixed-size numeric matrix container.
Definition: CMatrixFixed.h:33
#define MRPT_START
Definition: exceptions.h:241
TPenStyle
Definition of pen styles.
Definition: CCanvas.h:55
#define M_2PI
Definition: common.h:58
virtual void line(int x0, int y0, int x1, int y1, const mrpt::img::TColor color, unsigned int width=1, TPenStyle penStyle=psSolid)
Draws a line.
Definition: CCanvas.cpp:125
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:67
size_t size(const MATRIXLIKE &m, const int dim)
bool list_fonts_init
Definition: CCanvas.cpp:56
void decodeUTF8(const std::string &strUTF8, std::vector< uint16_t > &out_uniStr)
Decodes a UTF-8 string into an UNICODE string.
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:849
STL namespace.
#define MRPT_END_WITH_CLEAN_UP(stuff)
Definition: exceptions.h:247
void triangle(int x0, int y0, int size, const mrpt::img::TColor color, bool inferior=true, unsigned int width=1)
Draws a triangle.
Definition: CCanvas.cpp:181
void reverseBytesInPlace(bool &v_in_out)
Reverse the order of the bytes of a given type (useful for transforming btw little/big endian) ...
#define LOAD_FONT(FONTNAME)
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:120
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:818
virtual void selectTextFont(const std::string &fontName)
Select the current font used when drawing text.
Definition: CCanvas.cpp:220
virtual void filledRectangle(int x0, int y0, int x1, int y1, const mrpt::img::TColor color)
Draws a filled rectangle.
Definition: CCanvas.cpp:205
void rectangle(int x0, int y0, int x1, int y1, const mrpt::img::TColor color, unsigned int width=1)
Draws a rectangle (an empty rectangle, without filling)
Definition: CCanvas.cpp:161
map< string, FontData > list_registered_fonts
Definition: CCanvas.cpp:55
void ellipseGaussian(const mrpt::math::CMatrixFixed< double, 2, 2 > &cov2D, const double mean_x, const double mean_y, double confIntervalStds=2, const mrpt::img::TColor &color=mrpt::img::TColor(255, 255, 255), unsigned int width=1, int nEllipsePoints=20)
Draws an ellipse representing a given confidence interval of a 2D Gaussian distribution.
Definition: CCanvas.cpp:452
std::vector< uint8_t > data
Definition: CCanvas.cpp:50
void drawMark(int x0, int y0, const mrpt::img::TColor color, char type, int size=5, unsigned int width=1)
Draw a mark.
Definition: CCanvas.cpp:304
return_t square(const num_t x)
Inline function for the square of a number.
PixelDepth getPixelDepth() const
Definition: CImage.cpp:294
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool isColor() const
Returns true if the image is RGB, false if it is grayscale.
Definition: CImage.cpp:859
bool isOriginTopLeft() const
Returns true (as of MRPT v2.0.0, it&#39;s fixed)
Definition: CImage.cpp:888
void init_fonts_list()
Definition: CCanvas.cpp:58
bool prepared_to_big_endian
Definition: CCanvas.cpp:51
#define MRPT_END
Definition: exceptions.h:245
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
Definition: CMatrixFixed.h:251
virtual void textOut(int x0, int y0, const std::string &str, const mrpt::img::TColor color)
Renders 2D text using bitmap fonts.
Definition: CCanvas.cpp:374
virtual void drawImage(int x, int y, const mrpt::img::CImage &img)
Draws an image as a bitmap at a given position.
Definition: CCanvas.cpp:255
A RGB color - 8bit.
Definition: TColor.h:25
double getHeight(const TPolygon3D &p, const TPoint3D &c)
void setDiagonal(const std::size_t N, const T value)
Resize to NxN, set all entries to zero, except the main diagonal which is set to value ...
Definition: MatrixBase.h:34
A class for storing images as grayscale or RGB bitmaps.
Definition: img/CImage.h:148
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
int round(const T value)
Returns the closer integer (int) to x.
Definition: round.h:24



Page generated by Doxygen 1.8.14 for MRPT 2.0.2 Git: 9b4fd2465 Mon May 4 16:59:08 2020 +0200 at lun may 4 17:26:07 CEST 2020