1 /* xpm-ximage.c --- converts XPM data to an XImage for use with OpenGL.
2 * xscreensaver, Copyright (c) 1998 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
19 #include <X11/Intrinsic.h>
21 extern char *progname;
23 #ifdef HAVE_XPM /* whole file */
25 #include <X11/Xutil.h>
31 union { int i; char c[sizeof(int)]; } u;
37 /* Returns an XImage structure containing the bits of the given XPM image.
38 This XImage will be 32 bits per pixel, 8 each per R, G, and B, with the
39 extra byte set to 0xFF.
41 The Display and Visual arguments are used only for creating the XImage;
42 no bits are pushed to the server.
44 The Colormap argument is used just for parsing color names; no colors
48 xpm_to_ximage (Display *dpy, Visual *visual, Colormap cmap, char **xpm_data)
50 /* All we want to do is get RGB data out of the XPM file built in to this
51 program. This is a pain, because there is no way (as of XPM version
52 4.6, at least) to get libXpm to make an XImage without also allocating
53 colors with XAllocColor. So, instead, we create an XpmImage and parse
54 out the RGB values of the pixels ourselves; and construct an XImage
55 by hand. Regardless of the depth of the visual we're using, this
56 XImage will have 32 bits per pixel, 8 each per R, G, and B. We put
57 0xFF in the fourth slot, as GL will interpret that as "alpha".
67 memset (&xpm_image, 0, sizeof(xpm_image));
68 memset (&xpm_info, 0, sizeof(xpm_info));
69 result = XpmCreateXpmImageFromData (xpm_data, &xpm_image, &xpm_info);
70 if (result != XpmSuccess)
72 fprintf(stderr, "%s: unable to parse xpm data (%d).\n", progname,
77 ximage = XCreateImage (dpy, visual, 32, ZPixmap, 0, 0,
78 xpm_image.width, xpm_image.height, 32, 0);
80 bpl = ximage->bytes_per_line;
83 ximage->data = (char *) malloc(xpm_image.height * bpl);
85 /* Parse the colors in the XPM into RGB values. */
86 for (i = 0; i < xpm_image.ncolors; i++)
87 if (!XParseColor(dpy, cmap, xpm_image.colorTable[i].c_color, &colors[i]))
89 fprintf(stderr, "%s: unparsable color: %s\n", progname,
90 xpm_image.colorTable[i].c_color);
94 /* Translate the XpmImage to an RGB XImage. */
96 int rpos, gpos, bpos, apos; /* bitfield positions */
98 /* Note that unlike X, which is endianness-agnostic (since any XImage
99 can have its own specific bit ordering, with the server reversing
100 things as necessary) OpenGL pretends everything is client-side, so
101 we need to pack things in the right order for the client machine.
104 rpos = 24, gpos = 16, bpos = 8, apos = 0;
106 rpos = 0, gpos = 8, bpos = 16, apos = 24;
108 for (y = 0; y < xpm_image.height; y++)
110 int y2 = (xpm_image.height-1-y); /* Texture maps are upside down. */
112 unsigned int *oline = (unsigned int *) (ximage->data + (y * bpl));
113 unsigned int *iline = (unsigned int *) (xpm_image.data + (y2 * wpl));
115 for (x = 0; x < xpm_image.width; x++)
117 XColor *c = &colors[iline[x]];
118 /* pack it as RGBA */
119 oline[x] = (((c->red >> 8) << rpos) |
120 ((c->green >> 8) << gpos) |
121 ((c->blue >> 8) << bpos) |
127 /* I sure hope these only free the contents, and not the args. */
128 #if 0 /* Apparently not? Gotta love those well-documented APIs! */
129 XpmFreeXpmImage (&xpm_image);
130 XpmFreeXpmInfo (&xpm_info);
137 #else /* !HAVE_XPM */
140 xpm_to_ximage (char **xpm_data)
142 fprintf(stderr, "%s: not compiled with XPM support.\n", progname);
146 #endif /* !HAVE_XPM */