Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!elroy.jpl.nasa.gov!ncar!unmvax!bbx!tantalum!tantalum!cheeks From: cheeks@edsr.eds.com (Mark Costlow) Newsgroups: comp.windows.x Subject: Need help cycling colors with X11 Keywords: colors cycle Message-ID: <1991May28.001741.29301@edsr.eds.com> Date: 28 May 91 00:17:41 GMT Sender: usenet@edsr.eds.com Reply-To: cheeks@edsr.eds.com Followup-To: comp.windows.x Organization: EDS Research Lines: 382 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 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 test.c <<'@EOF' /* * test.c -- test color cycling with X11. * * Mark Costlow * cheeks@edsr.eds.com * May 27, 1991 */ #include #include /* X-windows includes */ #include #include #include #include #include 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