70 #include <unordered_map> 75 unsigned char R{0},
G{0},
B{0};
77 using XPMColorMap = std::unordered_map<std::string, XPMColorMapData>;
82 static const char*
const targets[] = {
"c ",
"g ",
"g4 ",
"m ",
87 for (
int i = 0; targets[i] !=
nullptr; i++)
90 for (q = targets[i]; *r !=
'\0'; r++)
92 if (*r != *q)
continue;
93 if (!isspace(*(r - 1)))
continue;
97 if (*q ==
'\0')
return p;
98 if (*p++ != *q++)
break;
126 #define myRGB(r, g, b) \ 127 (static_cast<uint32_t>(r) << 16 | static_cast<uint32_t>(g) << 8 | \ 128 static_cast<uint32_t>(b)) 131 {
"aliceblue",
myRGB(240, 248, 255)},
132 {
"antiquewhite",
myRGB(250, 235, 215)},
133 {
"aquamarine",
myRGB(50, 191, 193)},
134 {
"azure",
myRGB(240, 255, 255)},
135 {
"beige",
myRGB(245, 245, 220)},
136 {
"bisque",
myRGB(255, 228, 196)},
137 {
"black",
myRGB(0, 0, 0)},
138 {
"blanchedalmond",
myRGB(255, 235, 205)},
139 {
"blue",
myRGB(0, 0, 255)},
140 {
"blueviolet",
myRGB(138, 43, 226)},
141 {
"brown",
myRGB(165, 42, 42)},
142 {
"burlywood",
myRGB(222, 184, 135)},
143 {
"cadetblue",
myRGB(95, 146, 158)},
144 {
"chartreuse",
myRGB(127, 255, 0)},
145 {
"chocolate",
myRGB(210, 105, 30)},
146 {
"coral",
myRGB(255, 114, 86)},
147 {
"cornflowerblue",
myRGB(34, 34, 152)},
148 {
"cornsilk",
myRGB(255, 248, 220)},
149 {
"cyan",
myRGB(0, 255, 255)},
150 {
"darkgoldenrod",
myRGB(184, 134, 11)},
151 {
"darkgreen",
myRGB(0, 86, 45)},
152 {
"darkkhaki",
myRGB(189, 183, 107)},
153 {
"darkolivegreen",
myRGB(85, 86, 47)},
154 {
"darkorange",
myRGB(255, 140, 0)},
155 {
"darkorchid",
myRGB(139, 32, 139)},
156 {
"darksalmon",
myRGB(233, 150, 122)},
157 {
"darkseagreen",
myRGB(143, 188, 143)},
158 {
"darkslateblue",
myRGB(56, 75, 102)},
159 {
"darkslategray",
myRGB(47, 79, 79)},
160 {
"darkturquoise",
myRGB(0, 166, 166)},
161 {
"darkviolet",
myRGB(148, 0, 211)},
162 {
"deeppink",
myRGB(255, 20, 147)},
163 {
"deepskyblue",
myRGB(0, 191, 255)},
164 {
"dimgray",
myRGB(84, 84, 84)},
165 {
"dodgerblue",
myRGB(30, 144, 255)},
166 {
"firebrick",
myRGB(142, 35, 35)},
167 {
"floralwhite",
myRGB(255, 250, 240)},
168 {
"forestgreen",
myRGB(80, 159, 105)},
169 {
"gainsboro",
myRGB(220, 220, 220)},
170 {
"ghostwhite",
myRGB(248, 248, 255)},
171 {
"gold",
myRGB(218, 170, 0)},
172 {
"goldenrod",
myRGB(239, 223, 132)},
173 {
"gray",
myRGB(126, 126, 126)},
174 {
"gray0",
myRGB(0, 0, 0)},
175 {
"gray1",
myRGB(3, 3, 3)},
176 {
"gray10",
myRGB(26, 26, 26)},
177 {
"gray100",
myRGB(255, 255, 255)},
178 {
"gray11",
myRGB(28, 28, 28)},
179 {
"gray12",
myRGB(31, 31, 31)},
180 {
"gray13",
myRGB(33, 33, 33)},
181 {
"gray14",
myRGB(36, 36, 36)},
182 {
"gray15",
myRGB(38, 38, 38)},
183 {
"gray16",
myRGB(41, 41, 41)},
184 {
"gray17",
myRGB(43, 43, 43)},
185 {
"gray18",
myRGB(46, 46, 46)},
186 {
"gray19",
myRGB(48, 48, 48)},
187 {
"gray2",
myRGB(5, 5, 5)},
188 {
"gray20",
myRGB(51, 51, 51)},
189 {
"gray21",
myRGB(54, 54, 54)},
190 {
"gray22",
myRGB(56, 56, 56)},
191 {
"gray23",
myRGB(59, 59, 59)},
192 {
"gray24",
myRGB(61, 61, 61)},
193 {
"gray25",
myRGB(64, 64, 64)},
194 {
"gray26",
myRGB(66, 66, 66)},
195 {
"gray27",
myRGB(69, 69, 69)},
196 {
"gray28",
myRGB(71, 71, 71)},
197 {
"gray29",
myRGB(74, 74, 74)},
198 {
"gray3",
myRGB(8, 8, 8)},
199 {
"gray30",
myRGB(77, 77, 77)},
200 {
"gray31",
myRGB(79, 79, 79)},
201 {
"gray32",
myRGB(82, 82, 82)},
202 {
"gray33",
myRGB(84, 84, 84)},
203 {
"gray34",
myRGB(87, 87, 87)},
204 {
"gray35",
myRGB(89, 89, 89)},
205 {
"gray36",
myRGB(92, 92, 92)},
206 {
"gray37",
myRGB(94, 94, 94)},
207 {
"gray38",
myRGB(97, 97, 97)},
208 {
"gray39",
myRGB(99, 99, 99)},
209 {
"gray4",
myRGB(10, 10, 10)},
210 {
"gray40",
myRGB(102, 102, 102)},
211 {
"gray41",
myRGB(105, 105, 105)},
212 {
"gray42",
myRGB(107, 107, 107)},
213 {
"gray43",
myRGB(110, 110, 110)},
214 {
"gray44",
myRGB(112, 112, 112)},
215 {
"gray45",
myRGB(115, 115, 115)},
216 {
"gray46",
myRGB(117, 117, 117)},
217 {
"gray47",
myRGB(120, 120, 120)},
218 {
"gray48",
myRGB(122, 122, 122)},
219 {
"gray49",
myRGB(125, 125, 125)},
220 {
"gray5",
myRGB(13, 13, 13)},
221 {
"gray50",
myRGB(127, 127, 127)},
222 {
"gray51",
myRGB(130, 130, 130)},
223 {
"gray52",
myRGB(133, 133, 133)},
224 {
"gray53",
myRGB(135, 135, 135)},
225 {
"gray54",
myRGB(138, 138, 138)},
226 {
"gray55",
myRGB(140, 140, 140)},
227 {
"gray56",
myRGB(143, 143, 143)},
228 {
"gray57",
myRGB(145, 145, 145)},
229 {
"gray58",
myRGB(148, 148, 148)},
230 {
"gray59",
myRGB(150, 150, 150)},
231 {
"gray6",
myRGB(15, 15, 15)},
232 {
"gray60",
myRGB(153, 153, 153)},
233 {
"gray61",
myRGB(156, 156, 156)},
234 {
"gray62",
myRGB(158, 158, 158)},
235 {
"gray63",
myRGB(161, 161, 161)},
236 {
"gray64",
myRGB(163, 163, 163)},
237 {
"gray65",
myRGB(166, 166, 166)},
238 {
"gray66",
myRGB(168, 168, 168)},
239 {
"gray67",
myRGB(171, 171, 171)},
240 {
"gray68",
myRGB(173, 173, 173)},
241 {
"gray69",
myRGB(176, 176, 176)},
242 {
"gray7",
myRGB(18, 18, 18)},
243 {
"gray70",
myRGB(179, 179, 179)},
244 {
"gray71",
myRGB(181, 181, 181)},
245 {
"gray72",
myRGB(184, 184, 184)},
246 {
"gray73",
myRGB(186, 186, 186)},
247 {
"gray74",
myRGB(189, 189, 189)},
248 {
"gray75",
myRGB(191, 191, 191)},
249 {
"gray76",
myRGB(194, 194, 194)},
250 {
"gray77",
myRGB(196, 196, 196)},
251 {
"gray78",
myRGB(199, 199, 199)},
252 {
"gray79",
myRGB(201, 201, 201)},
253 {
"gray8",
myRGB(20, 20, 20)},
254 {
"gray80",
myRGB(204, 204, 204)},
255 {
"gray81",
myRGB(207, 207, 207)},
256 {
"gray82",
myRGB(209, 209, 209)},
257 {
"gray83",
myRGB(212, 212, 212)},
258 {
"gray84",
myRGB(214, 214, 214)},
259 {
"gray85",
myRGB(217, 217, 217)},
260 {
"gray86",
myRGB(219, 219, 219)},
261 {
"gray87",
myRGB(222, 222, 222)},
262 {
"gray88",
myRGB(224, 224, 224)},
263 {
"gray89",
myRGB(227, 227, 227)},
264 {
"gray9",
myRGB(23, 23, 23)},
265 {
"gray90",
myRGB(229, 229, 229)},
266 {
"gray91",
myRGB(232, 232, 232)},
267 {
"gray92",
myRGB(235, 235, 235)},
268 {
"gray93",
myRGB(237, 237, 237)},
269 {
"gray94",
myRGB(240, 240, 240)},
270 {
"gray95",
myRGB(242, 242, 242)},
271 {
"gray96",
myRGB(245, 245, 245)},
272 {
"gray97",
myRGB(247, 247, 247)},
273 {
"gray98",
myRGB(250, 250, 250)},
274 {
"gray99",
myRGB(252, 252, 252)},
275 {
"green",
myRGB(0, 255, 0)},
276 {
"greenyellow",
myRGB(173, 255, 47)},
277 {
"honeydew",
myRGB(240, 255, 240)},
278 {
"hotpink",
myRGB(255, 105, 180)},
279 {
"indianred",
myRGB(107, 57, 57)},
280 {
"ivory",
myRGB(255, 255, 240)},
281 {
"khaki",
myRGB(179, 179, 126)},
282 {
"lavender",
myRGB(230, 230, 250)},
283 {
"lavenderblush",
myRGB(255, 240, 245)},
284 {
"lawngreen",
myRGB(124, 252, 0)},
285 {
"lemonchiffon",
myRGB(255, 250, 205)},
286 {
"lightblue",
myRGB(176, 226, 255)},
287 {
"lightcoral",
myRGB(240, 128, 128)},
288 {
"lightcyan",
myRGB(224, 255, 255)},
289 {
"lightgoldenrod",
myRGB(238, 221, 130)},
290 {
"lightgoldenrodyellow",
myRGB(250, 250, 210)},
291 {
"lightgray",
myRGB(168, 168, 168)},
292 {
"lightpink",
myRGB(255, 182, 193)},
293 {
"lightsalmon",
myRGB(255, 160, 122)},
294 {
"lightseagreen",
myRGB(32, 178, 170)},
295 {
"lightskyblue",
myRGB(135, 206, 250)},
296 {
"lightslateblue",
myRGB(132, 112, 255)},
297 {
"lightslategray",
myRGB(119, 136, 153)},
298 {
"lightsteelblue",
myRGB(124, 152, 211)},
299 {
"lightyellow",
myRGB(255, 255, 224)},
300 {
"limegreen",
myRGB(0, 175, 20)},
301 {
"linen",
myRGB(250, 240, 230)},
302 {
"magenta",
myRGB(255, 0, 255)},
303 {
"maroon",
myRGB(143, 0, 82)},
304 {
"mediumaquamarine",
myRGB(0, 147, 143)},
305 {
"mediumblue",
myRGB(50, 50, 204)},
306 {
"mediumforestgreen",
myRGB(50, 129, 75)},
307 {
"mediumgoldenrod",
myRGB(209, 193, 102)},
308 {
"mediumorchid",
myRGB(189, 82, 189)},
309 {
"mediumpurple",
myRGB(147, 112, 219)},
310 {
"mediumseagreen",
myRGB(52, 119, 102)},
311 {
"mediumslateblue",
myRGB(106, 106, 141)},
312 {
"mediumspringgreen",
myRGB(35, 142, 35)},
313 {
"mediumturquoise",
myRGB(0, 210, 210)},
314 {
"mediumvioletred",
myRGB(213, 32, 121)},
315 {
"midnightblue",
myRGB(47, 47, 100)},
316 {
"mintcream",
myRGB(245, 255, 250)},
317 {
"mistyrose",
myRGB(255, 228, 225)},
318 {
"moccasin",
myRGB(255, 228, 181)},
319 {
"navajowhite",
myRGB(255, 222, 173)},
320 {
"navy",
myRGB(35, 35, 117)},
321 {
"navyblue",
myRGB(35, 35, 117)},
322 {
"oldlace",
myRGB(253, 245, 230)},
323 {
"olivedrab",
myRGB(107, 142, 35)},
324 {
"orange",
myRGB(255, 135, 0)},
325 {
"orangered",
myRGB(255, 69, 0)},
326 {
"orchid",
myRGB(239, 132, 239)},
327 {
"palegoldenrod",
myRGB(238, 232, 170)},
328 {
"palegreen",
myRGB(115, 222, 120)},
329 {
"paleturquoise",
myRGB(175, 238, 238)},
330 {
"palevioletred",
myRGB(219, 112, 147)},
331 {
"papayawhip",
myRGB(255, 239, 213)},
332 {
"peachpuff",
myRGB(255, 218, 185)},
333 {
"peru",
myRGB(205, 133, 63)},
334 {
"pink",
myRGB(255, 181, 197)},
335 {
"plum",
myRGB(197, 72, 155)},
336 {
"powderblue",
myRGB(176, 224, 230)},
337 {
"purple",
myRGB(160, 32, 240)},
338 {
"red",
myRGB(255, 0, 0)},
339 {
"rosybrown",
myRGB(188, 143, 143)},
340 {
"royalblue",
myRGB(65, 105, 225)},
341 {
"saddlebrown",
myRGB(139, 69, 19)},
342 {
"salmon",
myRGB(233, 150, 122)},
343 {
"sandybrown",
myRGB(244, 164, 96)},
344 {
"seagreen",
myRGB(82, 149, 132)},
345 {
"seashell",
myRGB(255, 245, 238)},
346 {
"sienna",
myRGB(150, 82, 45)},
347 {
"silver",
myRGB(192, 192, 192)},
348 {
"skyblue",
myRGB(114, 159, 255)},
349 {
"slateblue",
myRGB(126, 136, 171)},
350 {
"slategray",
myRGB(112, 128, 144)},
351 {
"snow",
myRGB(255, 250, 250)},
352 {
"springgreen",
myRGB(65, 172, 65)},
353 {
"steelblue",
myRGB(84, 112, 170)},
354 {
"tan",
myRGB(222, 184, 135)},
355 {
"thistle",
myRGB(216, 191, 216)},
356 {
"tomato",
myRGB(255, 99, 71)},
357 {
"transparent",
myRGB(0, 0, 1)},
358 {
"turquoise",
myRGB(25, 204, 223)},
359 {
"violet",
myRGB(156, 62, 206)},
360 {
"violetred",
myRGB(243, 62, 150)},
361 {
"wheat",
myRGB(245, 222, 179)},
362 {
"white",
myRGB(255, 255, 255)},
363 {
"whitesmoke",
myRGB(245, 245, 245)},
364 {
"yellow",
myRGB(255, 255, 0)},
365 {
"yellowgreen",
myRGB(50, 216, 56)},
366 {
nullptr,
myRGB(0, 0, 0)}};
371 unsigned char i1, i2;
374 i1 = (
unsigned char)(digit1 -
'a' + 0x0A);
375 else if (digit1 >=
'A')
376 i1 = (
unsigned char)(digit1 -
'A' + 0x0A);
378 i1 = (
unsigned char)(digit1 -
'0');
380 i2 = (
unsigned char)(digit2 -
'a' + 0x0A);
381 else if (digit2 >=
'A')
382 i2 = (
unsigned char)(digit2 -
'A' + 0x0A);
384 i2 = (
unsigned char)(digit2 -
'0');
385 return (
unsigned char)(0x10 * i1 + i2);
389 const char* inname,
bool* isNone,
unsigned char* r,
unsigned char* g,
392 int left, right, middle;
399 size_t inname_len = strlen(inname);
400 if (*inname ==
'#' && (inname_len == 7 || inname_len == 13))
402 size_t ofs = (inname_len == 7) ? 2 : 4;
410 name = ::strdup(inname);
416 while ((p = strchr(name,
' ')) !=
nullptr)
428 *p = (char)tolower(*p);
434 if ((grey = strstr(name,
"grey")) !=
nullptr) grey[2] =
'a';
438 if (strcmp(name,
"none") == 0)
452 middle = (left + right) / 2;
457 *r = (
unsigned char)((rgbVal >> 16) & 0xFF);
458 *g = (
unsigned char)((rgbVal >> 8) & 0xFF);
459 *b = (
unsigned char)((rgbVal)&0xFF);
472 }
while (left <= right);
485 [[maybe_unused]]
const char*
const* xpm_data, [[maybe_unused]]
bool swap_rb)
494 std::string maskKey, keyString;
499 unsigned width, height, colors_cnt, chars_per_pixel;
500 const int count = ::sscanf(
501 xpm_data[0],
"%u %u %u %u", &width, &height, &colors_cnt,
503 if (count != 4 || width * height * colors_cnt == 0)
512 chars_per_pixel < 64,
"XPM colormaps this large not supported.");
515 key[chars_per_pixel] =
'\0';
521 for (
size_t i = 0; i < colors_cnt; i++)
523 const char* xmpColLine = xpm_data[1 + i];
526 if (!xmpColLine || strlen(xmpColLine) < chars_per_pixel + 5)
529 "XPM: incorrect colour description in line %d",
533 for (
size_t i_key = 0; i_key < chars_per_pixel; i_key++)
534 key[i_key] = xmpColLine[i_key];
535 const char* clr_def =
ParseColor(xmpColLine + chars_per_pixel);
537 if (clr_def ==
nullptr)
540 "XPM: malformed colour definition '%s' at line %d!",
541 xmpColLine, (
int)(1 + i));
546 clr_def, &isNone, &clr_data.
R, &clr_data.
G, &clr_data.
B))
549 "XPM: malformed colour definition '%s' at line %d!",
550 xmpColLine, (
int)(1 + i));
554 if (isNone) maskKey = keyString;
556 clr_tbl[keyString] = clr_data;
561 if (!maskKey.empty())
565 const size_t n = clr_tbl.size();
566 auto iter = clr_tbl.begin();
567 for (
size_t i = 0; i < n; ++i, ++iter)
573 for (rgb = 0; rgb <= 0xffffff && rgb_table.count(rgb); ++rgb)
581 maskData.
R = uint8_t(rgb >> 16);
582 maskData.
G = uint8_t(rgb >> 8);
583 maskData.
B = uint8_t(rgb);
592 unsigned char* img_data = (*this)(0, 0);
593 auto end = clr_tbl.end();
595 for (
size_t j = 0; j < height; j++)
597 for (
size_t i = 0; i < width; i++, img_data += 3)
599 const char* xpmImgLine = xpm_data[1 + colors_cnt + j];
600 if (!xpmImgLine || strlen(xpmImgLine) < width * chars_per_pixel)
603 "XPM: truncated image data at line %d!",
604 (
int)(1 + colors_cnt + j));
608 for (
size_t i_key = 0; i_key < chars_per_pixel; i_key++)
610 key[i_key] = xpmImgLine[chars_per_pixel * i + i_key];
614 auto entry = clr_tbl.find(keyString);
626 img_data[0] = entry->second.R;
627 img_data[1] = entry->second.G;
628 img_data[2] = entry->second.B;
632 if (swap_rb) this->
swapRB();
636 catch (
const std::exception& e)
638 std::cerr <<
"[CImage::loadFromXPM] " << e.what() << std::endl;
bool loadFromXPM(const char *const *xpm_array, bool swap_rb=true)
Loads the image from an XPM array, as #include'd from a ".xpm" file.
#define THROW_EXCEPTION(msg)
static const rgbRecord theRGBRecords[]
static bool GetRGBFromName(const char *inname, bool *isNone, unsigned char *r, unsigned char *g, unsigned char *b)
void swapRB()
Swaps red and blue channels.
void resize(std::size_t width, std::size_t height, TImageChannels nChannels, PixelDepth depth=PixelDepth::D8U)
Changes the size of the image, erasing previous contents (does NOT scale its current content...
static const int numTheRGBRecords
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
const_iterator end() const
static const char * ParseColor(const char *data)
std::unordered_map< std::string, XPMColorMapData > XPMColorMap
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
std::unordered_map< int64_t, int64_t > Long2LongHash
static unsigned char ParseHexadecimal(char digit1, char digit2)
static struct FontData data