68 #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] != NULL; i++)
90 for (
q = targets[i]; *
r !=
'\0';
r++)
92 if (*
r != *
q)
continue;
93 if (!isspace((
int)(*(
r - 1))))
continue;
97 if (*
q ==
'\0')
return p;
98 if (*
p++ != *
q++)
break;
126 #define myRGB(r, g, b) ((uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b)
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)}};
369 unsigned char i1, i2;
372 i1 = (
unsigned char)(digit1 -
'a' + 0x0A);
373 else if (digit1 >=
'A')
374 i1 = (
unsigned char)(digit1 -
'A' + 0x0A);
376 i1 = (
unsigned char)(digit1 -
'0');
378 i2 = (
unsigned char)(digit2 -
'a' + 0x0A);
379 else if (digit2 >=
'A')
380 i2 = (
unsigned char)(digit2 -
'A' + 0x0A);
382 i2 = (
unsigned char)(digit2 -
'0');
383 return (
unsigned char)(0x10 * i1 + i2);
387 const char* inname,
bool* isNone,
unsigned char*
r,
unsigned char*
g,
390 int left, right, middle;
397 size_t inname_len = strlen(inname);
398 if (*inname ==
'#' && (inname_len == 7 || inname_len == 13))
400 size_t ofs = (inname_len == 7) ? 2 : 4;
408 name = ::strdup(inname);
414 while ((
p = strchr(
name,
' ')) != NULL)
426 *
p = (char)tolower(*
p);
432 if ((grey = strstr(
name,
"grey")) != NULL) grey[2] =
'a';
436 if (strcmp(
name,
"none") == 0)
450 middle = (left + right) / 2;
455 *
r = (
unsigned char)((rgbVal >> 16) & 0xFF);
456 *
g = (
unsigned char)((rgbVal >> 8) & 0xFF);
457 *
b = (
unsigned char)((rgbVal)&0xFF);
470 }
while (left <= right);
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,
510 chars_per_pixel < 64,
"XPM colormaps this large not supported.");
513 key[chars_per_pixel] =
'\0';
519 for (
size_t i = 0; i < colors_cnt; i++)
521 const char* xmpColLine = xpm_data[1 + i];
524 if (!xmpColLine || strlen(xmpColLine) < chars_per_pixel + 5)
527 "XPM: incorrect colour description in line %d",
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);
539 "XPM: malformed colour definition '%s' at line %d!",
540 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));
555 if (isNone) maskKey = keyString;
557 clr_tbl[keyString] = clr_data;
562 if (!maskKey.empty())
566 const size_t n = clr_tbl.size();
567 auto iter = clr_tbl.begin();
568 for (
size_t i = 0; i <
n; ++i, ++iter)
574 for (rgb = 0; rgb <= 0xffffff && rgb_table.count(rgb); ++rgb)
594 unsigned char* img_data = (*this)(0, 0);
595 auto end = clr_tbl.end();
597 for (
size_t j = 0; j <
height; j++)
599 for (
size_t i = 0; i <
width; i++, img_data += 3)
601 const char* xpmImgLine = xpm_data[1 + colors_cnt + j];
602 if (!xpmImgLine || strlen(xpmImgLine) <
width * chars_per_pixel)
605 "XPM: truncated image data at line %d!",
606 (
int)(1 + colors_cnt + j));
610 for (
size_t i_key = 0; i_key < chars_per_pixel; i_key++)
612 key[i_key] = xpmImgLine[chars_per_pixel * i + i_key];
616 auto entry = clr_tbl.find(keyString);
628 img_data[0] = entry->second.R;
629 img_data[1] = entry->second.G;
630 img_data[2] = entry->second.B;
634 if (swap_rb) this->
swapRB();
638 catch (std::exception& e)
640 std::cerr <<
"[CImage::loadFromXPM] " << e.what() << std::endl;