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"
35 * Restricted support for XPM images.
37 * The images must be in the following "normalized" format:
42 * 2 ignored ( normally "static char *xpm[] = {" )
43 * 3 "width height color_count chars" where chars is 1 or 2
44 * 4 color definitions. Only c values with #rrggbb or #rrrrggggbbb
48 * - no comments or blank lines are allowed, except for the signature
49 * - all lines must have at most 256 characters
50 * - no white spaces allowed at left of each line
56 static void free_color_symbol_table(unsigned char *color_table
[],
57 unsigned short *symbol_table
)
71 RImage
*RGetImageFromXPMData(RContext
* context
, char **data
)
74 unsigned char *color_table
[4] = { NULL
, NULL
, NULL
, NULL
};
75 unsigned short *symbol_table
= NULL
;
76 unsigned char *r
, *g
, *b
, *a
;
77 int i
, j
, k
, line
= 0;
81 int w
, h
, ccount
, csize
;
84 * When using libXpm we need the context argument but the code here does
85 * not, so tell the compiler to not warn about it
89 if (sscanf(data
[line
++], "%i %i %i %i", &w
, &h
, &ccount
, &csize
) != 4
90 || w
<= 0 || h
<= 0 || ccount
<= 0 || csize
<= 0)
93 if (csize
!= 1 && csize
!= 2)
96 color_table
[0] = malloc(ccount
);
97 color_table
[1] = malloc(ccount
);
98 color_table
[2] = malloc(ccount
);
99 color_table
[3] = malloc(ccount
);
100 symbol_table
= malloc(ccount
* sizeof(unsigned short));
102 bsize
= csize
* w
+ 16;
104 if (!color_table
[0] || !color_table
[1] || !color_table
[2] || !color_table
[3] || !symbol_table
|| !bsize
) {
105 RErrorCode
= RERR_NOMEMORY
;
106 free_color_symbol_table(color_table
, symbol_table
);
111 /* get color table */
112 for (i
= 0; i
< ccount
; i
++) {
113 symbol_table
[i
] = data
[line
][0];
115 symbol_table
[i
] |= data
[line
][1] << 8;
118 while (data
[line
][j
] != '#' && data
[line
][j
] != 0 && data
[line
][j
] != 'N')
121 if (data
[line
][j
] == '#') {
122 unsigned int red
, green
, blue
;
126 while (data
[line
][j
+ k
] != 0)
129 if (sscanf(&(data
[line
][j
]), "%2x%2x%2x", &red
, &green
, &blue
) != 3)
131 } else if (k
== 12) {
132 if (sscanf(&(data
[line
][j
]), "%4x%4x%4x", &red
, &green
, &blue
) != 3)
140 color_table
[0][i
] = red
;
141 color_table
[1][i
] = green
;
142 color_table
[2][i
] = blue
;
143 color_table
[3][i
] = 255;
144 } else if (strncmp(&(data
[line
][j
]), "None", 4) == 0 || strncmp(&(data
[line
][j
]), "none", 4) == 0) {
145 color_table
[3][i
] = 0;
153 image
= RCreateImage(w
, h
, transp
);
155 free_color_symbol_table(color_table
, symbol_table
);
162 if (image
->format
== RRGBAFormat
)
167 for (i
= 0; i
< h
; i
++) {
169 for (j
= 0; j
< w
; j
++) {
170 color
= data
[line
][j
];
172 for (k
= 0; k
< ccount
; k
++) {
173 if (symbol_table
[k
] == color
)
179 *r
= color_table
[0][k
];
180 *g
= color_table
[1][k
];
181 *b
= color_table
[2][k
];
183 *a
= color_table
[3][k
];
195 for (j
= 0; j
< w
* 2; j
++) {
196 color
= data
[line
][j
++];
197 color
|= data
[line
][j
];
199 for (k
= 0; k
< ccount
; k
++) {
200 if (symbol_table
[k
] == color
)
206 *r
= color_table
[0][k
];
207 *g
= color_table
[1][k
];
208 *b
= color_table
[2][k
];
210 *a
= color_table
[3][k
];
225 free_color_symbol_table(color_table
, symbol_table
);
229 RErrorCode
= RERR_BADIMAGEFILE
;
230 free_color_symbol_table(color_table
, symbol_table
);
232 RReleaseImage(image
);
236 RImage
*RLoadXPM(RContext
* context
, const char *file
)
238 RImage
*image
= NULL
;
239 char line
[LINEWIDTH
+ 1];
241 unsigned char *color_table
[4] = { NULL
, NULL
, NULL
, NULL
};
242 unsigned short *symbol_table
= NULL
;
243 unsigned char *r
, *g
, *b
, *a
;
246 unsigned short color
;
248 int w
, h
, ccount
, csize
;
252 * When using libXpm we need the context argument but the code here does
253 * not, so tell the compiler to not warn about it
257 f
= fopen(file
, "rb");
259 RErrorCode
= RERR_OPEN
;
263 if (!fgets(line
, LINEWIDTH
, f
))
266 if (!fgets(line
, LINEWIDTH
, f
))
270 if (!fgets(line
, LINEWIDTH
, f
))
274 if (!fgets(line
, LINEWIDTH
, f
))
277 if (sscanf(line
, "\"%i %i %i %i\"", &w
, &h
, &ccount
, &csize
) != 4
278 || w
<= 0 || h
<= 0 || ccount
<= 0 || csize
<= 0)
281 if (csize
!= 1 && csize
!= 2)
284 color_table
[0] = malloc(ccount
);
285 color_table
[1] = malloc(ccount
);
286 color_table
[2] = malloc(ccount
);
287 color_table
[3] = malloc(ccount
);
288 symbol_table
= malloc(ccount
* sizeof(unsigned short));
290 bsize
= csize
* w
+ 16;
291 buffer
= malloc(bsize
);
293 if (!color_table
[0] || !color_table
[1] || !color_table
[2] ||
294 !color_table
[3] || !symbol_table
|| !bsize
|| !buffer
) {
295 RErrorCode
= RERR_NOMEMORY
;
297 free_color_symbol_table(color_table
, symbol_table
);
304 /* get color table */
305 for (i
= 0; i
< ccount
; i
++) {
306 if (!fgets(line
, LINEWIDTH
, f
))
309 if (!fgets(line
, LINEWIDTH
, f
))
312 symbol_table
[i
] = line
[1];
314 symbol_table
[i
] |= line
[2] << 8;
317 while (line
[j
] != '#' && line
[j
] != '"' && line
[j
] != 0 && line
[j
] != 'N')
320 if (line
[j
] == '#') {
321 unsigned int red
, green
, blue
;
325 while (line
[j
+ k
] != '"' && line
[j
+ k
] != 0)
328 if (sscanf(&(line
[j
]), "%2x%2x%2x", &red
, &green
, &blue
) != 3)
330 } else if (k
== 12) {
331 if (sscanf(&(line
[j
]), "%4x%4x%4x", &red
, &green
, &blue
) != 3)
339 color_table
[0][i
] = red
;
340 color_table
[1][i
] = green
;
341 color_table
[2][i
] = blue
;
342 color_table
[3][i
] = 255;
343 } else if (strncmp(&(line
[j
]), "None", 4) == 0 || strncmp(&(line
[j
]), "none", 4) == 0) {
344 color_table
[3][i
] = 0;
351 image
= RCreateImage(w
, h
, transp
);
354 free_color_symbol_table(color_table
, symbol_table
);
363 if (image
->format
== RRGBAFormat
)
368 for (i
= 0; i
< h
; i
++) {
369 if (!fgets(buffer
, bsize
, f
))
371 if (buffer
[0] == '/')
372 if (!fgets(buffer
, bsize
, f
))
376 for (j
= 1; j
<= w
; j
++) {
379 for (k
= 0; k
< ccount
; k
++) {
380 if (symbol_table
[k
] == color
)
386 *r
= color_table
[0][k
];
387 *g
= color_table
[1][k
];
388 *b
= color_table
[2][k
];
390 *a
= color_table
[3][k
];
402 for (j
= 1; j
<= w
* 2; j
++) {
404 color
|= buffer
[j
] << 8;
406 for (k
= 0; k
< ccount
; k
++) {
407 if (symbol_table
[k
] == color
)
414 *r
= color_table
[0][k
];
415 *g
= color_table
[1][k
];
416 *b
= color_table
[2][k
];
418 *a
= color_table
[3][k
];
433 free_color_symbol_table(color_table
, symbol_table
);
439 RErrorCode
= RERR_BADIMAGEFILE
;
441 free_color_symbol_table(color_table
, symbol_table
);
445 RReleaseImage(image
);
449 RErrorCode
= RERR_BADIMAGEFILE
;
451 free_color_symbol_table(color_table
, symbol_table
);
455 RReleaseImage(image
);