MRPT  1.9.9
CImage_loadXPM.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 /*
10 
11 This file is partially based on source code of ImageMagick by John Cristy. Its
12 license is as follows:
13 
14 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15 % %
16 % %
17 % %
18 % X X PPPP M M %
19 % X X P P MM MM %
20 % X PPPP M M M %
21 % X X P M M %
22 % X X P M M %
23 % %
24 % %
25 % Read/Write ImageMagick Image Format. %
26 % %
27 % %
28 % Software Design %
29 % John Cristy %
30 % July 1992 %
31 % %
32 % %
33 % Copyright (C) 2001 ImageMagick Studio, a non-profit organization dedicated %
34 % to making software imaging solutions freely available. %
35 % %
36 % Permission is hereby granted, free of charge, to any person obtaining a %
37 % copy of this software and associated documentation files ("ImageMagick"), %
38 % to deal in ImageMagick without restriction, including without limitation %
39 % the rights to use, copy, modify, merge, publish, distribute, sublicense, %
40 % and/or sell copies of ImageMagick, and to permit persons to whom the %
41 % ImageMagick is furnished to do so, subject to the following conditions: %
42 % %
43 % The above copyright notice and this permission notice shall be included in %
44 % all copies or substantial portions of ImageMagick. %
45 % %
46 % The software is provided "as is", without warranty of any kind, express or %
47 % implied, including but not limited to the warranties of merchantability, %
48 % fitness for a particular purpose and noninfringement. In no event shall %
49 % ImageMagick Studio be liable for any claim, damages or other liability, %
50 % whether in an action of contract, tort or otherwise, arising from, out of %
51 % or in connection with ImageMagick or the use or other dealings in %
52 % ImageMagick. %
53 % %
54 % Except as contained in this notice, the name of the ImageMagick Studio %
55 % shall not be used in advertising or otherwise to promote the sale, use or %
56 % other dealings in ImageMagick without prior written authorization from the %
57 % ImageMagick Studio. %
58 % %
59 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60 %
61 %
62 */
63 
64 #include "img-precomp.h" // Precompiled headers
65 
66 #include <mrpt/img/CImage.h>
67 #include <mrpt/core/exceptions.h>
68 #include <unordered_map>
69 #include <string>
70 #include <cstring>
71 
72 #if MRPT_HAS_OPENCV
74 {
75  unsigned char R{0}, G{0}, B{0};
76 };
77 using XPMColorMap = std::unordered_map<std::string, XPMColorMapData>;
78 using Long2LongHash = std::unordered_map<int64_t, int64_t>;
79 
80 static const char* ParseColor(const char* data)
81 {
82  static const char* const targets[] = {"c ", "g ", "g4 ", "m ",
83  "b ", "s ", NULL};
84 
85  const char *p, *r;
86  const char* q;
87  for (int i = 0; targets[i] != NULL; i++)
88  {
89  r = data;
90  for (q = targets[i]; *r != '\0'; r++)
91  {
92  if (*r != *q) continue;
93  if (!isspace((int)(*(r - 1)))) continue;
94  p = r;
95  for (;;)
96  {
97  if (*q == '\0') return p;
98  if (*p++ != *q++) break;
99  }
100  q = targets[i];
101  }
102  }
103  return nullptr;
104 }
105 
106 /*****************************************************************************\
107 * rgbtab.h *
108 * *
109 * A hard coded rgb.txt. To keep it short I removed all colornames with *
110 * trailing numbers, Blue3 etc, except the GrayXX. Sorry Grey-lovers I prefer *
111 * Gray ;-). But Grey is recognized on lookups, only on save Gray will be *
112 * used, maybe you want to do some substitue there too. *
113 * *
114 * To save memory the RGBs are coded in one long value, as done by the RGB *
115 * macro. *
116 * *
117 * Developed by HeDu 3/94 (hedu@cul-ipn.uni-kiel.de) *
118 \*****************************************************************************/
119 
120 typedef struct
121 {
122  const char* name;
124 } rgbRecord;
125 
126 #define myRGB(r, g, b) ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b)
127 
128 static const rgbRecord theRGBRecords[] = {
129  {"aliceblue", myRGB(240, 248, 255)},
130  {"antiquewhite", myRGB(250, 235, 215)},
131  {"aquamarine", myRGB(50, 191, 193)},
132  {"azure", myRGB(240, 255, 255)},
133  {"beige", myRGB(245, 245, 220)},
134  {"bisque", myRGB(255, 228, 196)},
135  {"black", myRGB(0, 0, 0)},
136  {"blanchedalmond", myRGB(255, 235, 205)},
137  {"blue", myRGB(0, 0, 255)},
138  {"blueviolet", myRGB(138, 43, 226)},
139  {"brown", myRGB(165, 42, 42)},
140  {"burlywood", myRGB(222, 184, 135)},
141  {"cadetblue", myRGB(95, 146, 158)},
142  {"chartreuse", myRGB(127, 255, 0)},
143  {"chocolate", myRGB(210, 105, 30)},
144  {"coral", myRGB(255, 114, 86)},
145  {"cornflowerblue", myRGB(34, 34, 152)},
146  {"cornsilk", myRGB(255, 248, 220)},
147  {"cyan", myRGB(0, 255, 255)},
148  {"darkgoldenrod", myRGB(184, 134, 11)},
149  {"darkgreen", myRGB(0, 86, 45)},
150  {"darkkhaki", myRGB(189, 183, 107)},
151  {"darkolivegreen", myRGB(85, 86, 47)},
152  {"darkorange", myRGB(255, 140, 0)},
153  {"darkorchid", myRGB(139, 32, 139)},
154  {"darksalmon", myRGB(233, 150, 122)},
155  {"darkseagreen", myRGB(143, 188, 143)},
156  {"darkslateblue", myRGB(56, 75, 102)},
157  {"darkslategray", myRGB(47, 79, 79)},
158  {"darkturquoise", myRGB(0, 166, 166)},
159  {"darkviolet", myRGB(148, 0, 211)},
160  {"deeppink", myRGB(255, 20, 147)},
161  {"deepskyblue", myRGB(0, 191, 255)},
162  {"dimgray", myRGB(84, 84, 84)},
163  {"dodgerblue", myRGB(30, 144, 255)},
164  {"firebrick", myRGB(142, 35, 35)},
165  {"floralwhite", myRGB(255, 250, 240)},
166  {"forestgreen", myRGB(80, 159, 105)},
167  {"gainsboro", myRGB(220, 220, 220)},
168  {"ghostwhite", myRGB(248, 248, 255)},
169  {"gold", myRGB(218, 170, 0)},
170  {"goldenrod", myRGB(239, 223, 132)},
171  {"gray", myRGB(126, 126, 126)},
172  {"gray0", myRGB(0, 0, 0)},
173  {"gray1", myRGB(3, 3, 3)},
174  {"gray10", myRGB(26, 26, 26)},
175  {"gray100", myRGB(255, 255, 255)},
176  {"gray11", myRGB(28, 28, 28)},
177  {"gray12", myRGB(31, 31, 31)},
178  {"gray13", myRGB(33, 33, 33)},
179  {"gray14", myRGB(36, 36, 36)},
180  {"gray15", myRGB(38, 38, 38)},
181  {"gray16", myRGB(41, 41, 41)},
182  {"gray17", myRGB(43, 43, 43)},
183  {"gray18", myRGB(46, 46, 46)},
184  {"gray19", myRGB(48, 48, 48)},
185  {"gray2", myRGB(5, 5, 5)},
186  {"gray20", myRGB(51, 51, 51)},
187  {"gray21", myRGB(54, 54, 54)},
188  {"gray22", myRGB(56, 56, 56)},
189  {"gray23", myRGB(59, 59, 59)},
190  {"gray24", myRGB(61, 61, 61)},
191  {"gray25", myRGB(64, 64, 64)},
192  {"gray26", myRGB(66, 66, 66)},
193  {"gray27", myRGB(69, 69, 69)},
194  {"gray28", myRGB(71, 71, 71)},
195  {"gray29", myRGB(74, 74, 74)},
196  {"gray3", myRGB(8, 8, 8)},
197  {"gray30", myRGB(77, 77, 77)},
198  {"gray31", myRGB(79, 79, 79)},
199  {"gray32", myRGB(82, 82, 82)},
200  {"gray33", myRGB(84, 84, 84)},
201  {"gray34", myRGB(87, 87, 87)},
202  {"gray35", myRGB(89, 89, 89)},
203  {"gray36", myRGB(92, 92, 92)},
204  {"gray37", myRGB(94, 94, 94)},
205  {"gray38", myRGB(97, 97, 97)},
206  {"gray39", myRGB(99, 99, 99)},
207  {"gray4", myRGB(10, 10, 10)},
208  {"gray40", myRGB(102, 102, 102)},
209  {"gray41", myRGB(105, 105, 105)},
210  {"gray42", myRGB(107, 107, 107)},
211  {"gray43", myRGB(110, 110, 110)},
212  {"gray44", myRGB(112, 112, 112)},
213  {"gray45", myRGB(115, 115, 115)},
214  {"gray46", myRGB(117, 117, 117)},
215  {"gray47", myRGB(120, 120, 120)},
216  {"gray48", myRGB(122, 122, 122)},
217  {"gray49", myRGB(125, 125, 125)},
218  {"gray5", myRGB(13, 13, 13)},
219  {"gray50", myRGB(127, 127, 127)},
220  {"gray51", myRGB(130, 130, 130)},
221  {"gray52", myRGB(133, 133, 133)},
222  {"gray53", myRGB(135, 135, 135)},
223  {"gray54", myRGB(138, 138, 138)},
224  {"gray55", myRGB(140, 140, 140)},
225  {"gray56", myRGB(143, 143, 143)},
226  {"gray57", myRGB(145, 145, 145)},
227  {"gray58", myRGB(148, 148, 148)},
228  {"gray59", myRGB(150, 150, 150)},
229  {"gray6", myRGB(15, 15, 15)},
230  {"gray60", myRGB(153, 153, 153)},
231  {"gray61", myRGB(156, 156, 156)},
232  {"gray62", myRGB(158, 158, 158)},
233  {"gray63", myRGB(161, 161, 161)},
234  {"gray64", myRGB(163, 163, 163)},
235  {"gray65", myRGB(166, 166, 166)},
236  {"gray66", myRGB(168, 168, 168)},
237  {"gray67", myRGB(171, 171, 171)},
238  {"gray68", myRGB(173, 173, 173)},
239  {"gray69", myRGB(176, 176, 176)},
240  {"gray7", myRGB(18, 18, 18)},
241  {"gray70", myRGB(179, 179, 179)},
242  {"gray71", myRGB(181, 181, 181)},
243  {"gray72", myRGB(184, 184, 184)},
244  {"gray73", myRGB(186, 186, 186)},
245  {"gray74", myRGB(189, 189, 189)},
246  {"gray75", myRGB(191, 191, 191)},
247  {"gray76", myRGB(194, 194, 194)},
248  {"gray77", myRGB(196, 196, 196)},
249  {"gray78", myRGB(199, 199, 199)},
250  {"gray79", myRGB(201, 201, 201)},
251  {"gray8", myRGB(20, 20, 20)},
252  {"gray80", myRGB(204, 204, 204)},
253  {"gray81", myRGB(207, 207, 207)},
254  {"gray82", myRGB(209, 209, 209)},
255  {"gray83", myRGB(212, 212, 212)},
256  {"gray84", myRGB(214, 214, 214)},
257  {"gray85", myRGB(217, 217, 217)},
258  {"gray86", myRGB(219, 219, 219)},
259  {"gray87", myRGB(222, 222, 222)},
260  {"gray88", myRGB(224, 224, 224)},
261  {"gray89", myRGB(227, 227, 227)},
262  {"gray9", myRGB(23, 23, 23)},
263  {"gray90", myRGB(229, 229, 229)},
264  {"gray91", myRGB(232, 232, 232)},
265  {"gray92", myRGB(235, 235, 235)},
266  {"gray93", myRGB(237, 237, 237)},
267  {"gray94", myRGB(240, 240, 240)},
268  {"gray95", myRGB(242, 242, 242)},
269  {"gray96", myRGB(245, 245, 245)},
270  {"gray97", myRGB(247, 247, 247)},
271  {"gray98", myRGB(250, 250, 250)},
272  {"gray99", myRGB(252, 252, 252)},
273  {"green", myRGB(0, 255, 0)},
274  {"greenyellow", myRGB(173, 255, 47)},
275  {"honeydew", myRGB(240, 255, 240)},
276  {"hotpink", myRGB(255, 105, 180)},
277  {"indianred", myRGB(107, 57, 57)},
278  {"ivory", myRGB(255, 255, 240)},
279  {"khaki", myRGB(179, 179, 126)},
280  {"lavender", myRGB(230, 230, 250)},
281  {"lavenderblush", myRGB(255, 240, 245)},
282  {"lawngreen", myRGB(124, 252, 0)},
283  {"lemonchiffon", myRGB(255, 250, 205)},
284  {"lightblue", myRGB(176, 226, 255)},
285  {"lightcoral", myRGB(240, 128, 128)},
286  {"lightcyan", myRGB(224, 255, 255)},
287  {"lightgoldenrod", myRGB(238, 221, 130)},
288  {"lightgoldenrodyellow", myRGB(250, 250, 210)},
289  {"lightgray", myRGB(168, 168, 168)},
290  {"lightpink", myRGB(255, 182, 193)},
291  {"lightsalmon", myRGB(255, 160, 122)},
292  {"lightseagreen", myRGB(32, 178, 170)},
293  {"lightskyblue", myRGB(135, 206, 250)},
294  {"lightslateblue", myRGB(132, 112, 255)},
295  {"lightslategray", myRGB(119, 136, 153)},
296  {"lightsteelblue", myRGB(124, 152, 211)},
297  {"lightyellow", myRGB(255, 255, 224)},
298  {"limegreen", myRGB(0, 175, 20)},
299  {"linen", myRGB(250, 240, 230)},
300  {"magenta", myRGB(255, 0, 255)},
301  {"maroon", myRGB(143, 0, 82)},
302  {"mediumaquamarine", myRGB(0, 147, 143)},
303  {"mediumblue", myRGB(50, 50, 204)},
304  {"mediumforestgreen", myRGB(50, 129, 75)},
305  {"mediumgoldenrod", myRGB(209, 193, 102)},
306  {"mediumorchid", myRGB(189, 82, 189)},
307  {"mediumpurple", myRGB(147, 112, 219)},
308  {"mediumseagreen", myRGB(52, 119, 102)},
309  {"mediumslateblue", myRGB(106, 106, 141)},
310  {"mediumspringgreen", myRGB(35, 142, 35)},
311  {"mediumturquoise", myRGB(0, 210, 210)},
312  {"mediumvioletred", myRGB(213, 32, 121)},
313  {"midnightblue", myRGB(47, 47, 100)},
314  {"mintcream", myRGB(245, 255, 250)},
315  {"mistyrose", myRGB(255, 228, 225)},
316  {"moccasin", myRGB(255, 228, 181)},
317  {"navajowhite", myRGB(255, 222, 173)},
318  {"navy", myRGB(35, 35, 117)},
319  {"navyblue", myRGB(35, 35, 117)},
320  {"oldlace", myRGB(253, 245, 230)},
321  {"olivedrab", myRGB(107, 142, 35)},
322  {"orange", myRGB(255, 135, 0)},
323  {"orangered", myRGB(255, 69, 0)},
324  {"orchid", myRGB(239, 132, 239)},
325  {"palegoldenrod", myRGB(238, 232, 170)},
326  {"palegreen", myRGB(115, 222, 120)},
327  {"paleturquoise", myRGB(175, 238, 238)},
328  {"palevioletred", myRGB(219, 112, 147)},
329  {"papayawhip", myRGB(255, 239, 213)},
330  {"peachpuff", myRGB(255, 218, 185)},
331  {"peru", myRGB(205, 133, 63)},
332  {"pink", myRGB(255, 181, 197)},
333  {"plum", myRGB(197, 72, 155)},
334  {"powderblue", myRGB(176, 224, 230)},
335  {"purple", myRGB(160, 32, 240)},
336  {"red", myRGB(255, 0, 0)},
337  {"rosybrown", myRGB(188, 143, 143)},
338  {"royalblue", myRGB(65, 105, 225)},
339  {"saddlebrown", myRGB(139, 69, 19)},
340  {"salmon", myRGB(233, 150, 122)},
341  {"sandybrown", myRGB(244, 164, 96)},
342  {"seagreen", myRGB(82, 149, 132)},
343  {"seashell", myRGB(255, 245, 238)},
344  {"sienna", myRGB(150, 82, 45)},
345  {"silver", myRGB(192, 192, 192)},
346  {"skyblue", myRGB(114, 159, 255)},
347  {"slateblue", myRGB(126, 136, 171)},
348  {"slategray", myRGB(112, 128, 144)},
349  {"snow", myRGB(255, 250, 250)},
350  {"springgreen", myRGB(65, 172, 65)},
351  {"steelblue", myRGB(84, 112, 170)},
352  {"tan", myRGB(222, 184, 135)},
353  {"thistle", myRGB(216, 191, 216)},
354  {"tomato", myRGB(255, 99, 71)},
355  {"transparent", myRGB(0, 0, 1)},
356  {"turquoise", myRGB(25, 204, 223)},
357  {"violet", myRGB(156, 62, 206)},
358  {"violetred", myRGB(243, 62, 150)},
359  {"wheat", myRGB(245, 222, 179)},
360  {"white", myRGB(255, 255, 255)},
361  {"whitesmoke", myRGB(245, 245, 245)},
362  {"yellow", myRGB(255, 255, 0)},
363  {"yellowgreen", myRGB(50, 216, 56)},
364  {NULL, myRGB(0, 0, 0)}};
365 static const int numTheRGBRecords = 235;
366 
367 static unsigned char ParseHexadecimal(char digit1, char digit2)
368 {
369  unsigned char i1, i2;
370 
371  if (digit1 >= 'a')
372  i1 = (unsigned char)(digit1 - 'a' + 0x0A);
373  else if (digit1 >= 'A')
374  i1 = (unsigned char)(digit1 - 'A' + 0x0A);
375  else
376  i1 = (unsigned char)(digit1 - '0');
377  if (digit2 >= 'a')
378  i2 = (unsigned char)(digit2 - 'a' + 0x0A);
379  else if (digit2 >= 'A')
380  i2 = (unsigned char)(digit2 - 'A' + 0x0A);
381  else
382  i2 = (unsigned char)(digit2 - '0');
383  return (unsigned char)(0x10 * i1 + i2);
384 }
385 
386 static bool GetRGBFromName(
387  const char* inname, bool* isNone, unsigned char* r, unsigned char* g,
388  unsigned char* b)
389 {
390  int left, right, middle;
391  int cmp;
392  uint32_t rgbVal;
393  char* name;
394  char *grey, *p;
395 
396  // Neither #rrggbb nor #rrrrggggbbbb are in database, we parse them directly
397  size_t inname_len = strlen(inname);
398  if (*inname == '#' && (inname_len == 7 || inname_len == 13))
399  {
400  size_t ofs = (inname_len == 7) ? 2 : 4;
401  *r = ParseHexadecimal(inname[1], inname[2]);
402  *g = ParseHexadecimal(inname[1 * ofs + 1], inname[1 * ofs + 2]);
403  *b = ParseHexadecimal(inname[2 * ofs + 1], inname[2 * ofs + 2]);
404  *isNone = false;
405  return true;
406  }
407 
408  name = ::strdup(inname);
409 
410  // theRGBRecords[] has no names with spaces, and no grey, but a
411  // lot of gray...
412 
413  // so first extract ' '
414  while ((p = strchr(name, ' ')) != NULL)
415  {
416  while (*(p)) // till eof of string
417  {
418  *p = *(p + 1); // copy to the left
419  p++;
420  }
421  }
422  // fold to lower case
423  p = name;
424  while (*p)
425  {
426  *p = (char)tolower(*p);
427  p++;
428  }
429 
430  // substitute Grey with Gray, else rgbtab.h would have more than 100
431  // 'duplicate' entries
432  if ((grey = strstr(name, "grey")) != NULL) grey[2] = 'a';
433 
434  // check for special 'none' colour:
435  bool found;
436  if (strcmp(name, "none") == 0)
437  {
438  *isNone = true;
439  found = true;
440  }
441  else // not "None"
442  {
443  found = false;
444 
445  // binary search:
446  left = 0;
447  right = numTheRGBRecords - 1;
448  do
449  {
450  middle = (left + right) / 2;
451  cmp = strcmp(name, theRGBRecords[middle].name);
452  if (cmp == 0)
453  {
454  rgbVal = theRGBRecords[middle].rgb;
455  *r = (unsigned char)((rgbVal >> 16) & 0xFF);
456  *g = (unsigned char)((rgbVal >> 8) & 0xFF);
457  *b = (unsigned char)((rgbVal)&0xFF);
458  *isNone = false;
459  found = true;
460  break;
461  }
462  else if (cmp < 0)
463  {
464  right = middle - 1;
465  }
466  else // cmp > 0
467  {
468  left = middle + 1;
469  }
470  } while (left <= right);
471  }
472 
473  free(name);
474 
475  return found;
476 }
477 #endif
478 
479 /** Loads the image from an XPM array, as #include'd from a ".xpm" file.
480  * \sa loadFromFile
481  * \return false on any error */
482 bool mrpt::img::CImage::loadFromXPM(const char* const* xpm_data, bool swap_rb)
483 {
484 #if MRPT_HAS_OPENCV
485  try
486  {
487  ASSERTMSG_(xpm_data, "XPM data is nullptr");
488 
489  char key[64];
490  XPMColorMap clr_tbl;
491  std::string maskKey, keyString;
492 
493  /*
494  * Read hints and initialize structures:
495  */
496  unsigned width, height, colors_cnt, chars_per_pixel;
497  const int count = ::sscanf(
498  xpm_data[0], "%u %u %u %u", &width, &height, &colors_cnt,
499  &chars_per_pixel);
500  if (count != 4 || width * height * colors_cnt == 0)
501  {
502  THROW_EXCEPTION("XPM: incorrect header format!");
503  return false;
504  }
505 
506  // VS: XPM color map this large would be insane, since XPMs are encoded
507  // with 92 possible values on each position, 92^64 is *way* larger space
508  // than 8bit RGB...
509  ASSERTMSG_(
510  chars_per_pixel < 64, "XPM colormaps this large not supported.");
511 
512  this->changeSize(width, height, CH_RGB, true /*originTopLeft*/);
513  key[chars_per_pixel] = '\0';
514 
515  /*
516  * Create colour map:
517  */
518  XPMColorMapData clr_data;
519  for (size_t i = 0; i < colors_cnt; i++)
520  {
521  const char* xmpColLine = xpm_data[1 + i];
522 
523  // we must have at least " x y" after the colour index, hence +5
524  if (!xmpColLine || strlen(xmpColLine) < chars_per_pixel + 5)
525  {
527  "XPM: incorrect colour description in line %d",
528  (int)(1 + i));
529  return false;
530  }
531 
532  for (size_t i_key = 0; i_key < chars_per_pixel; i_key++)
533  key[i_key] = xmpColLine[i_key];
534  const char* clr_def = ParseColor(xmpColLine + chars_per_pixel);
535 
536  if (clr_def == NULL)
537  {
539  "XPM: malformed colour definition '%s' at line %d!",
540  xmpColLine, (int)(1 + i));
541  return false;
542  }
543 
544  bool isNone = false;
545  if (!GetRGBFromName(
546  clr_def, &isNone, &clr_data.R, &clr_data.G, &clr_data.B))
547  {
549  "XPM: malformed colour definition '%s' at line %d!",
550  xmpColLine, (int)(1 + i));
551  return false;
552  }
553 
554  keyString = key;
555  if (isNone) maskKey = keyString;
556 
557  clr_tbl[keyString] = clr_data;
558  }
559 
560  // deal with the mask: we must replace pseudo-colour "None" with the
561  // mask colour (which can be any colour not otherwise used in the image)
562  if (!maskKey.empty())
563  {
564  Long2LongHash rgb_table;
565  long rgb;
566  const size_t n = clr_tbl.size();
567  auto iter = clr_tbl.begin();
568  for (size_t i = 0; i < n; ++i, ++iter)
569  {
570  const XPMColorMapData& data = iter->second;
571  rgb = (data.R << 16) + (data.G << 8) + data.B;
572  rgb_table[rgb];
573  }
574  for (rgb = 0; rgb <= 0xffffff && rgb_table.count(rgb); ++rgb)
575  ;
576  if (rgb > 0xffffff)
577  {
578  THROW_EXCEPTION("XPM: no colors left to use for mask!");
579  return false;
580  }
581 
582  XPMColorMapData& maskData = clr_tbl[maskKey];
583  maskData.R = uint8_t(rgb >> 16);
584  maskData.G = uint8_t(rgb >> 8);
585  maskData.B = uint8_t(rgb);
586 
587  // MRPT CImage does not implement masks (!!)
588  // img.SetMaskColour(maskData.R, maskData.G, maskData.B);
589  }
590 
591  /*
592  * Parse image data:
593  */
594  unsigned char* img_data = (*this)(0, 0);
595  auto end = clr_tbl.end();
596 
597  for (size_t j = 0; j < height; j++)
598  {
599  for (size_t i = 0; i < width; i++, img_data += 3)
600  {
601  const char* xpmImgLine = xpm_data[1 + colors_cnt + j];
602  if (!xpmImgLine || strlen(xpmImgLine) < width * chars_per_pixel)
603  {
605  "XPM: truncated image data at line %d!",
606  (int)(1 + colors_cnt + j));
607  return false;
608  }
609 
610  for (size_t i_key = 0; i_key < chars_per_pixel; i_key++)
611  {
612  key[i_key] = xpmImgLine[chars_per_pixel * i + i_key];
613  }
614 
615  keyString = key;
616  auto entry = clr_tbl.find(keyString);
617  if (entry == end)
618  {
619  THROW_EXCEPTION("XPM: Malformed pixel data!");
620 
621  // better return right now as otherwise we risk to flood the
622  // user with error messages as something seems to be
623  // seriously wrong with the file and so we could give this
624  // message for each remaining pixel if we don't bail out
625  return false;
626  }
627 
628  img_data[0] = entry->second.R;
629  img_data[1] = entry->second.G;
630  img_data[2] = entry->second.B;
631  }
632  }
633 
634  if (swap_rb) this->swapRB();
635 
636  return true;
637  }
638  catch (std::exception& e)
639  {
640  std::cerr << "[CImage::loadFromXPM] " << e.what() << std::endl;
641  return false;
642  }
643 #else
644  MRPT_UNUSED_PARAM(xpm_data);
645  MRPT_UNUSED_PARAM(swap_rb);
646  return false;
647 #endif
648 }
unsigned char B
GLuint GLuint GLsizei count
Definition: glext.h:3528
bool loadFromXPM(const char *const *xpm_array, bool swap_rb=true)
Loads the image from an XPM array, as #include&#39;d from a ".xpm" file.
void changeSize(unsigned int width, unsigned int height, TImageChannels nChannels, bool originTopLeft)
Resize the buffers in "img" to accomodate a new image size and/or format.
Definition: CImage.cpp:223
#define THROW_EXCEPTION(msg)
Definition: exceptions.h:41
static const rgbRecord theRGBRecords[]
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
GLenum GLsizei n
Definition: glext.h:5074
unsigned char G
static bool GetRGBFromName(const char *inname, bool *isNone, unsigned char *r, unsigned char *g, unsigned char *b)
uint32_t rgb
GLenum GLsizei width
Definition: glext.h:3531
unsigned char uint8_t
Definition: rptypes.h:41
void swapRB()
Swaps red and blue channels.
Definition: CImage.cpp:2005
unsigned char R
static const int numTheRGBRecords
GLuint GLuint end
Definition: glext.h:3528
GLubyte g
Definition: glext.h:6279
GLubyte GLubyte b
Definition: glext.h:6279
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:101
GLsizei const GLchar ** string
Definition: glext.h:4101
#define myRGB(r, g, b)
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
static const char * ParseColor(const char *data)
std::unordered_map< std::string, XPMColorMapData > XPMColorMap
GLuint const GLchar * name
Definition: glext.h:4054
GLenum GLsizei GLsizei height
Definition: glext.h:3554
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
Definition: exceptions.h:43
unsigned __int32 uint32_t
Definition: rptypes.h:47
std::unordered_map< int64_t, int64_t > Long2LongHash
static unsigned char ParseHexadecimal(char digit1, char digit2)
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
GLfloat GLfloat p
Definition: glext.h:6305
const char * name
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
Definition: common.h:186
#define CH_RGB
Definition: img/CImage.h:45



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020