[comp.windows.x] XCopyPlane, X Bitmap Problem

darken@seas.gwu.edu (Rudolph Darken) (02/28/91)

I am in desperate need of assistance with XCopyPlane and the
format of X bitmap files. First, if I have an 8 bit/pixel
pixmap, what do I need to do to copy that to a visible
window? It's the 'plane' parameter that's confusing me.
Next, say I want to save my 8 bit/pixel pixmap into a
bitmap file. Can this be done? And if so, will my 8 bits
be preserved? It seems that the definition of a bitmap 
would not allow this. If this won't work, are there any
suggestions as to how to save a color image to disk for
future use in an X application? Thanks very much for
any help.

Rudy Darken
darken@seas.gwu.edu 

mouse@lightning.mcrcim.mcgill.EDU (02/28/91)

> I am in desperate need of assistance with XCopyPlane and the format
> of X bitmap files.  First, if I have an 8 bit/pixel pixmap, what do I
> need to do to copy that to a visible window?

If the window is 8 bits deep, you can use XCopyArea.  However, for this
to do what you probably want, you have to make sure the window's
colormap is correct for the picture.  How easy this is depends in part
on the visual in use.  Choosing visuals and dealing with colormaps is
another topic entirely; I won't go into it now.

If the window is not 8 bits deep, it's more difficult.  (In both the
following cases, if what you want is not covered, you will probably
have to manipulate the picture in the client to generate a new picture
of the appropriate depth and display the result with XPutImage and/or
XCopyArea.)

If the window is only one bit deep, you can use XCopyPlane to select
one bitplane of your image and display it.  You have limited control
over how it's displayed with the GC's function parameter.

If the window is neither 1 bit nor 8 bits deep, you can generate a new
picture by using XCopyPlane to pick a plane out of the 8-bit picture
and store it in a bitmap, then use XCopyPlane to merge it with a deeper
picture elsewhere, repeating for each plane you want to copy.  (I don't
see any way to do this without handling each plane separately,
unfortunately.)  You need to use either the plane-mask in the GC to
restrict writes in the target to the bitplane you want to set, or you
can diddle the foreground and background values and set the function to
do the appropriate thing.

> It's the 'plane' parameter that's confusing me.

This sounds as though you think you want to use XCopyArea, and you may
well be right.

What does the plane parameter do?  Well, let's take a simple example.
Suppose you have a 6x3x8 pixmap whose pixel values in binary are

	11000000 00111101 01010100 11111100 01101001 01101110
	00111000 10010001 10100101 00010110 11011110 11111001
	00111011 01001110 01111110 01011011 01000001 01111110

Now, you want to create a 6x3x4 pixmap containing just the top four
bits of the original pixmap.  I'll demonstrate things for just one of
the four bits (bit 6, 00100000); the other are similar, with just the
particular choice of bit changed.  I assume the source and destination
pixmaps already exist.

First, you create a 6x3x1 bitmap on the same screen as the pixmap.  You
will also need two GCs created on this screen, one of depth 1 (to use
when writing into the bitmap) and one of depth 4 (for use when writing
into the 6x3x4 pixmap).  For these, you can just pass the corresponding
pixmap/bitmap as the drawable argument to XCreateGC.

Then you XCopyPlane with

	src = the 6x3x8 pixmap
	dest = the 6x3x1 bitmap
	gc = the depth-1 GC, with the following settings:
		foreground = 1
		background = 0
		function = GXcopy
	src_x = 0
	src_y = 0
	width = 6
	height = 3
	dest_x = 0
	dest_y = 0
	plane = the bit, 00100000

This causes each pixel in the bitmap to contain the 00100000 bit from
the original pixmap's corresponding pixel:

	0 1 1 1 0 0
	1 1 0 1 1 1
	1 0 1 1 0 1

Then to copy it into the 0010 bit of the destination pixmap, you issue
another XCopyArea with

	src = the 6x3x1 bitmap
	dest = the 6x3x4 pixmap
	gc = the depth-4 GC, with the following settings:
		foreground = 0010
		background = 0
		function = GXor
	src_x = 0
	src_y = 0
	width = 6
	height = 3
	dest_x = 0
	dest_y = 0
	plane = 1 (the low (and only) bit of the bitmap)

This assumes the 0010 bit in the 6x3x4 pixmap is already cleared.  If
not, you may have to instead set the depth-4 GC up with

		foreground = 0010 (or anything else with that bit set)
		background = 0 (or anything with bit 0010 clear)
		function = GXcopy
		plane-mask = 0010

This will normally be substantially slower than using GXor; you might
find it faster to instead clear the 0010 bit by doing a XFillRectangle
of the whole 6x3x4 pixmap with the GC set to

		foreground = 0010
		function = GXandInverted

Playing with the function, plane-mask, etc, lets you get lots of
different effects, most of which are not useful....

> Next, say I want to save my 8 bit/pixel pixmap into a bitmap file.

No can do - bitmap files store bitmaps, not pixmaps.

There is a file format that can deal with pixmaps, the XPM format.  I
don't really know much more about it, except that you can get lots of
stuff about it from the usual X archive sources.

> [...], are there any suggestions as to how to save a color image to
> disk for future use in an X application?

If you want an interchange format comparable to xbm format, xpm is
probably best.  If you just want to save it for later use (by the same
program on the same machine), do whatever seems convenient - for
example, just write out the raw data area you're storing it in.  There
are lots of possible things to do, and various tradeoffs you have to
make....

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

mouse@lightning.mcrcim.mcgill.EDU (02/28/91)

I said:

> 	0 1 1 1 0 0
> 	1 1 0 1 1 1
> 	1 0 1 1 0 1

but that was the wrong bit, 00010000 instead of 00100000.  I should
have said:

	0 1 0 1 1 1
	1 0 1 0 0 1
	1 0 1 0 0 1

Sorry about that.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu