1 /* xpm-ximage.c --- converts XPM data to an XImage for use with OpenGL.
2 * xscreensaver, Copyright (c) 1998, 2001, 2002 Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
12 * Alpha channel support by Eric Lassauge <lassauge@mail.dotcom.fr>.
22 extern char *progname;
25 #if defined(HAVE_GDK_PIXBUF)
27 # include <gdk-pixbuf/gdk-pixbuf.h>
28 # include <gdk-pixbuf/gdk-pixbuf-xlib.h>
31 /* Returns an XImage structure containing the bits of the given XPM image.
32 This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the
33 extra byte set to either 0xFF or 0x00 (based on the XPM file's mask.)
35 The Display and Visual arguments are used only for creating the XImage;
36 no bits are pushed to the server.
38 The Colormap argument is used just for parsing color names; no colors
41 This is the gdk_pixbuf version of this function.
44 xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap,
49 static int initted = 0;
53 gdk_pixbuf_xlib_init (dpy, DefaultScreen (dpy));
54 xlib_rgb_init (dpy, DefaultScreenOfDisplay (dpy));
59 ? gdk_pixbuf_new_from_file (filename)
60 : gdk_pixbuf_new_from_xpm_data ((const char **) xpm_data));
64 int w = gdk_pixbuf_get_width (pb);
65 int h = gdk_pixbuf_get_height (pb);
66 guchar *row = gdk_pixbuf_get_pixels (pb);
67 int stride = gdk_pixbuf_get_rowstride (pb);
68 int chan = gdk_pixbuf_get_n_channels (pb);
71 image = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0, w, h, 32, 0);
72 image->data = (char *) malloc(h * image->bytes_per_line);
75 fprintf (stderr, "%s: out of memory (%d x %d)\n", progname, w, h);
79 for (y = 0; y < h; y++)
81 int y2 = (h-1-y); /* Texture maps are upside down. */
84 for (x = 0; x < w; x++)
86 unsigned long rgba = 0;
89 rgba = ((0xFF << 24) |
96 rgba = ((0xFF << 24) |
103 rgba = ((i[3] << 24) |
113 XPutPixel (image, x, y2, rgba);
117 /* gdk_pixbuf_unref (pb); -- #### does doing this free colors? */
123 fprintf (stderr, "%s: unable to load %s\n", progname, filename);
128 fprintf (stderr, "%s: unable to initialize builtin texture\n", progname);
134 #elif defined(HAVE_XPM)
139 #include <X11/Intrinsic.h>
141 #include <X11/Xutil.h>
145 #define countof(x) (sizeof((x))/sizeof((*x)))
150 union { int i; char c[sizeof(int)]; } u;
156 /* The libxpm version of this function...
159 xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap,
160 const char *filename, char **xpm_data)
162 /* All we want to do is get RGB data out of the XPM file built in to this
163 program. This is a pain, because there is no way (as of XPM version
164 4.6, at least) to get libXpm to make an XImage without also allocating
165 colors with XAllocColor. So, instead, we create an XpmImage and parse
166 out the RGB values of the pixels ourselves; and construct an XImage
167 by hand. Regardless of the depth of the visual we're using, this
168 XImage will have 32 bits per pixel, 8 each per R, G, and B. We put
169 0xFF or 0x00 in the fourth (alpha) slot, depending on the file's mask.
175 int transparent_color_index = -1;
180 memset (&xpm_image, 0, sizeof(xpm_image));
181 memset (&xpm_info, 0, sizeof(xpm_info));
186 if (! XpmReadFileToData ((char *) filename, &xpm_data))
188 fprintf (stderr, "%s: unable to read XPM file %f\n",
194 result = XpmCreateXpmImageFromData (xpm_data, &xpm_image, &xpm_info);
195 if (result != XpmSuccess)
197 fprintf(stderr, "%s: unable to parse xpm data (%d).\n", progname,
202 if (xpm_image.ncolors > countof(colors))
204 fprintf (stderr, "%s: too many colors (%d) in XPM.\n",
205 progname, xpm_image.ncolors);
209 ximage = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0,
210 xpm_image.width, xpm_image.height, 32, 0);
212 bpl = ximage->bytes_per_line;
215 ximage->data = (char *) malloc(xpm_image.height * bpl);
217 /* Parse the colors in the XPM into RGB values. */
218 for (i = 0; i < xpm_image.ncolors; i++)
220 const char *c = xpm_image.colorTable[i].c_color;
223 fprintf(stderr, "%s: bogus color table? ($d)\n", progname, i);
226 else if (!strncasecmp (c, "None", 4))
228 transparent_color_index = i;
229 colors[transparent_color_index].red = 0xFF;
230 colors[transparent_color_index].green = 0xFF;
231 colors[transparent_color_index].blue = 0xFF;
233 else if (!XParseColor (dpy, cmap, c, &colors[i]))
235 fprintf(stderr, "%s: unparsable color: %s\n", progname, c);
240 /* Translate the XpmImage to an RGB XImage. */
242 int rpos, gpos, bpos, apos; /* bitfield positions */
244 /* Note that unlike X, which is endianness-agnostic (since any XImage
245 can have its own specific bit ordering, with the server reversing
246 things as necessary) OpenGL pretends everything is client-side, so
247 we need to pack things in the right order for the client machine.
250 rpos = 24, gpos = 16, bpos = 8, apos = 0;
252 rpos = 0, gpos = 8, bpos = 16, apos = 24;
254 for (y = 0; y < xpm_image.height; y++)
256 int y2 = (xpm_image.height-1-y); /* Texture maps are upside down. */
258 unsigned int *oline = (unsigned int *) (ximage->data + (y * bpl));
259 unsigned int *iline = (unsigned int *) (xpm_image.data + (y2 * wpl));
261 for (x = 0; x < xpm_image.width; x++)
263 XColor *c = &colors[iline[x]];
264 int alpha = ((iline[x] == transparent_color_index) ? 0x00 : 0xFF);
265 oline[x] = (((c->red >> 8) << rpos) |
266 ((c->green >> 8) << gpos) |
267 ((c->blue >> 8) << bpos) |
273 /* I sure hope these only free the contents, and not the args. */
274 #if 0 /* Apparently not? Gotta love those well-documented APIs! */
275 XpmFreeXpmImage (&xpm_image);
276 XpmFreeXpmInfo (&xpm_info);
283 #else /* !HAVE_XPM && !HAVE_GDK_PIXBUF */
286 xpm_to_ximage_1 (Display *dpy, Visual *visual, Colormap cmap,
287 const char *filename, char **xpm_data)
289 fprintf(stderr, "%s: not compiled with XPM or Pixbuf support.\n", progname);
293 #endif /* !HAVE_XPM */
296 /* Returns an XImage structure containing the bits of the given XPM image.
297 This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the
298 extra byte set to either 0xFF or 0x00 (based on the XPM file's mask.)
300 The Display and Visual arguments are used only for creating the XImage;
301 no bits are pushed to the server.
303 The Colormap argument is used just for parsing color names; no colors
307 xpm_to_ximage (Display *dpy, Visual *visual, Colormap cmap, char **xpm_data)
309 return xpm_to_ximage_1 (dpy, visual, cmap, 0, xpm_data);
314 xpm_file_to_ximage (Display *dpy, Visual *visual, Colormap cmap,
315 const char *filename)
317 return xpm_to_ximage_1 (dpy, visual, cmap, filename, 0);