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 0
rws@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!cheeks
mikey@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