1 /* +-------------------------------------------------------------------+ */
2 /* | Copyright 1993, David Koblas (koblas@netcom.com)		       | */
3 /* |								       | */
4 /* | Permission to use, copy, modify, and to distribute this software  | */
5 /* | and its documentation for any purpose is hereby granted without   | */
6 /* | fee, provided that the above copyright notice appear in all       | */
7 /* | copies and that both that copyright notice and this permission    | */
8 /* | notice appear in supporting documentation.	 There is no	       | */
9 /* | representations about the suitability of this software for	       | */
10 /* | any purpose.  this software is provided "as is" without express   | */
11 /* | or implied warranty.					       | */
12 /* |								       | */
13 /* +-------------------------------------------------------------------+ */
14 
15 /* $Id: readWriteXPM.c,v 1.21 2005/03/20 20:15:34 demailly Exp $ */
16 
17 #include <stdio.h>
18 
19 #include <X11/Intrinsic.h>
20 #include <X11/xpm.h>
21 
22 #include "xpaint.h"
23 #include "messages.h"
24 #include "image.h"
25 #include "rwTable.h"
26 
27 extern int file_transparent;
28 extern void Notice(Widget w,...);
29 
AlphaWarning(char * format,int mode)30 void AlphaWarning(char *format, int mode)
31 {
32     Notice((Global.canvas)? Global.canvas : Global.toplevel,
33             msgText[WARNING_ALPHA_NO_SUPPORT+mode], format);
34 }
35 
WriteXPM(char * file,Image * image)36 int WriteXPM(char *file, Image * image)
37 {
38     XpmAttributes attr;
39     Display *dpy = Global.display;
40 
41     if (!image) return 1;
42 
43     if (image->alpha) AlphaWarning("XPM", 1);
44 
45     if (!image->sourcePixmap) return 1;
46     attr.valuemask = XpmColormap;
47     if (image->sourceColormap)
48         attr.colormap = (Colormap) image->sourceColormap;
49     else
50         attr.colormap = DefaultColormap(dpy, DefaultScreen(dpy));
51 
52     return (XpmWriteFileFromPixmap(Global.display, file,
53 	      image->sourcePixmap, image->sourceMask, &attr) != XpmSuccess);
54 }
55 
TestXPM(char * file)56 int TestXPM(char *file)
57 {
58     FILE *fd = fopen(file, "r");
59     char buf[40];
60     int i, n, ret = 0;
61     int cstart = False;
62 
63     if (fd == NULL)
64 	return 0;
65 
66     n = fread(buf, sizeof(char), sizeof(buf), fd);
67 
68     for (i = 0; i < n && ret == 0; i++) {
69 	if (!cstart) {
70 	    if (buf[i] == '/' && buf[i + 1] == '*')
71 		cstart = True;
72 	} else {
73 	    if (buf[i] == 'X' && buf[i + 1] == 'P' && buf[i + 2] == 'M')
74 		ret = 1;
75 	}
76     }
77 
78     fclose(fd);
79     return ret;
80 }
81 
ReadXPM(char * file)82 Image * ReadXPM(char *file)
83 {
84     Display *dpy = Global.display;
85     XImage *xim, *mim = NULL;
86     int x, y, i;
87     Image *image;
88     XpmAttributes attr;
89     XpmColorSymbol bg;
90     XColor bgcolor;
91     XColor *col;
92     unsigned char *ucp, *ump = NULL;
93     unsigned short *usp;
94     Colormap cmap = DefaultColormap(dpy, DefaultScreen(dpy));
95     int status;
96 
97     bgcolor.flags = DoRed | DoGreen | DoBlue;
98     bgcolor.red = Global.bg[0]*257;
99     bgcolor.green = Global.bg[1]*257;
100     bgcolor.blue = Global.bg[2]*257;
101     XAllocColor(dpy, cmap, &bgcolor);
102     attr.valuemask = XpmColormap | XpmReturnPixels | XpmColorSymbols;
103     attr.colormap =  cmap;
104     attr.numsymbols = 1;
105     attr.colorsymbols = &bg;
106     bg.pixel = bgcolor.pixel;
107     bg.name = NULL;
108     bg.value = "None";
109 
110     if ((status = XpmReadFileToImage(dpy, file, &xim, &mim, &attr)) != XpmSuccess) {
111 	switch (status) {
112 	case XpmColorError:
113 	    RWSetMsg("XPM Color Error");
114 	    break;
115 	case XpmSuccess:
116 	    RWSetMsg("Success, shouldn't have error & success");
117 	    break;
118 	case XpmOpenFailed:
119 	    RWSetMsg("XPM Open Failed");
120 	    break;
121 	case XpmFileInvalid:
122 	    RWSetMsg("File Invalid");
123 	    break;
124 	case XpmNoMemory:
125 	    RWSetMsg("Not enough memory");
126 	    break;
127 	case XpmColorFailed:
128 	    RWSetMsg("Unable to allocate color");
129 	    break;
130 	}
131 	XpmFreeAttributes(&attr);
132 	return NULL;
133     }
134 
135     image = ImageNewCmap(attr.width, attr.height, attr.npixels);
136     ucp = (unsigned char *) image->data;
137     usp = (unsigned short *) image->data;
138 
139     col = (XColor *) XtMalloc(sizeof(XColor) * attr.npixels);
140     for (i = 0; i < attr.npixels; i++) {
141 	col[i].pixel = attr.pixels[i];
142 	col[i].flags = DoRed | DoGreen | DoBlue;
143     }
144     XQueryColors(dpy, cmap, col, attr.npixels);
145 
146     if (mim != NULL) {
147         file_transparent = 1;
148 	ImageMakeMask(image);
149 	ump = image->alpha;
150     }
151 
152     for (i = 0; i < attr.npixels; i++)
153 	ImageSetCmap(image, i, col[i].red>>8, col[i].green>>8, col[i].blue>>8);
154 
155     for (y = 0; y < xim->height; y++) {
156 	for (x = 0; x < xim->width; x++) {
157 	    Pixel p;
158 
159 	    if (mim != NULL) {
160 		Pixel f = XGetPixel(mim, x, y);
161 
162 		if (!(*ump++ = (f?255:0))) {
163 		    if (attr.npixels > 256)
164 			*usp++ = 0;
165 		    else
166 			*ucp++ = 0;
167 		    continue;
168 		}
169 	    }
170 	    p = XGetPixel(xim, x, y);
171 
172 	    for (i = 0; i < attr.npixels && col[i].pixel != p; i++);
173 
174 	    if (attr.npixels > 256)
175 		*usp++ = i;
176 	    else
177 		*ucp++ = i;
178 	}
179     }
180 
181     XtFree((XtPointer) col);
182     XDestroyImage(xim);
183     XpmFreeAttributes(&attr);
184 
185     return image;
186 }
187