1 /* nxpm.c - load "normalized" XPM image
3 * Raster graphics library
5 * Copyright (c) 1997 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., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* AIX requires this to be the first thing in the file. */
26 # define alloca __builtin_alloca
34 # ifndef alloca /* predefined by HP cc +Olibcalls */
50 * Restricted support for XPM images.
52 * The images must be in the following "normalized" format:
57 * 2 ignored ( normally "static char *xpm[] = {" )
58 * 3 "width height color_count chars" where chars is 1 or 2
59 * 4 color definitions. Only c values with #rrggbb or #rrrrggggbbb
63 * - no comments or blank lines are allowed, except for the signature
64 * - all lines must have at most 256 characters
65 * - no white spaces allowed at left of each line
74 RGetImageFromXPMData(RContext
*context
, char **data
)
77 unsigned char *color_table
[4];
78 unsigned short *symbol_table
;
79 unsigned char *r
, *g
, *b
, *a
;
80 int i
, j
, k
, line
= 0;
84 int w
, h
, ccount
, csize
;
86 if (sscanf(data
[line
++], "%i %i %i %i", &w
, &h
, &ccount
, &csize
)!=4
87 || w
<= 0 || h
<= 0 || ccount
<= 0 || csize
<= 0)
90 if (csize
!=1 && csize
!=2)
93 color_table
[0] = alloca(ccount
);
94 color_table
[1] = alloca(ccount
);
95 color_table
[2] = alloca(ccount
);
96 color_table
[3] = alloca(ccount
);
97 symbol_table
= alloca(ccount
* sizeof(unsigned short));
99 bsize
= csize
* w
+ 16;
101 if (!color_table
[0] || !color_table
[1] || !color_table
[2] ||
102 !color_table
[3] || !symbol_table
|| !bsize
) {
103 sprintf(RErrorString
, "out of memory while converting XPM data");
109 /* get color table */
110 for (i
=0; i
<ccount
; i
++) {
111 symbol_table
[i
] = data
[line
][0];
113 symbol_table
[i
] |= data
[line
][1]<<8;
116 while (data
[line
][j
]!='#' && data
[line
][j
]!=0
117 && data
[line
][j
]!='N') j
++;
119 if (data
[line
][j
]=='#') {
120 unsigned int red
, green
, blue
;
124 while (data
[line
][j
+k
]!=0) k
++;
126 if (sscanf(&(data
[line
][j
]), "%2x%2x%2x", &red
, &green
, &blue
)!=3)
129 if (sscanf(&(data
[line
][j
]), "%4x%4x%4x", &red
, &green
, &blue
)!=3)
137 color_table
[0][i
] = red
;
138 color_table
[1][i
] = green
;
139 color_table
[2][i
] = blue
;
140 color_table
[3][i
] = 255;
141 } else if (strncmp(&(data
[line
][j
]), "None", 4)==0) {
142 color_table
[3][i
] = 0;
150 image
= RCreateImage(w
, h
, transp
);
152 sprintf(RErrorString
, "out of memory while converting XPM data");
162 for (i
=0; i
<h
; i
++) {
164 for (j
=0; j
<w
; j
++) {
165 color
= data
[line
][j
];
167 for (k
=0; k
<ccount
; k
++) {
168 if (symbol_table
[k
] == color
)
174 *(r
++) = color_table
[0][k
];
175 *(g
++) = color_table
[1][k
];
176 *(b
++) = color_table
[2][k
];
178 *(a
++) = color_table
[3][k
];
181 for (j
=0; j
<w
*2; j
++) {
182 color
= data
[line
][j
++];
183 color
|= data
[line
][j
];
185 for (k
=0; k
<ccount
; k
++) {
186 if (symbol_table
[k
] == color
)
192 *(r
++) = color_table
[0][k
];
193 *(g
++) = color_table
[1][k
];
194 *(b
++) = color_table
[2][k
];
196 *(a
++) = color_table
[3][k
];
208 sprintf(RErrorString
, "XPM data is not in the normalized format");
213 RDestroyImage(image
);
220 RLoadXPM(RContext
*context
, char *file
, int index
)
222 RImage
*image
= NULL
;
223 char line
[LINEWIDTH
+1];
225 unsigned char *color_table
[4];
226 unsigned short *symbol_table
;
227 unsigned char *r
, *g
, *b
, *a
;
230 unsigned short color
;
232 int w
, h
, ccount
, csize
;
235 f
= fopen(file
, "r");
237 sprintf(RErrorString
, "can't open XPM file \"%s\"", file
);
241 if (!fgets(line
, LINEWIDTH
, f
))
244 if (!fgets(line
, LINEWIDTH
, f
))
248 if (!fgets(line
, LINEWIDTH
, f
))
252 if (!fgets(line
, LINEWIDTH
, f
))
255 if (sscanf(line
, "\"%i %i %i %i\"", &w
, &h
, &ccount
, &csize
)!=4
256 || w
<= 0 || h
<= 0 || ccount
<= 0 || csize
<= 0)
259 if (csize
!=1 && csize
!=2)
262 color_table
[0] = alloca(ccount
);
263 color_table
[1] = alloca(ccount
);
264 color_table
[2] = alloca(ccount
);
265 color_table
[3] = alloca(ccount
);
266 symbol_table
= alloca(ccount
* sizeof(unsigned short));
268 bsize
= csize
* w
+ 16;
269 buffer
= alloca(bsize
);
271 if (!color_table
[0] || !color_table
[1] || !color_table
[2] ||
272 !color_table
[3] || !symbol_table
|| !bsize
) {
273 sprintf(RErrorString
, "out of memory while loading XPM file \"%s\"",
281 /* get color table */
282 for (i
=0; i
<ccount
; i
++) {
283 if (!fgets(line
, LINEWIDTH
, f
))
286 if (!fgets(line
, LINEWIDTH
, f
))
289 symbol_table
[i
] = line
[1];
291 symbol_table
[i
] |= line
[2]<<8;
294 while (line
[j
]!='#' && line
[j
]!='"' && line
[j
]!=0 && line
[j
]!='N') j
++;
297 unsigned int red
, green
, blue
;
301 while (line
[j
+k
]!='"' && line
[j
+k
]!=0) k
++;
303 if (sscanf(&(line
[j
]), "%2x%2x%2x", &red
, &green
, &blue
)!=3)
306 if (sscanf(&(line
[j
]), "%4x%4x%4x", &red
, &green
, &blue
)!=3)
314 color_table
[0][i
] = red
;
315 color_table
[1][i
] = green
;
316 color_table
[2][i
] = blue
;
317 color_table
[3][i
] = 255;
318 } else if (strncmp(&(line
[j
]), "None", 4)==0) {
319 color_table
[3][i
] = 0;
326 image
= RCreateImage(w
, h
, transp
);
328 sprintf(RErrorString
, "out of memory while loading XPM file \"%s\"",
340 for (i
=0; i
<h
; i
++) {
341 if (!fgets(buffer
, bsize
, f
))
344 if (!fgets(buffer
, bsize
, f
))
348 for (j
=1; j
<=w
; j
++) {
351 for (k
=0; k
<ccount
; k
++) {
352 if (symbol_table
[k
] == color
)
358 *(r
++) = color_table
[0][k
];
359 *(g
++) = color_table
[1][k
];
360 *(b
++) = color_table
[2][k
];
362 *(a
++) = color_table
[3][k
];
365 for (j
=1; j
<=w
*2; j
++) {
367 color
|= buffer
[j
] << 8;
369 for (k
=0; k
<ccount
; k
++) {
370 if (symbol_table
[k
] == color
)
377 *(r
++) = color_table
[0][k
];
378 *(g
++) = color_table
[1][k
];
379 *(b
++) = color_table
[2][k
];
381 *(a
++) = color_table
[3][k
];
393 sprintf(RErrorString
, "XPM file \"%s\" is not in the normalized format", file
);
399 RDestroyImage(image
);
403 sprintf(RErrorString
, "bad XPM file \"%s\"", file
);
409 RDestroyImage(image
);