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
53 typedef struct XPMColor
{
58 struct XPMColor
*next
;
61 #define I2CHAR(i) ((i)<12 ? (i)+'0' : ((i)<38 ? (i)+'A'-12 : (i)+'a'-38))
62 #define CINDEX(xpmc) (((unsigned)(xpmc)->red)<<16|((unsigned)(xpmc)->green)<<8|((unsigned)(xpmc)->blue))
64 static XPMColor
*lookfor(XPMColor
* list
, int index
)
69 for (; list
!= NULL
; list
= list
->next
) {
70 if (CINDEX(list
) == index
)
77 * Looks for the color in the colormap and inserts if it is not found.
79 * list is a binary search list. The unbalancing problem is just ignored.
81 * Returns False on error
83 static Bool
addcolor(XPMColor
** list
, unsigned r
, unsigned g
, unsigned b
, int *colors
)
89 index
= r
<< 16 | g
<< 8 | b
;
91 tmpc
= lookfor(*list
, index
);
96 newc
= malloc(sizeof(XPMColor
));
100 RErrorCode
= RERR_NOMEMORY
;
116 static char *index2str(char *buffer
, int index
, int charsPerPixel
)
120 for (i
= 0; i
< charsPerPixel
; i
++) {
121 buffer
[i
] = I2CHAR(index
& 63);
129 static void outputcolormap(FILE * file
, XPMColor
* colormap
, int charsPerPixel
)
137 for (index
= 0; colormap
!= NULL
; colormap
= colormap
->next
, index
++) {
138 colormap
->index
= index
;
139 fprintf(file
, "\"%s c #%02x%02x%02x\",\n",
140 index2str(buf
, index
, charsPerPixel
), colormap
->red
, colormap
->green
, colormap
->blue
);
144 static void freecolormap(XPMColor
* colormap
)
149 tmp
= colormap
->next
;
155 /* save routine is common to internal support and library support */
156 Bool
RSaveXPM(RImage
* image
, const char *filename
)
162 XPMColor
*colormap
= NULL
;
166 unsigned char *r
, *g
, *b
, *a
;
170 file
= fopen(filename
, "wb+");
172 RErrorCode
= RERR_OPEN
;
176 fprintf(file
, "/* XPM */\n");
178 fprintf(file
, "static char *image[] = {\n");
183 if (image
->format
== RRGBAFormat
)
188 /* first pass: make colormap for the image */
191 for (y
= 0; y
< image
->height
; y
++) {
192 for (x
= 0; x
< image
->width
; x
++) {
193 if (!a
|| *a
> 127) {
194 if (!addcolor(&colormap
, *r
, *g
, *b
, &colorCount
)) {
212 while ((1 << charsPerPixel
* 6) < colorCount
)
215 /* write header info */
216 fprintf(file
, "\"%i %i %i %i\",\n", image
->width
, image
->height
, colorCount
, charsPerPixel
);
218 /* write colormap data */
220 for (i
= 0; i
< charsPerPixel
; i
++)
224 fprintf(file
, "\"%s c None\",\n", transp
);
227 outputcolormap(file
, colormap
, charsPerPixel
);
232 if (image
->format
== RRGBAFormat
)
238 for (y
= 0; y
< image
->height
; y
++) {
242 for (x
= 0; x
< image
->width
; x
++) {
244 if (!a
|| *a
> 127) {
245 tmpc
= lookfor(colormap
, (unsigned)*r
<< 16 | (unsigned)*g
<< 8 | (unsigned)*b
);
247 fprintf(file
, "%s", index2str(buf
, tmpc
->index
, charsPerPixel
));
249 fprintf(file
, "%s", transp
);
264 if (y
< image
->height
- 1)
265 fprintf(file
, "\",\n");
267 fprintf(file
, "\"};\n");
274 if (ok
&& errno
== ENOSPC
) {
275 RErrorCode
= RERR_WRITE
;
278 freecolormap(colormap
);
280 return ok
? True
: False
;