OpenGL provides three basic commands that manipulate image data:
glReadPixels() - Reads a rectangular array of pixels from the framebuffer and stores the data in processor memory.
glDrawPixels() - Writes a rectangular array of pixels into the framebuffer from data kept in processor memory.
glCopyPixels() - Copies a rectangular array of pixels from one part of the framebuffer to another. This command behaves something like a call to glReadPixels() followed by a call to glDrawPixels(), but the data is never written into processor memory.
The basic ideas behind these commands are simple, but complexity arises because there are many kinds of framebuffer data, many ways to store pixel information in computer memory, and various data conversions that can be performed during the reading, writing, and copying operations. All these possibilities translate to many different modes of operation. If all your program does is copy images on the screen, or read them into memory temporarily so that they can be copied out later, you can ignore most of these modes. However, if you want your program to modify the data while it's in memory - for example, if you have an image stored in one format but the window requires a different format - or if you want to save image data to a file for future restoration in another session or on another kind of machine with significantly different graphical capabilities, you have to understand the various modes.
The rest of this section describes the basic commands in detail. "Storing, Transforming, and Mapping Pixels" discusses the details of pixel-storage modes, pixel-transfer operations, and pixel-mapping operations. void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
Reads pixel data from the framebuffer rectangle whose lower left corner is at (x, y) and whose dimensions are width and height, and stores it in the array pointed to by pixels. format indicates the kind of pixel data elements that are read (an index value or an R, G, B, or A component value, as listed in Table 8-1 ), and type indicates the data type of each element (see Table 8-2 ).
| Name | Kind of Pixel Data |
|---|---|
GL_COLOR_INDEX | A single color index |
GL_RGB | A red color component, followed by a green color component, followed by a blue color component |
GL_RGBA | A red color component, followed by a green color component, followed by a blue color component, followed by an alpha color component |
GL_RED | A single red color component |
GL_GREEN | A single green color component |
GL_BLUE | A single blue color component |
GL_ALPHA | A single alpha color component |
GL_LUMINANCE | A single luminance component |
GL_LUMINANCE_ALPHA | A luminance component followed by an alpha color component |
GL_STENCIL_INDEX | A single stencil index |
GL_DEPTH_COMPONENT | A single depth component |
Draws a rectangle of pixel data with dimensions width and height. The pixel rectangle is drawn with its lower left corner at the current raster position. The format and type parameters have the same meaning as with glReadPixels(). The array pointed to by pixels contains the pixel data to be drawn. If the current raster position is invalid, nothing is drawn, and it remains invalid.
Remember that, depending on the format, anywhere from one to four elements are read or written. For example, if the format is GL_RGBA, and you're reading into 32-bit integers (that is, if type = GL_INT), then every pixel read requires 16 bytes of storage (4 components × 4 bytes/compenents).
| Name | Data Type |
|---|---|
GL_UNSIGNED_BYTE | unsigned 8-bit integer |
GL_BYTE | signed 8-bit integer |
GL_BITMAP | single bits in unsigned 8-bit integers |
GL_UNSIGNED_SHORT | unsigned 16-bit integer |
GL_SHORT | signed 16-bit integer |
GL_UNSIGNED_INT | unsigned 32-bit integer |
GL_INT | 32-bit integer |
GL_FLOAT | single-precision floating point |
Each element of the saved image is stored in memory as indicated by Table 8-2 . If the element represents a continuous value, such as a red, green, blue, or luminance component, each value is scaled to fit into the number of bits available. For example, the red component is a floating-point value between 0.0 and 1.0. If it needs to be packed into an unsigned byte, only 8 bits of precision are kept, even if more bits are allocated to the red component in the framebuffer. GL_UNSIGNED_SHORT and GL_UNSIGNED_INT give 16 and 32 bits of precision, respectively. The normal (signed) versions of GL_BYTE, GL_SHORT, and GL_INT have 7, 15, and 31 bits of precision, since the negative values are typically not used.
If the element is an index (a color index or a stencil index, for example), and the type is not GL_FLOAT, the value is simply masked against the available bits in the type. The signed versions - GL_BYTE, GL_SHORT, and GL_INT - have masks with one fewer bit. For example, if a color index is to be stored in a signed 8-bit integer, it's first masked against 0xff, a mask containing seven 1s. If the type is GL_FLOAT, the index is simply converted into a single-precision floating-point number (for example, the index 17 is converted to the float 17.0). void glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
Copies pixel data from the framebuffer rectangle whose lower left corner is at (x, y) and whose dimensions are width and height. The data is copied to a new position whose lower left corner is given by the current raster position. The type parameter is either GL_COLOR, GL_STENCIL, or GL_DEPTH. glCopyPixels() behaves much like a glReadPixels() followed by a glDrawPixels(), with the following translation for the type to format parameter:
If type is GL_DEPTH or GL_STENCIL, then GL_DEPTH_COMPONENT or GL_STENCIL_INDEX is used, respectively.
If GL_COLOR is specified, GL_RGBA or GL_COLOR_INDEX is used, depending on whether the system is in RGBA or color-index mode.
glCopyPixels() applies all the pixel transformations, transfer functions, and so on during what would be the glReadPixels() activity. The resulting data is written as it would be by glDrawPixels(), but the transformations aren't applied a second time. Note that there's no need for a format or data parameter for glCopyPixels(), since the data is never copied into processor memory. For all three functions, the exact conversions of the data going to or from the framebuffer depend on the modes in effect at the time. See the next section for details.
OpenGL Programming Guide