[comp.windows.x] Colormap question

rusty@BOSCO.BERKELEY.EDU (06/09/88)

How does one go about printing out the "default" color map?  I'm on a
sun 3/60 (cgfour) running x11r2.  My code looks something like

	dpy = XOpenDisplay(NULL));
	scr = DefaultScreen(dpy);
	scrn = XScreenOfDisplay(dpy, scr);
	nplanes = XDefaultDepth(dpy, scr);
	ncells = XCellsOfScreen(scrn);

	XAllocColorCells(dpy, XDefaultColormap(dpy, scr), 0, plane_masks,
			 nplanes, cmap_cells, ncells);

	for (i = 0; i < nplanes; i++)
		printf("plane_masks[%d] = 0x%x\n", i, plane_masks[i]);
	for (i = 0; i < ncells; i++)
		printf("cmap_cells[%d] = 0x%x\n", i, cmap_cells[i]);

If I run my program after starting up the server all I get is 0's.

The cgfour has a 256 cell color map and I just want to display a 16 by
16 grid with each color of the color map in a square.

Is there a good book that explains the concepts, principals, etc. of
color maps?

jim@EXPO.LCS.MIT.EDU (Jim Fulton) (06/10/88)

There are a couple of problems with your example.  One is relatively minor and
the other is the reason why it failed. 

>         nplanes = XDefaultDepth (dpy, scr);
>         ncells = XCellsOfScreen (scrn);
>
>         XAllocColorCells(dpy, XDefaultColormap(dpy, scr), 0, plane_masks,
>                         nplanes, cmap_cells, ncells);

First off, the definitions of nplanes and ncells should probably be:

          nplanes = DisplayPlanes (dpy, scr);
	  ncells = DisplayCells (dpy, scr);

And, you'll have to make sure that plane_masks and cmap_cells are arrays
containing nplanes and ncells entries each.

But, in any case, it won't work.

You are trying to allocate ncells*2^nplanes pixels (which on a display with
256 color cells and 8 planes will be 65536) out of a colormap that has at most
254 entries remaining (since BlackPixel and WhitePixel have been allocated
by the server)!  The reason why you are getting zeros is because the request
is failing and you're not checking the return status.

What you'll probably want to do is to try to allocate 256 pixels (through some
combination of cells and planes), and, if that fails, create a new colormap
using XCreateColormap with something along the lines of:

	visual = /* select the proper visual if DefaultVisual isn't right */
	cmap = XCreateColormap (dpy, RootWindow (dpy, scr), visual, All);

The visual determines what sort of colormap should be allocated.  This is 
necessary for running on displays that provide more than one type of window
(for example: 24 bit DirectColor and 16 bit PseudoColor, or 8 bit PseudoColor
and 1 bit StaticGray).

Once you have a colormap with all of the entries allocated, you can set them
to be whatever you want.  Then, whenever you are ready, you can install the
colormap.  Note that this will cause the rest of the screen to go "technicolor"
if there is only one colormap.  The Inter-Client Communications Conventions
Manual describes installing colormaps in more detail (since it is something
that affects the entire screen).

Jim Fulton
MIT X Consortium

august@ole.UUCP (Augustine Chan) (06/16/88)

In article <8806091630.AA02763@velveeta> rusty@cartan.berkeley.edu writes:
>How does one go about printing out the "default" color map?  I'm on a
>sun 3/60 (cgfour) running x11r2.  My code looks something like
>
>	dpy = XOpenDisplay(NULL));
>	scr = DefaultScreen(dpy);
>	scrn = XScreenOfDisplay(dpy, scr);
>	nplanes = XDefaultDepth(dpy, scr);
>	ncells = XCellsOfScreen(scrn);
>
>	XAllocColorCells(dpy, XDefaultColormap(dpy, scr), 0, plane_masks,
>			 nplanes, cmap_cells, ncells);
>
>	for (i = 0; i < nplanes; i++)
>		printf("plane_masks[%d] = 0x%x\n", i, plane_masks[i]);
>	for (i = 0; i < ncells; i++)
>		printf("cmap_cells[%d] = 0x%x\n", i, cmap_cells[i]);
>
>If I run my program after starting up the server all I get is 0's.
>
>The cgfour has a 256 cell color map and I just want to display a 16 by
>16 grid with each color of the color map in a square.
>
>Is there a good book that explains the concepts, principals, etc. of
>color maps?

There is a bit of misunderstanding here.

