cheeks@edsr.eds.com (Mark Costlow) (05/28/91)
I have an Xlib application in which I want to cycle a range of colors. In
one mode, I just build a bunch of color maps and cycle through those. That
works fine. What I *haven't* been able to get working is a mode where the
program allocates some color cells from the default color map and causes
only those cells to cycle. This mode would let me run the application and
still see my other windows. (I am only concerned with pseudocolor displays
at the moment).
I use XAllocColorCells() to allocate the cells and then use XStoreColors()
to store the RGB values that I choose. When it's time to cycle the colors,
I shift the ".pixel" member of all color definitions in my array of
XColors, and call XStoreColors() again to redefine the pixel indices.
This does not work (*) ... the colors in the window never change. I've
looked through the FAQ and in all the Xlib books I can find and I haven't
found anything which indicates that this scheme should not work. Is there
something very basic that I'm overlooking?
(*) - I've run this program on several types of Sparcs and on HP9000s300
machines. It behaves the same on all machines EXCEPT Sparcs with GX boards
-- on those machines the program works as I would expect it to. Sparcs
with CG3s don't work though. In all cases, the machines are running X11R4
from MIT with most or all of the MIT patches.
Following my .signature is a small test program which demonstrates my
problem. The two functions of interest are GetColors() which allocates the
color cells, and CycleColors() which attempts to cycle them. I would
REALLY appreciate any insight (or kicks in the head) that anyone out in
netland has.
Thanks,
Mark
--
cheeks@edsr.eds.com or ...uunet!edsr!cheeks
#---------------------------------- cut here ----------------------------------
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Mark Costlow <cheeks@argon> on Mon May 27 17:56:44 1991
#
# This archive contains:
# Makefile test.c
#
# Existing files will not be overwritten.
# Error checking via wc(1) will be performed.
LANG=""; export LANG
PATH=/bin:/usr/bin:$PATH; export PATH
if test -f Makefile
then
echo Ok to overwrite existing file Makefile\?
read answer
case "$answer" in
[yY]*) echo Proceeding;;
*) echo Aborting; exit 1;;
esac
rm -f Makefile
if test -f Makefile
then
echo Error: could not remove Makefile, aborting
exit 1
fi
fi
echo x - Makefile
cat >Makefile <<'@EOF'
CC = gcc
CFLAGS = -g
.c.o:
$(CC) $(CFLAGS) -c $<
PROGS = test
all: $(PROGS)
test: test.o
$(CC) $(CFLAGS) -o test test.o -lX11 -lm
clean:
rm -f core *.o $(PROGS)
@EOF
set `wc -lwc <Makefile`
if test $1$2$3 != 1531170
then
echo ERROR: wc results of Makefile are $* should be 15 31 170
fi
chmod 664 Makefile
if test -f test.c
then
echo Ok to overwrite existing file test.c\?
read answer
case "$answer" in
[yY]*) echo Proceeding;;
*) echo Aborting; exit 1;;
esac
rm -f test.c
if test -f test.c
then
echo Error: could not remove test.c, aborting
exit 1
fi
fi
echo x - test.c
cat >test.c <<'@EOF'
/*
* test.c -- test color cycling with X11.
*
* Mark Costlow
* cheeks@edsr.eds.com
* May 27, 1991
*/
#include <stdio.h>
#include <math.h>
/* X-windows includes */
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
typedef unsigned long Pixel;
typedef unsigned char byte;
Display *display;
Visual *visual = NULL;
Status status;
unsigned long wp, bp; /* pixel values for black & white */
int screen, nplanes, ncolors;
XEvent event;
XExposeEvent *expose;
XSetWindowAttributes attrib;
GC gc;
XGCValues gc_val;
XSizeHints sizehints;
Window imagewin; /* window ID for image */
XImage *image = NULL;
Colormap cmap;
Pixel pixels[256];
XColor *colors;
int num_colors = 0;
int global_x, global_y;
byte *buf;
#define MAXI 65535
void remap(byte *buf, int x, int y, Pixel *pixels)
{
int i, j;
for(i = 0; i < y; i++)
for(j = 0; j < x; j++)
{
*buf = (byte)pixels[*buf];
buf++;
}
}
/*
* This code is partially based on a routine in Jim Frost's xloadimage.
*
* It does this:
* 1. grab the server so no one can goof with the colormap.
* 2. count the available colors using XAllocColorCells.
* 3. free the colors we just allocated.
* 4. allocate the colors again with XAllocColorCells
* 6. ungrab the server and continue
*/
void GetColors(int nplanes)
{
int i;
int ncolors = 1 << nplanes;
double rstep, rf;
double gstep, gf;
double bstep, bf;
cmap = DefaultColormap(display, screen);
XGrabServer(display);
for (i= 0; i < ncolors; i++) /* count entries we got */
if (! XAllocColorCells(display, cmap, False, NULL, 0, pixels + i, 1))
break;
if (i > 0)
XFreeColors(display, cmap, pixels, i, 0);
if (i <= 2)
{
fprintf(stderr, "Cannot fit into default colormap, aborting.\n");
fflush(stderr);
exit(1);
}
num_colors = ncolors = i;
colors = (XColor *) malloc(num_colors * sizeof(XColor));
if (! XAllocColorCells(display, cmap, False, NULL, 0, pixels, num_colors))
{
fprintf(stderr, "Cannot allocate color cells\n");
exit(1);
}
/*
* Generate a rainbow of colors
*/
rstep = (double) ( (M_PI * (double)nplanes) / (double) ncolors);
gstep = (double) ( (M_PI_4 * (double)nplanes) / (double) ncolors);
bstep = (double) ( (M_PI_2 * (double)nplanes) / (double) ncolors);
rf = M_PI;
gf = 2 * M_PI;
bf = M_PI_2;
for (i= 0; i < ncolors; i++)
{
double scale = MAXI / 2.0;
double sin(double);
colors[i].pixel = pixels[i];
colors[i].red = (int)((scale * sin(rf)) + scale);
colors[i].green = (int)((scale * sin(gf)) + scale);
colors[i].blue = (int)((scale * sin(bf)) + scale);
rf += rstep;
gf += gstep;
bf += bstep;
}
XStoreColors(display, cmap, colors, num_colors);
remap(buf, global_x, global_y, pixels);
XUngrabServer(display);
}
/*
* Cycle the indices in the default color map. This is done by rotating
* the .pixel member in each color structure, and then calling XStoreColors
* with the array of colors.
*/
void CycleColors()
{
int i, j;
/*
* rotate the colors
*/
j = colors[0].pixel;
for (i = 0; i < num_colors-1; i++)
colors[i].pixel = colors[i+1].pixel;
colors[num_colors-1].pixel = j;
XStoreColors(display, cmap, colors, num_colors);
XSync(display, False);
}
void InitX(char *disp, int x, int y)
{
char win_name[64];
strcpy(win_name, "colortest");
/* Open connection to the X11 server and set defaults */
if ((display = XOpenDisplay(disp)) == NULL)
{
fprintf(stderr,"Could not open display.\n");
exit(1);
}
screen = XDefaultScreen(display);
visual = XDefaultVisual(display, screen);
nplanes = XDisplayPlanes(display, screen);
bp = BlackPixel(display, screen);
wp = WhitePixel(display, screen);
/*
* Set window manager hints
*/
sizehints.flags = PPosition | PSize | PMinSize | PMaxSize;
sizehints.width = sizehints.min_width = x;
sizehints.max_width = x;
sizehints.height = sizehints.min_height = y;
sizehints.max_height = y;
sizehints.x = sizehints.y = 0;
GetColors(nplanes);
attrib.background_pixel = wp;
attrib.border_pixel = bp;
attrib.event_mask = (ExposureMask | LeaveWindowMask |
ButtonPressMask | ButtonReleaseMask |
ColormapChangeMask | Button1MotionMask |
EnterWindowMask);
attrib.cursor = XCreateFontCursor(display, XC_top_left_arrow);
/*
* Create the window.
*/
imagewin = XCreateWindow(display, RootWindow(display, screen), 0, 0,
x, y, 5, XDefaultDepth(display, screen),
InputOutput, visual,
(CWBackPixel|CWEventMask|CWCursor|CWBorderPixel),
&attrib);
/*
* Install properties for the window.
*/
XSetStandardProperties(display, imagewin, win_name, win_name, NULL,
NULL, NULL, &sizehints);
XSetIconName(display, imagewin, "colortest");
/* Now finally map the window ... */
XMapWindow(display, imagewin);
/* Create a Graphics Context. */
gc_val.foreground = bp;
gc_val.background = wp;
gc = XCreateGC(display, imagewin, GCForeground | GCBackground , &gc_val);
/* select which input events to honor */
XSelectInput(display, imagewin, (ExposureMask | KeyPressMask));
/* Wait for first expose event */
XNextEvent(display, &event);
while (event.type != Expose)
XNextEvent(display, &event);
}
void show_pic(byte *buf, int x, int y)
{
image = XCreateImage(display, visual, nplanes, ZPixmap, 0, (char *)buf,
x, y, 8, 0);
XPutImage(display, imagewin, gc, image, 0, 0, 0, 0, x, y);
XSync(display, False);
}
int main (int argc, char **argv)
{
char *display = NULL;
int x = 64, y = 64, i, j;
byte *p;
global_x = x;
global_y = y;
p = buf = (byte *)malloc(x * y);
if (!buf)
{
fprintf(stderr, "%s: malloc failure.\n", argv[0]);
exit(1);
}
/* This should leave buf containing horizontal bands of color. */
for(i = 0; i < y; i++)
for(j = 0; j < x; j++)
*p++ = i;
InitX(display, x, y);
show_pic(buf, x, y);
while(1)
{
usleep(50000);
CycleColors();
}
return 0;
}
@EOF
set `wc -lwc <test.c`
if test $1$2$3 != 2648346299
then
echo ERROR: wc results of test.c are $* should be 264 834 6299
fi
chmod 664 test.c
exit 0rws@expo.lcs.mit.EDU (Bob Scheifler) (05/28/91)
I use XAllocColorCells() to allocate the cells and then use XStoreColors()
to store the RGB values that I choose.
RTFM. You aren't setting the XColor.flags components to DoRed|DoGreen|DoBlue.cheeks@tantalum.UUCP (Mark Costlow) (05/28/91)
me> I use XAllocColorCells() to allocate the cells and then use XStoreColors()
me> to store the RGB values that I choose.
rws> RTFM. You aren't setting the XColor.flags components to
rws> DoRed|DoGreen|DoBlue.
Arggh! I don't know how I managed to remove that line ... thanks for that
kick in the head.
>>Chx
cheeks@edsr.eds.com or ...uunet!edsr!cheeksmikey@eukanuba.wpd.sgi.com (Mike Yang) (05/29/91)
XStoreColors only changes the components you specify in the flags
member of the XColor structure. You never set this field. It should
probably be (DoRed | DoGreen | DoBlue).
-----------------------------------------------------------------------
Mike Yang Silicon Graphics, Inc.
mikey@sgi.com 415/335-1786