Contents / Previous / Next


Image Storage Modes

An image stored in memory has between one and four chunks of data, called elements, for each pixel in a rectangular portion of the screen. The data might consist of just the color index or the luminance (luminance is the possibly weighted sum of the red, green, and blue values), or it might consist of the red, green, blue, and alpha components for each pixel. The possible arrangements of pixel data, or formats, determine the number of elements stored for each pixel and their order.

Elements can be stored in memory as various data types, ranging from 8-bit bytes to 32-bit integers or floating-point numbers. OpenGL explicitly defines the conversion of each component in each format to each of the possible data types.

All the possible pixel-storage modes are controlled with the glPixelStore*() command. Typically, several successive calls are made with this command to set several parameter values:

   void glPixelStore{if}(GLenum pname, TYPEparam)
Parameters for Use with glPixelStore()
Parameter Name Type Initial Value Valid Range 
GL_UNPACK_SWAP_BYTES, GL_PACK_SWAP_BYTES GLboolean FALSE TRUE/FALSE
GL_UNPACK_LSB_FIRST, GL_PACK_LSB_FIRST GLboolean FALSE TRUE/FALSE
GL_UNPACK_ROW_LENGTH, GL_PACK_ROW_LENGTH GLint 0 any nonnegative integer
GL_UNPACK_SKIP_ROWS, GL_PACK_SKIP_ROWS GLint 0 any nonnegative integer
GL_UNPACK_SKIP_PIXELS, GL_PACK_SKIP_PIXELS GLint 0 any nonnegative integer
GL_UNPACK_ALIGNMENT, GL_PACK_ALIGNMENT GLint 4 1, 2, 4, 8

If the *SWAP_BYTES parameter is FALSE (the default), the ordering of the bytes in memory is whatever is native for the OpenGL client; otherwise, the bytes are reversed.

As long as your OpenGL application doesn't share images with other machines, you can ignore the issue of byte ordering. If your application must render an OpenGL image that was created on a different machine, and the "endianness" of the two machines differs, byte ordering can be swapped using *SWAP_BYTES.

The *LSB_FIRST parameter applies when drawing or reading 1-bit images or bitmaps.

Sometimes you want to draw or read only a subrectangle of the entire rectangle of image data that's stored in memory. If the rectangle in memory is larger than the subrectangle that's being drawn or read, you need to specify the actual length of the larger rectangle with *ROW_LENGTH. If *ROW_LENGTH is zero (which it is by default), the row length is understood to be the same as the width that's specified with glReadPixels*(), glDrawPixels*(), or glCopyPixels(). You also need to specify the number of rows and pixels to skip before starting to copy the data for the subrectangle. These numbers are set using the parameters *SKIP_ROWS and *SKIP_PIXELS.

Often, a particular machine's hardware is optimized for moving pixel data to and from memory if the data is saved in memory with a particular byte alignment. For example, in a machine with 32-bit words, hardware can often retrieve data much faster if it's initially aligned on a 32-bit boundary, which typically has an address that is a multiple of 4. Likewise, 64-bit architectures might work better when the data is aligned to eight-byte boundaries. On some machines, however, byte alignment makes no difference.

As an example, suppose your machine works better with pixel data aligned to a four-byte boundary. Images are most efficiently saved by forcing the data for each row of the image to begin on a four-byte boundary. If the image is 5 pixels wide, and each pixel consists of one byte each of red, green, and blue information, a row requires 5 *3 = 15 bytes of data. Maximum display efficiency can be achieved if the first row, and each successive row, begins on a four-byte boundary, so there is one byte of waste in the memory storage for each row. If your data is stored like this, set the *ALIGNMENT parameter appropriately (to 4, in this case).

If *ALIGNMENT is set to 1, the next available byte is used. If it's 2, at the end of each row, a byte is skipped if necessary, so that the first byte of the next row has an address that's a multiple of 2. In the case of bitmaps (or one-bit images) where a single bit is saved for each pixel, the same byte alignment works, although you have to count individual bits. For example, if you're saving a single bit per pixel, the row length is 75, and the alignment is 4, each row requires 75/8, or 9 3/8 bytes. Since 12 is the smallest multiple of 4 that is bigger than 9 3/8, twelve bytes of memory are used for each row.


Pixel-Transfer Operations

You can perform various operations on pixels as they're transferred from and to the framebuffer. The continuous components, including the red, green, blue, alpha, and depth components, can have an affine transformation applied. In addition, after transformation, these components - as well as the color-index and stencil values - can be transformed by an arbitrary table lookup.

Some of the pixel-transfer function characteristics are set with glPixelTransfer*().

void glPixelTransfer{if}(GLenum pname, TYPEparam); 
The other characteristics are specified with glPixelMap*().


Pixel Mapping

As mentioned in the previous section, all the color components, color indices, and stencil indices can be modified by means of a table lookup before being placed in screen memory. The command for controlling this mapping is glPixelMap*().
  void glPixelMap[ui us f}v(GLenum map, GLint mapsize, const TYPE *values);