rhl@wombat@stsci.ARPA (Robert Lupton) (02/27/87)
I am pretty naive, but if I ask for more than 6 planes (on a sun with 8 planes) I get funny colours all over the screen - how do I get 240 colours, and leave the remaining few bit pattersn to the server? (I'd settle for 128) Robert Lupton
mouse@LARRY.MCRCIM.MCGILL.EDU (12/10/90)
> The Xlib - C Language X Interface states that the function > XCreateImage "allocates the memory needed for an XImage > structure"..."but doesn't allocate space for the image itself." How > can we determine the amount of space to be allocated for image data > in the various formats (XY* or Z*)? You need to know the expected layout of the image in memory. As far as I've been able to tell, this isn't properly documented either. (See below about this.) > i.e. if I have to display an image in a say 600x600 pixels window how > many bytes I need to allocate? If you want to depend on just the written spec in Xlib - C Language X Interface, I don't think you can. You can cheat, though. You generally can tell by using XCreateImage with (char *)0 as the data argument. This is not portable, though, because it is no part of XCreateImage's contract to work with a null data pointer. (It is reasonable for it to do so, because the contents of an XImage structure are documented, but I don't think it's promised.) Once you have the XImage, you multiply the Y size by the bytes_per_line value to get the number of bytes of image data required, and pass that to malloc. Given that much, I think it probably can be shown that it is guaranteed that you will get away with just bashing the data field of the returned XImage to point to the newly-allocated data. Then we're right back to the question of memory layout of the data: you need to store something in that space you just allocated. The portable, guaranteed way to do this is to use XPutPixel for every pixel in the image. Except for small images, you can expect this to be slow, probably excessively so. The data format in memory is not very well documented. Warning: long (6Kb) discourse on image layout in memory follows, aka "all you wanted to know about XImages but didn't know who to ask". Much of this is inference from various pieces of documentation; some of it is more or less verbatim. If I have made any errors, or if there's something unclear, I would appreciate an email message on the subject. There are too many numbers and their interactions are not well described. There is the list of pixmap formats, each of which specifies a depth (any 8-bit number, though numbers greater than 32 cause problems in other areas), a bits-per-pixel (1, 4, 8, 16, 24, or 32 -- odd, why isn't 2 listed?), and a scanline-pad (8, 16, or 32). In addition, there is the image-byte-order (MSBFirst or LSBFirst), the bitmap-scanline-unit (8, 16, or 32), the bitmap-scanline-pad (also 8, 16, or 32), and the bitmap-bit-order (LeastSignificant or MostSignificant). Here is how I interpret these numbers as related to the stream of bytes needed for XPutImage. (All of this can be found, more or less verbatim, in the protocol document. I'll relate this to XImages after I've explained the three formats.) When the format is Bitmap, each scanline is padded to a multiple of bitmap-scanline-pad bits. The non-padding bits are grouped into chunks of bitmap-scanline-unit bits each (bitmap-scanline-unit must always be less than or equal to bitmap-scanline-pad). If these chunks are larger than 8 bits, they are considered as integers with byte sex as given by image-byte-order. Each integer's bits (ie, pixels - this is Bitmap format) get ordered left-to-right, with the leftmost bit being as specified by bitmap-bit-order. When the format is XYPixmap, it is simply split into a sequence of bitmaps, each specified as above. No padding is inserted between bitmaps (padding at the end of the last scanline of a bitmap, if any, is considered part of the bitmap). When the format is ZPixmap, there must be exactly one pixmap format listed for that depth (no entries of that depth means the server does not support it; more than one is, to my reading, contrary to the protocol). If bits-per-pixel is 1, the format is identical to bitmap format (the scanline-pad in the pixmap format must match bitmap-scanline-pad). Otherwise, the pixels are strung together left-to-right to form the scanline; each pixel takes bits-per-pixel bits (if depth is less than bits-per-pixel, the pixel value is in the low-order bits with the leftover bits undefined). Each scanline is padded to a multiple of scanline-pad. If the bits-per-pixel is greater than 8, then it will be a multiple of 8, so each pixel is an integral number of bytes; each pixel is then considered as an integer (of bits-per-pixel bits) and serialized into the byte-stream with the byte sex specified by the image-byte-order. If bits-per-pixel is less than 8, then it must be a factor of 8, so each byte holds an integral number of pixels; the pixels are then packed into bytes as specified by the image-byte-order. (If the bits-per-pixel equals 8, each pixel is one byte and there is no problem.) It is not clearly specified how a pixel's bits are arranged when multiple pixels are packed into a byte, but I would assume (and it is an assumption) that each pixel's bits are ordered MSB to LSB in the same direction as the byte's bits. Now, how does all this relate to XImages? An XImage contains six values which are presumably related to some of the values I talked about above. The relevant members of the XImage structure, from the Xlib document, are: int format; /* XYBitmap, XYPixmap, ZPixmap */ int byte_order; /* data byte order, LSBFirst, MSBFirst */ int bitmap_unit; /* quant. of scanline 8, 16, 32 */ int bitmap_bit_order; /* LSBFirst, MSBFirst */ int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */ int depth; /* depth of image */ int bits_per_pixel; /* bits per pixel (ZPixmap) */ There are also int xoffset; /* number of pixels offset in X direction */ int bytes_per_line; /* accelerator to next scanline */ but they are not essential to the discussion here. They are relevant only when you want to manipulate a sub-image of an image you already have in memory (or, for bytes_per_line, as an accelerator when stepping through scanlines). Here is my guess on what these values mean. Much of this next paragraph is conjecture; all of it should be taken with an implied "In my interpretation". The format, of course, is the format I mentioned above (though what the protocol calls Bitmap format is called XYBitmap by Xlib). I shall use the term "bitmap data" for XYBitmap, XYPixmap, or ZPixmap for depth=1 when bit-per-pixel is also 1; the other case, ZPixmap when bits-per-pixel is not 1, I shall refer to as "non-bitmap data". The depth is of course the depth of the image. The bits_per_pixel is either 1, for bitmap format, or the bits-per-pixel value from the pixmap format, for non-bitmap format. The byte_order is the protocol's image-byte-order value. Bitmap data layout requires three more numbers; these are the bitmap-scanline-unit, bitmap-bit-order, and bitmap-scanline-pad above, which presumably go into the bitmap_unit, bitmap_bit_order, and bitmap_pad structure elements. Non-bitmap data layout needs just one more value, that being the scanline-pad. I assume this will be stored in the bitmap_pad field simply because that field makes more sense than any of the others, though the name is somewhat misleading. This should be enough for you to build your own XImage structure, but it's not. The reason it's not is that there are those silly function handles in the structure. So you have only two real possibilities. One is that you can massage your data into whatever format the server you happen to be connected to wants. The other is to write your own functions to stuff into the function handles, allocate the XImage structure yourself, and use whatever data layout happens to be convenient. IMO this is a botch. It should be possible to use your own preferred data layout and have Xlib do whatever is necessary to accomodate it. It more or less has to do this anyway, because the handles do not include functions for PutImage and GetImage format conversion. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
jimf@SABER.COM (12/11/90)
|So you have only two real possibilities. One is that you can massage |your data into whatever format the server you happen to be connected to |wants. The other is to write your own functions to stuff into the |function handles, allocate the XImage structure yourself, and use |whatever data layout happens to be convenient. | |IMO this is a botch. It should be possible to use your own preferred |data layout and have Xlib do whatever is necessary to accomodate it. |It more or less has to do this anyway, because the handles do not |include functions for PutImage and GetImage format conversion. Yea, the XImage stuff is not well designed or documented. It's highly portable, though, to allocate an XImage and smash the attributes you want into the structure. Xlib (at least all of them I've used) will convert to server-natural format for you. This is highly convenient because all you have to do is describe what your image looks like and send it off. Sample code which does this can be had from expo.lcs.mit.edu in /contrib/xloadimage.2.02.tar.Z. Look at send.c. While I admit that it's not the cleanest way to do things and it doesn't seem to be guaranteed that Xlib will convert for you, it does work very portably (ie I know of no system which doesn't convert, and xloadimage runs on a *lot* of systems). Nice description, BTW. I would have killed for that a couple of years ago :-). Happy hacking, jim frost saber software jimf@saber.com
rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (12/11/90)
it doesn't seem to be guaranteed that Xlib will convert for you, It is supposed to be guaranteed, for all formats covered by the X protocol.
jimf@SABER.COM (12/11/90)
| it doesn't seem to be guaranteed that Xlib will convert for you, | |It is supposed to be guaranteed, for all formats covered by the X protocol. Ok -- my documentation certainly doesn't mention that, but I can live with it if you say so. jim frost saber software jimf@saber.com
jg@crl.dec.com (Jim Gettys) (12/11/90)
Yes, the XImage stuff is botched... I got interrupted in the middle of trying to design it. Sigh... It is the worst part of Xlib, hands down. In any case, Xlib does convert the data for you. - Jim
marbru@attc.UUCP (Martin Brunecky) (12/12/90)
In article <9012101728.AA23279@test4> jimf@SABER.COM writes: > >Yea, the XImage stuff is not well designed or documented. It's highly >portable, though, to allocate an XImage and smash the attributes you >want into the structure. Xlib (at least all of them I've used) will >convert to server-natural format for you. This is highly convenient >because all you have to do is describe what your image looks like and >send it off. > Well, the XImage stuff documentation deserves a LOT. So far, I'v seen 3 guys struggling with it, and each comming back with completely different understanding of the subject. And even after working with all three guys and having the code which seems to correctly receive, process and put images to a variaty of servers, I still do NOT get the mening of "image byte order". For image bit order, MSBfirst/LSBfirst are crystal clear. But when it comes to byte order ... My *observation* is that IF I access image data as BYTES on either SPARC or DECstation, I must assume MSBfirst no matter what the XImage structure says. IF I access image data as scan-units (32 bits in this case), I must honor the "image byte order". What does NOT make sense to me, is that the BYTE order in 32 bit unit is a CLIENT machine feature, not the SERVER machine. To add to the confusion, the protocol request (73),GetImage specifies the image data as LISTofBYTES. Any explanations ? -- =*= Opinions presented here are solely of my own and not those of Auto-trol =*= Martin Brunecky {...}sunpeaks!auto-trol!marbru (303) 252-2499 (sometimes also: marbru@auto-trol.COM ) Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404
luj@gus16.ecn.purdue.edu (Jun Lu) (12/12/90)
In article <9012091630.AA14377@Larry.McRCIM.McGill.EDU> mouse@LARRY.MCRCIM.MCGILL.EDU writes: > > If bits-per-pixel is less than >8, then it must be a factor of 8, so each byte holds an integral number >of pixels; the pixels are then packed into bytes as specified by the >image-byte-order. (If the bits-per-pixel equals 8, each pixel is one >byte and there is no problem.) It is not clearly specified how a >pixel's bits are arranged when multiple pixels are packed into a byte, >but I would assume (and it is an assumption) that each pixel's bits are >ordered MSB to LSB in the same direction as the byte's bits. The protocol doc page 10 states: when the bits_per_pixel is 4, the order of nibbles in the byte is the same as the image byte_order. > >An XImage contains six values which are presumably related to some of >the values I talked about above. The relevant members of the XImage >structure, from the Xlib document, are: > > int format; /* XYBitmap, XYPixmap, ZPixmap */ > int byte_order; /* data byte order, LSBFirst, MSBFirst */ > int bitmap_unit; /* quant. of scanline 8, 16, 32 */ > int bitmap_bit_order; /* LSBFirst, MSBFirst */ > int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */ > int depth; /* depth of image */ > int bits_per_pixel; /* bits per pixel (ZPixmap) */ > >There are also > > int xoffset; /* number of pixels offset in X direction */ > int bytes_per_line; /* accelerator to next scanline */ > >but they are not essential to the discussion here. They are relevant >only when you want to manipulate a sub-image of an image you already >have in memory (or, for bytes_per_line, as an accelerator when stepping >through scanlines). Basically, two things need to be distinguished: image format as required by the server characterstics versus the image acutally stored in the client cpu memory. The fields of XImage struct such as byte_order, bitmap_unit, bitmap_bit_order, bitmap_pad, (depth), bits_per_pixel, (bytes_per_line) as returned by XCreateImage are the characteristics of the server, and they may not be the same as how the image is actually stored in the client cpu. Therefore, one should fill those fields according to how image is actually stored. In case that the client-side image is in a format different from that required/supported by the server, XPutImage will do necessary conversions for client before it acutally send the image to the server. -- -- Jun Lu Internet:luj@ecn.purdue.edu -- -- Aeronautics & Astronautics Bitnet: luj%ecn.purdue.edu@purccvm -- -- Purdue University UUCP: pur-ee!luj -- -- W. Lafayette, IN 47907 Phone:317-494-9410 Fax:317-494-0307 --
jim@ncd.COM (Jim Fulton) (12/12/90)
For image bit order, MSBfirst/LSBfirst are crystal clear. But when it comes to byte order ... If it helps, here's a description that I wrote up recently: Definitions: BitmapPad specifies the number of bits to which each glyph scanline will be padded. This value will always be greater than or equal to BitmapUnit. BitmapUnit specifies the number of bits that should be treated as a unit for swapping. ImageByteOrder specifies whether the Most- or Least-Significant Byte of each bitmap-unit will be returned first. BitmapBitOrder specifies whether the left-most bit in each glyph bitmap-unit is stored in the Most- or Least-Significant Bit of transmitted bitmap-unit. Algorithm: Each scanline is padded to a multiple of the number of bits specified by BitmapPad. The scanline is then divided into a sequence of BitmapUnit bits. The bits of each unit are then swapped such that the left-most pixel is stored in the most- or least-significant bit, according to BitmapBitOrder. The bytes of each unit are then swapped such that the most- or least-significant byte is transmitted first, according to ImageByteOrder. Jim Fulton Network Computing Devices jim@ncd.com
marbru@attc.UUCP (Martin Brunecky) (12/13/90)
In article <1990Dec12.052259.7256@noose.ecn.purdue.edu> luj@gus16.ecn.purdue.edu (Jun Lu) writes: >In article <9012091630.AA14377@Larry.McRCIM.McGill.EDU> mouse@LARRY.MCRCIM.MCGILL.EDU writes: > >The protocol doc page 10 states: when the bits_per_pixel is 4, the order of >nibbles in the byte is the same as the image byte_order. > Can you, please, state WHICH "doc". The doc's I can dig out of my MIT release trees don't seem to have that information on this page. -- =*= Opinions presented here are solely of my own and not those of Auto-trol =*= Martin Brunecky {...}sunpeaks!auto-trol!marbru (303) 252-2499 (sometimes also: marbru@auto-trol.COM ) Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404
luj@delta.ecn.purdue.edu (Jun Lu) (12/13/90)
In article <927@attc.UUCP> marbru@auto-trol.com (Martin Brunecky) writes: > > My *observation* is that IF I access image data as BYTES on either > SPARC or DECstation, I must assume MSBfirst no matter what the XImage > structure says. Not true(at least for Sparcs). In the case that a image is stored as bytes, byte_ordering is not important. You can always specifiey the byte_order with the macro ImageBteOrder(dpy) -- becasue for byte images, byte_order does not really matter.(Of course, you can arbitrarily specify the byte_order as LSBFirst if you insist). > IF I access image data as scan-units (32 bits in this case), I must > honor the "image byte order". Agree. > What does NOT make sense to me, is that the BYTE order in 32 bit unit > is a CLIENT machine feature, not the SERVER machine. Depends on how you get your images. In the case that the client read the image from a disk, the image byte_order should be specified according to how the image is actually stored in the client memory and this byte_ordeing has nothing do with whether the client is big_endian or little_endian. In the case the client gets its image by the request XGetImage, the XImage struct should never be modified and the client should access the image according the the byte_order/bit_order returned. -- -- Jun Lu Internet:luj@ecn.purdue.edu -- -- Aeronautics & Astronautics Bitnet: luj%ecn.purdue.edu@purccvm -- -- Purdue University UUCP: pur-ee!luj -- -- W. Lafayette, IN 47907 Phone:317-494-9410 Fax:317-494-0307 --
luj@delta.ecn.purdue.edu (Jun Lu) (12/14/90)
In article <930@attc.UUCP> marbru@auto-trol.com (Martin Brunecky) writes: >In article <1990Dec12.052259.7256@noose.ecn.purdue.edu> luj@gus16.ecn.purdue.edu (Jun Lu) writes: >>The protocol doc page 10 states: when the bits_per_pixel is 4, the order of >>nibbles in the byte is the same as the image byte_order. >> > Can you, please, state WHICH "doc". The doc's I can dig out of my MIT > release trees don't seem to have that information on this page. > > >-- mit/hardcopy/Protocol (R4) -- -- Jun Lu Internet:luj@ecn.purdue.edu -- -- Aeronautics & Astronautics Bitnet: luj%ecn.purdue.edu@purccvm -- -- Purdue University UUCP: pur-ee!luj -- -- W. Lafayette, IN 47907 Phone:317-494-9410 Fax:317-494-0307 --
mouse@LIGHTNING.MCRCIM.MCGILL.EDU (12/16/90)
>> It is not clearly specified how a pixel's bits are arranged when >> multiple pixels are packed into a byte, but I would assume (and it >> is an assumption) that each pixel's bits are ordered MSB to LSB in >> the same direction as the byte's bits. > The protocol doc page 10 states: when the bits_per_pixel is 4, the > order of nibbles in the byte is the same as the image byte_order. Yes, I know. Clearly which nybble goes in which half of the byte is specified. What isn't specified is the order of the bits within a nybble. (Of course, the order of the bits within a byte isn't specified in the >=8 bits/pixel case either, but the reasonable supposition is much stronger there.) >> An XImage contains six values which are presumably related to some >> of the values I talked about above. The relevant members of the >> XImage structure, from the Xlib document, are: [...] > Basically, two things need to be distinguished: image format as > required by the server characterstics versus the image acutally > stored in the client cpu memory. Yes, this is the problem. > The fields of XImage struct such as byte_order, bitmap_unit, [...] as > returned by XCreateImage are the characteristics of the server, and > they may not be the same as how the image is actually stored in the > client cpu. Therefore, one should fill those fields according to > how image is actually stored. This is the problem: where is it promised that one can do this? As far as I can tell, it isn't. It is - I think - promised that XPutImage will deal with it, but if you bash these fields, nothing guarantees that any of the function handles installed by XCreateImage will work any longer. And since nothing promises anything about the mapping from Xlib calls to the function handles, the only thing guaranteed to work if you bash the values is XPutImage. Even XDestroyImage may break. (To be sure, it would be a very twisted implementation, but I don't think it contravenes the spec.) Basically, the XImage facilities are only partially finished. They need to be finished, or else completely redone. (Presumably the major thing lacking is human time....) der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
marbru@attc.UUCP (Martin Brunecky) (12/18/90)
In article <9012121928.AA08593@hansen.com> jim@ncd.COM (Jim Fulton) writes: > > ImageByteOrder specifies whether the Most- or Least-Significant Byte > of each bitmap-unit will be returned first. Than how do you explain that the Sun's Open Windows (2.0) server and DECwidnows(Ultrix or VMS) servers report oposite ImageByteOrder, but the first *byte* in returned image (accessed as (char*))is my pixel[0,0] for both servers ? (talking 8 bitplane systems on both sides, scanline unit 32 on both sides). I feel like in addition to the information about XImage byte order I need to know the servers's and client's byte order within the "scanline unit", i.e. I need a CUBE 2*2*2 to make my decision 8-). -- =*= Opinions presented here are solely of my own and not those of Auto-trol =*= Martin Brunecky {...}sunpeaks!auto-trol!marbru (303) 252-2499 (sometimes also: marbru@auto-trol.COM ) Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404
marbru@attc.UUCP (Martin Brunecky) (12/18/90)
>In article <9012121928.AA08593@hansen.com> jim@ncd.COM (Jim Fulton) writes: > > ImageByteOrder specifies whether the Most- or Least-Significant Byte > of each bitmap-unit will be returned first. I replied: Than how do you explain that the Sun's Open Windows (2.0) server and DECwidnows(Ultrix or VMS) servers report oposite ImageByteOrder, but the first *byte* in returned image (accessed as (char*))is my pixel[0,0] for both servers ? (talking 8 bitplane systems on both sides, scanline unit 32 on both sides). Now, when I looked at the MIT code: XImUtil.c, I have found this code: static unsigned long _XGetPixel8 (ximage, x, y) register XImage *ximage; int x; int y; { unsigned char pixel; if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) { pixel = ((unsigned char *)ximage->data) [y * ximage->bytes_per_line + x]; if (ximage->depth != 8) ^^^^^^^^^^^^^^^^^^^!!!! pixel &= low_bits_table[ximage->depth]; return pixel; } else { _XInitImageFuncPtrs(ximage); return XGetPixel(ximage, x, y); } } Note this code does NOT pay ANY attention to the ImageByteOrder, yet it will be used whenever the format (the first line) is matched. Is this a deviation from the protocol, or am I interpretting your statement incorrectly ? -- =*= Opinions presented here are solely of my own and not those of Auto-trol =*= Martin Brunecky {...}sunpeaks!auto-trol!marbru (303) 252-2499 (sometimes also: marbru@auto-trol.COM ) Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404
rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (12/18/90)
Than how do you explain that the Sun's Open Windows (2.0) server and DECwidnows(Ultrix or VMS) servers report oposite ImageByteOrder, but the first *byte* in returned image (accessed as (char*))is my pixel[0,0] for both servers ? Stop, do not pass Go, Contemplate for a long time. Take a look at the table that's embedded in comments in mit/lib/X/XPutImage. Study it. Convince yourself of its correctness (or incorrectness, I recall someone has submitted a bug report on part of it). Perhaps then you will attain enlightenment. :-) Image formats are a tricky business. So tricky, that in the X10 Sun server images got bytes reversed *twice*, even though they didn't really need to get reversed at all)! Since it took us at least 11 times around to understand that, don't be worried if it takes you a while. :-)
etaylor@wilkins.iaims.bcm.tmc.edu (Eric Taylor) (12/18/90)
ByteOrder has absolutely no effect on 8-bit images. If your data is 8-bit quanta, how could byte-order possibly make a difference ?? ByteOrder refers only to images whose depth > 8 bits. As to GetPixel8, it is there as a speedup for 8-bit images and is used only when parameters match exactly. -- Eric Taylor Baylor College of Medicine etaylor@wilkins.bcm.tmc.edu (713) 798-3776
marbru@attc.UUCP (Martin Brunecky) (12/19/90)
In article <9012172158.AA07950@expire.lcs.mit.edu> rws@EXPO.LCS.MIT.EDU (Bob Scheifler) writes: > > Than how do you explain that the Sun's Open Windows (2.0) server and > DECwidnows(Ultrix or VMS) servers report oposite ImageByteOrder, but the > first *byte* in returned image (accessed as (char*))is my pixel[0,0] for > both servers ? > >Stop, do not pass Go, Contemplate for a long time. Take a look at the Thanx to all of those who are helping me to get it RIGHT. My main problem with XImage is that it does not have a SCANLINE interface. XGetPixel/XPutPixel has way too overhead for scanline access, so we must try to bypass it. If the XImage structure also provided: XPutScanline ( XImage *image, int x, int y, Pixel *pixels, int length ) XGetScanline ( .... I (and probably everyone else) would forget about trying to understand the XImage pecularities, and just use those. CAN THIS BECOME an X11 R5 ENHANCEMENT REQUEST ? -- =*= Opinions presented here are solely of my own and not those of Auto-trol =*= Martin Brunecky {...}sunpeaks!auto-trol!marbru (303) 252-2499 (sometimes also: marbru@auto-trol.COM ) Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404