1 /* nxpm.c - load "normalized" XPM image
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
32 #include "imgformat.h"
37 * Restricted support for XPM images.
39 * The images must be in the following "normalized" format:
44 * 2 ignored ( normally "static char *xpm[] = {" )
45 * 3 "width height color_count chars" where chars is 1 or 2
46 * 4 color definitions. Only c values with #rrggbb or #rrrrggggbbb
50 * - no comments or blank lines are allowed, except for the signature
51 * - all lines must have at most 256 characters
52 * - no white spaces allowed at left of each line
58 static void free_color_symbol_table(unsigned char *color_table
[],
59 unsigned short *symbol_table
)
73 RImage
*RGetImageFromXPMData(RContext
* context
, char **data
)
76 unsigned char *color_table
[4] = { NULL
, NULL
, NULL
, NULL
};
77 unsigned short *symbol_table
= NULL
;
78 unsigned char *r
, *g
, *b
, *a
;
79 int i
, j
, k
, line
= 0;
83 int w
, h
, ccount
, csize
;
86 * When using libXpm we need the context argument but the code here does
87 * not, so tell the compiler to not warn about it
91 if (sscanf(data
[line
++], "%i %i %i %i", &w
, &h
, &ccount
, &csize
) != 4
92 || w
<= 0 || h
<= 0 || ccount
<= 0 || csize
<= 0)
95 if (csize
!= 1 && csize
!= 2)
98 color_table
[0] = malloc(ccount
);
99 color_table
[1] = malloc(ccount
);
100 color_table
[2] = malloc(ccount
);
101 color_table
[3] = malloc(ccount
);
102 symbol_table
= malloc(ccount
* sizeof(unsigned short));
104 bsize
= csize
* w
+ 16;
106 if (!color_table
[0] || !color_table
[1] || !color_table
[2] || !color_table
[3] || !symbol_table
|| !bsize
) {
107 RErrorCode
= RERR_NOMEMORY
;
108 free_color_symbol_table(color_table
, symbol_table
);
113 /* get color table */
114 for (i
= 0; i
< ccount
; i
++) {
115 symbol_table
[i
] = data
[line
][0];
117 symbol_table
[i
] |= data
[line
][1] << 8;
120 while (data
[line
][j
] != '#' && data
[line
][j
] != 0 && data
[line
][j
] != 'N')
123 if (data
[line
][j
] == '#') {
124 unsigned int red
, green
, blue
;
128 while (data
[line
][j
+ k
] != 0)
131 if (sscanf(&(data
[line
][j
]), "%2x%2x%2x", &red
, &green
, &blue
) != 3)
133 } else if (k
== 12) {
134 if (sscanf(&(data
[line
][j
]), "%4x%4x%4x", &red
, &green
, &blue
) != 3)
142 color_table
[0][i
] = red
;
143 color_table
[1][i
] = green
;
144 color_table
[2][i
] = blue
;
145 color_table
[3][i
] = 255;
146 } else if (strncmp(&(data
[line
][j
]), "None", 4) == 0 || strncmp(&(data
[line
][j
]), "none", 4) == 0) {
147 color_table
[3][i
] = 0;
155 image
= RCreateImage(w
, h
, transp
);
157 free_color_symbol_table(color_table
, symbol_table
);
164 if (image
->format
== RRGBAFormat
)
169 for (i
= 0; i
< h
; i
++) {
171 for (j
= 0; j
< w
; j
++) {
172 color
= data
[line
][j
];
174 for (k
= 0; k
< ccount
; k
++) {
175 if (symbol_table
[k
] == color
)
181 *r
= color_table
[0][k
];
182 *g
= color_table
[1][k
];
183 *b
= color_table
[2][k
];
185 *a
= color_table
[3][k
];
197 for (j
= 0; j
< w
* 2; j
++) {
198 color
= data
[line
][j
++];
199 color
|= data
[line
][j
];
201 for (k
= 0; k
< ccount
; k
++) {
202 if (symbol_table
[k
] == color
)
208 *r
= color_table
[0][k
];
209 *g
= color_table
[1][k
];
210 *b
= color_table
[2][k
];
212 *a
= color_table
[3][k
];
227 free_color_symbol_table(color_table
, symbol_table
);
231 RErrorCode
= RERR_BADIMAGEFILE
;
232 free_color_symbol_table(color_table
, symbol_table
);
234 RReleaseImage(image
);
238 RImage
*RLoadXPM(RContext
* context
, const char *file
)
240 RImage
*image
= NULL
;
241 char line
[LINEWIDTH
+ 1];
243 unsigned char *color_table
[4] = { NULL
, NULL
, NULL
, NULL
};
244 unsigned short *symbol_table
= NULL
;
245 unsigned char *r
, *g
, *b
, *a
;
248 unsigned short color
;
250 int w
, h
, ccount
, csize
;
254 * When using libXpm we need the context argument but the code here does
255 * not, so tell the compiler to not warn about it
259 f
= fopen(file
, "rb");
261 RErrorCode
= RERR_OPEN
;
265 if (!fgets(line
, LINEWIDTH
, f
))
268 if (!fgets(line
, LINEWIDTH
, f
))
272 if (!fgets(line
, LINEWIDTH
, f
))
276 if (!fgets(line
, LINEWIDTH
, f
))
279 if (sscanf(line
, "\"%i %i %i %i\"", &w
, &h
, &ccount
, &csize
) != 4
280 || w
<= 0 || h
<= 0 || ccount
<= 0 || csize
<= 0)
283 if (csize
!= 1 && csize
!= 2)
286 color_table
[0] = malloc(ccount
);
287 color_table
[1] = malloc(ccount
);
288 color_table
[2] = malloc(ccount
);
289 color_table
[3] = malloc(ccount
);
290 symbol_table
= malloc(ccount
* sizeof(unsigned short));
292 bsize
= csize
* w
+ 16;
293 buffer
= malloc(bsize
);
295 if (!color_table
[0] || !color_table
[1] || !color_table
[2] ||
296 !color_table
[3] || !symbol_table
|| !bsize
|| !buffer
) {
297 RErrorCode
= RERR_NOMEMORY
;
299 free_color_symbol_table(color_table
, symbol_table
);
306 /* get color table */
307 for (i
= 0; i
< ccount
; i
++) {
308 if (!fgets(line
, LINEWIDTH
, f
))
311 if (!fgets(line
, LINEWIDTH
, f
))
314 symbol_table
[i
] = line
[1];
316 symbol_table
[i
] |= line
[2] << 8;
319 while (line
[j
] != '#' && line
[j
] != '"' && line
[j
] != 0 && line
[j
] != 'N')
322 if (line
[j
] == '#') {
323 unsigned int red
, green
, blue
;
327 while (line
[j
+ k
] != '"' && line
[j
+ k
] != 0)
330 if (sscanf(&(line
[j
]), "%2x%2x%2x", &red
, &green
, &blue
) != 3)
332 } else if (k
== 12) {
333 if (sscanf(&(line
[j
]), "%4x%4x%4x", &red
, &green
, &blue
) != 3)
341 color_table
[0][i
] = red
;
342 color_table
[1][i
] = green
;
343 color_table
[2][i
] = blue
;
344 color_table
[3][i
] = 255;
345 } else if (strncmp(&(line
[j
]), "None", 4) == 0 || strncmp(&(line
[j
]), "none", 4) == 0) {
346 color_table
[3][i
] = 0;
353 image
= RCreateImage(w
, h
, transp
);
356 free_color_symbol_table(color_table
, symbol_table
);
365 if (image
->format
== RRGBAFormat
)
370 for (i
= 0; i
< h
; i
++) {
371 if (!fgets(buffer
, bsize
, f
))
373 if (buffer
[0] == '/')
374 if (!fgets(buffer
, bsize
, f
))
378 for (j
= 1; j
<= w
; j
++) {
381 for (k
= 0; k
< ccount
; k
++) {
382 if (symbol_table
[k
] == color
)
388 *r
= color_table
[0][k
];
389 *g
= color_table
[1][k
];
390 *b
= color_table
[2][k
];
392 *a
= color_table
[3][k
];
404 for (j
= 1; j
<= w
* 2; j
++) {
406 color
|= buffer
[j
] << 8;
408 for (k
= 0; k
< ccount
; k
++) {
409 if (symbol_table
[k
] == color
)
416 *r
= color_table
[0][k
];
417 *g
= color_table
[1][k
];
418 *b
= color_table
[2][k
];
420 *a
= color_table
[3][k
];
435 free_color_symbol_table(color_table
, symbol_table
);
441 RErrorCode
= RERR_BADIMAGEFILE
;
443 free_color_symbol_table(color_table
, symbol_table
);
447 RReleaseImage(image
);
451 RErrorCode
= RERR_BADIMAGEFILE
;
453 free_color_symbol_table(color_table
, symbol_table
);
457 RReleaseImage(image
);