Open GL Super Bible

Previous Table of Contents Next


Drawing Pixmaps

OpenGL provides a single function for drawing pixmaps called glDrawPixels. Like glBitmap, glDrawPixels uses the current raster position to define the lower-left corner of the image. You cannot specify a raster origin or movement as you can for glBitmap.

BITMAPINFO *BitmapInfo;
GLubyte    *BitmapBits;

glRasterPos2i(xoffset, yoffset);
glDrawPixels(BitmapInfo->bmiHeader.biWidth,
             BitmapInfo->bmiHeader.biHeight,
             GL_RGB, GL_UNSIGNED_BYTE, BitmapBits);

The glDrawPixels function accepts five arguments:

glDrawPixels(GLsizei width, GLsizei height,
             GLenum format, GLenum type,
             Glvoid *pixels)

The format parameter specifies the colorspace of the pixmap; valid formats are in Table 11-1. The GL_COLOR_INDEX format specifies that each color value in the pixmap is an index into the current Windows logical color palette. Color index images are often used for icons. The GL_LUMINANCE format maps each color value to a grayscale value on the screen, with the minimum value being completely black and the maximum value being completely white. The GL_RGB format specifies the exact red, green, and blue values for each pixel in the image.

Table 11-1 OpenGL Pixel Formats

Format Description

GL_COLOR_INDEX Color index pixels
GL_LUMINANCE Grayscale pixels
GL_RGB RGB pixels

The type parameter of glDrawPixels specifies the type and range of each color value or component, as listed in Table 11-2.

Table 11-2 OpenGL Pixel Types

Type Description

GL_BYTE Signed 8-bit values (from –128 to 127)
GL_UNSIGNED_BYTE Unsigned 8-bit values (from 0 to 255)
GL_BITMAP Bitmap image (from 0 to 1)

Remapping Colors

When using GL_COLOR_INDEX colors, you can remap the colors in your pixmap or bitmap using the glPixelMap or glPixelTransfer functions. The glPixelTransfer function lets you specify scaling and offsets for color index and RGB values. For example, here is the code to brighten an RGB image by 10%:

glPixelTransferf(GL_RED_SCALE, 1.1)
glPixelTransferf(GL_GREEN_SCALE, 1.1);
glPixelTransferf(GL_BLUE_SCALE, 1.1);

Similarly, to offset the color indices of a bitmap to the palette entries you have defined for it, use

glPixelTransferi(GL_INDEX_OFFSET, bitmap_entry);

In the “smiley” bitmap example (Listing 11-7), we might use this to remap the two colors in the bitmap to difference indices:

Listing 11-7 Repaint Window function to draw smiley faces

void
RepaintWindow(RECT *rect)   /* I - Client area rectangle */
{
  int            i;         /* Looping var */
  static GLubyte smiley[] = /* 16x16 smiley face */
  {
    0x03, 0xc0, 0, 0, /*       ****       */
    0x0f, 0xf0, 0, 0, /*     ********     */
    0x1e, 0x78, 0, 0, /*    ****  ****    */
    0x39, 0x9c, 0, 0, /*   ***  **  ***   */
    0x77, 0xee, 0, 0, /*  *** ****** ***  */
    0x6f, 0xf6, 0, 0, /*  ** ******** **  */
    0xff, 0xff, 0, 0, /* **************** */
    0xff, 0xff, 0, 0, /* **************** */
    0xff, 0xff, 0, 0, /* **************** */
    0xff, 0xff, 0, 0, /* **************** */
    0x73, 0xce, 0, 0, /*  ***  ****  ***  */
    0x73, 0xce, 0, 0, /*  ***  ****  ***  */
    0x3f, 0xfc, 0, 0, /*   ************   */
    0x1f, 0xf8, 0, 0, /*    **********    */
    0x0f, 0xf0, 0, 0, /*     ********     */
    0x03, 0xc0, 0, 0  /*       ****       */
  };

  glViewport(0, 0, rect->right, rect->bottom);

  glClearIndex(0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0, rect->right - 1.0, 0.0, rect->bottom - 1.0, -1.0, 1.0);

 /*  * This bitmap is aligned to 4-byte boundaries…
  */

  glPixelTransferi(GL_UNPACK_ALIGNMENT, 4);
  glPixelTransferi(GL_INDEX_OFFSET, 1);

  for (i = 0; i < 100; i ++)
  { 
    glRasterPos2i(rand() % rect->right, rand() % rect->bottom);
    glDrawPixels(16, 16, GL_COLOR_INDEX, GL_BITMAP, smiley);
  };

  glFinish();
}

Color Mapping Tables

Sometimes it is necessary to apply color corrections that are more complicated than simple linear scale and offset. One application is gamma correction, in which the intensity of each color value is adjusted to a power curve that compensates for irregularities on your monitor or printer (see Figure 11-2). The glPixelMap function allows you to do this by specifying a lookup table, as follows:

GLfloatlut[256];
GLfloatgamma_value;
int           i;

gamma_value = 1.7; /* For NTSC video monitors */
for (i = 0; i < 256; i ++)
 lut[i] = pow(i / 255.0, 1.0 / gamma_value);

glPixelTransferi(GL_MAP_COLOR, GL_TRUE);
glPixelMap(GL_PIXEL_MAP_R_TO_R, 256, lut);
glPixelMap(GL_PIXEL_MAP_G_TO_G, 256, lut);
glPixelMap(GL_PIXEL_MAP_B_TO_B, 256, lut);


Figure 11-2  Image without gamma correction (left) and with a gamma correction of 1.7 (right)

Scaling a Pixmap

Besides adjusting the colors of a pixmap, you can adjust the size of the pixmap using the glPixelZoom function. This function accepts two floating point parameters specifying the X and Y scaling factors for the image:

glPixelZoom(1.0, 1.0);   /* Don’t scale the image */
glPixelZoom(-1.0, 1.0);  /* Flip the image horizontally */
glPixelZoom(1.0, -2.0);  /* Flip the image and double the height */
glPixelZoom(0.33, 0.33); /* Draw the image 1/3 size */

As you can see, glPixelZoom allows you to scale and flip an image just about any way you like. For other nonlinear effects, such as rippling water or perspective correction, you’ll need to use texture mapping (Chapter 12).


Previous Table of Contents Next