Your XAllocColorCells() tries to allocate so-far unused slots in your
Default Colormap. This routine will fail if  all the slots in
the default colormap is already in use. When the call fails,
you'll get all 0's in the plane masks and the cells.
Such is the case with, e.g.,
the Apollo DN3000 which has only 4 bit planes, and all 16 available slots
are  probably tied up the window manager.
Your cgfour with 256 color cells should have room to spare unless
your window manager  + other X-things running have
tied up all 256 slots.

If successful the newly allocated cells are now at your disposal.
You may use XStoreColor() or XStoreColors() to put your own
rgb specifications into the slots. You have to keep track of
which color goes into which slot (pixel value)
for later use, e.g., in calls to XSetForeground.

If the Default colormap is full and XAllocColorCells() fails, you
can always Create your own color map, allocate cells in it and
store your own colors in the cells. Once installed with XInstallColormap(),
this new map will apply to the entire display and therefore will mess up
the colors of everything except the window it is intended for.

There is actually supposed to be another solution to your problem,
without having to store your own colors, but the color you obtain
will be only an approximation, the closest match in the standard
map to your rgb specification.
There is this function XGetStandardColormap() which supposedly
fills a XStandardColormap structure, which has all the information
needed for computing the pixel value of any rgb for the standard
colormap. However I have not yet been able to get this function
to return SUCCESS. The XGetStandardColormap() call in the
program below returns a FAILURE status on an APollo DN3000 and a Sun/260.
I would appreciate it if anyone out there could point out what
we are doing wrong.

/* ----------------------------- cut here -------------------------- */

#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>

int main() {
	Display *dpy;
	Window win;
	int	scrn;
	int	planes;
	XStandardColormap	sc_map;
  
	if ((dpy = XOpenDisplay (NULL)) == NULL) {
		fprintf (stderr, "Could not connect to default X display.\n");
		XCloseDisplay(dpy);
		exit (1);
	}

	scrn = XDefaultScreen(dpy);

	planes = XDisplayPlanes(dpy, scrn);

	printf("no of planes: %d\n", planes);

	win = XDefaultRootWindow(dpy);

	if (XGetStandardColormap(dpy, win, &sc_map, XA_RGB_COLOR_MAP) == 0)
		fprintf(stderr, "cannot obtain standard colormap\n");
	else
		fprintf(stderr, "standard colormap obtained\n");

	XCloseDisplay(dpy);
}
/* -------------------------- cut here ------------------------------- */


				Augustine Chan
				Seattle Silicon Corp.
				Bellevue, Wash

jim@EXPO.LCS.MIT.EDU (Jim Fulton) (06/16/88)

>> [the allocating colors misexample]
>
> There is a bit of misunderstanding here.

To say the least.  For reference, the indicated code was attempting to allocate
ncells*2^nplanes = 256*2^8 = 65536 color cells.  Ugh.


> [this was asking about why XGetStandardColormap wasn't working]
>
> I would appreciate it if anyone out there could point out what
> we are doing wrong.

Two things:

    1.  The publicly-available window managers don't create any standard
	colormaps, so there aren't any to fetch.  Unless you have created
	a special program to load the colormaps, XGetStandardColormap
	won't work.  See Section 9.2 of the Xlib manual and the ICCCM 
	for more detailed information.

    2.  You were passing the colormap property type (XA_RGB_COLOR_MAP)
	instead of one of the standard colormap property names listed in
	Section 9.2.2 of the Xlib manual:

		XA_RGB_DEFAULT_MAP
			a "nice" collection of commonly-used colors

		XA_RGB_BEST_MAP
			the widest distribution of colors

		XA_RGB_RED_MAP
		XA_RGB_GREEN_MAP
		XA_RGB_BLUE_MAP
			ramps of the indicated colors

		XA_RGB_GRAY_MAP
			ramps of gray



Jim Fulton
MIT X Consortium

kochhar@endor.harvard.edu (Sandeep Kochhar) (03/12/90)

Config: X11R4, twm, Sparcstation I

I have a program that creates a window and a colormap and associates
the colormap with the window using XSetWindowColormap().

This works fine, in that when the cursor comes into the window, twm
switches to my colormap, and when I move out of the window, it
switches back, and so on.

However, on random occasions (not always), I get the message

twm:  client illegally changed colormap (i = -1, j = -1

Also, sometimes on those occasions, twm doesn't install my  colormap
when I enter the program window.

Anybody  have any ideas?

(Note: the only other colormap related calls I use are:
XCreateColormap, XStoreColor, XLookupColor)

Thanks.

Sandeep Kochhar
(617) 495-3988              mail: kochhar@harvard.harvard.edu
Harvard University                kochhar@harvard.csnet
33 Oxford st,                     kochhar@harvard.uucp
Cambridge, MA 02138               kochhar@harvard.bitnet

Fax: (617) 495-9837