Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!mit-eddie!bloom-beacon!LARRY.MCRCIM.MCGILL.EDU!mouse From: mouse@LARRY.MCRCIM.MCGILL.EDU Newsgroups: comp.windows.x Subject: XImages Message-ID: <9012091630.AA14377@Larry.McRCIM.McGill.EDU> Date: 9 Dec 90 16:30:44 GMT Sender: daemon@athena.mit.edu (Mr Background) Organization: The Internet Lines: 157 > 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