Direct Color Bitmaps

The direct color bitmap is the bitmap format designed exclusively for direct color virtual buffers. Its structure is similar to Fastgraph's 256-color bitmaps, but the pixels contain actual RGB color values, not palette indices. A direct color bitmap requires two bytes for each bitmap pixel for high color virtual buffers, and three bytes per pixel for true color virtual buffers. In high color buffers, each bitmap pixel is encoded in the 5/6/5 format described earlier (some DirectX implementations use a 5/5/5 high color pixel format). In true color buffers, pixels are stored blue byte first, green byte second, and red byte third. For example, a 16x16-pixel direct color bitmap would occupy 512 bytes in a high color virtual buffer and 768 bytes in a true color virtual buffer.

Using our familiar 9x5 triangle image, we'll first build a direct color bitmap suitable for high color virtual buffers, then we'll build the equivalent bitmap for true color virtual buffers. Here is the image:

. . . . * . . . .
. . . * x * . . .
. . * x x x * . .
. * x x x x x * .
* * * * * * * * *

Again suppose we want the triangle's perimeter pixels to be blue, and the interior pixels to be green. In a high color bitmap, the blue component is in bits 0-4 (the low-order five bits) of a 5/6/5-encoded RGB color value, and the green component is in bits 5-10. The hexadecimal number 1F has bits 0-4 set and thus produces pure blue. Similarly, 7E0 hex has bits 5-10 set and produces pure green. We therefore want to set the perimeter pixels to 1F hex and the interior pixels to 7E0 hex. As with Fastgraph's 256-color bitmap display functions, most direct color bitmap display functions treat zero pixels as transparent, so we'll set all the pixels outside the actual triangle to zero. With each pixel expressed as a 16-bit hexadecimal value, the resulting bitmap is:

0000

0000

0000

0000

001F

0000

0000

0000

0000

0000

0000

0000

001F

07E0

001F

0000

0000

0000

0000

0000

001F

07E0

07E0

07E0

001F

0000

0000

0000

001F

07E0

07E0

07E0

07E0

07E0

001F

0000

001F

001F

001F

001F

001F

001F

001F

001F

001F

Our triangle is nine pixels wide and five pixels high, for a total of 45 pixels. Because each pixel requires two bytes, we need an array of at least 90 bytes to hold the image, with each two bytes of the array holding one pixel from the bitmap. In the case of high color bitmaps, it's much easier to use an array of 16-bit integers, so we'll use a 45-element array of type word in C/C++ and Delphi, and a 45-element array of type Integer in Visual Basic. The first element of a bitmap array represents the lower left corner of the image. The subscript progression then continues to the right until reaching the end of the first row. It then resumes at the leftmost pixel of the second row and continues to the right until the end of that row. It continues in this manner for all remaining rows. Assuming subscripts begin at zero, the subscript order for our 9x5 triangle image would thus be:

[36]

[37]

[38]

[39]

[40]

[41]

[42]

[43]

[44]

[27]

[28]

[29]

[30]

[31]

[32]

[33]

[34]

[35]

[18]

[19]

[20]

[21]

[22]

[23]

[24]

[25]

[26]

[9]

[10]

[11]

[12]

[13]

[14]

[15]

[16]

[17]

[0]

[1]

[2]

[3]

[4]

[5]

[6]

[7]

[8]

And we could store the direct color bitmap in an array like this:

C/C++:

WORD triangle[] = {

0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,

0x0000,0x001F,0x07E0,0x07E0,0x07E0,0x07E0,0x07E0,0x001F,0x0000,

0x0000,0x0000,0x001F,0x07E0,0x07E0,0x07E0,0x001F,0x0000,0x0000,

0x0000,0x0000,0x0000,0x001F,0x07E0,0x001F,0x0000,0x0000,0x0000,

0x0000,0x0000,0x0000,0x0000,0x001F,0x0000,0x0000,0x0000,0x0000};

Delphi:

triangle : array [1..45] of word = (

$001F,$001F,$001F,$001F,$001F,$001F,$001F,$001F,$001F,

$0000,$001F,$07E0,$07E0,$07E0,$07E0,$07E0,$001F,$0000,

$0000,$0000,$001F,$07E0,$07E0,$07E0,$001F,$0000,$0000,

$0000,$0000,$0000,$001F,$07E0,$001F,$0000,$0000,$0000,

$0000,$0000,$0000,$0000,$001F,$0000,$0000,$0000,$0000);

Note that we can use fg_maprgb() to calculate encoded RGB values for direct color bitmaps in high color virtual buffers. For example,

C/C++:

green = fg_maprgb(0,255,0);

Delphi:

green := fg_maprgb(0,255,0);

Visual Basic:

green = fg_maprgb(0, 255, 0)

returns the encoded RGB value 07E0 hex, which is used above for the green pixels.

In true color virtual buffers, each pixel in a direct color bitmap is a three-byte RGB color value. The blue byte is stored first, followed by the green and red bytes. We would thus represent pure blue by the three bytes 255,0,0 (FF,00,00 hex) and pure green by 0,255,0 (00,FF,00 hex). To make the triangle's perimeter pixels blue and its interior pixels green, we set the perimeter pixels to FF,00,00 and the interior pixels to 00,FF,00. As with Fastgraph's 256-color bitmap display functions, most direct color bitmap display functions treat zero pixels as transparent, so we'll set all the pixels outside the actual triangle to 00,00,00. The resulting bitmap is:

00 00 00 00 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 FF 00 00 00 FF 00 FF 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 FF 00 00 00 FF 00 00 FF 00 00 FF 00 FF 00 00 00 00 00 00 00 00
00 00 00 FF 00 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 FF 00 00 00 00 00
FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00 FF 00 00

Our triangle is nine pixels wide and five pixels high, for a total of 45 pixels. Because each pixel requires three bytes, we need an array of at least 135 bytes to hold the image, with each three bytes of the array holding one pixel from the bitmap. The first element of a bitmap array represents the lower left corner of the image. The direct color bitmap subscript progression for true color buffers is the same as for high color buffers, so we could store the direct color bitmap in an array like this:

C/C++:

BYTE triangle[] = {
   0xFF,0x00,0x00, 0xFF,0x00,0x00, 0xFF,0x00,0x00, 0xFF,0x00,0x00, 0xFF,0x00,0x00,
   0xFF,0x00,0x00, 0xFF,0x00,0x00, 0xFF,0x00,0x00, 0xFF 0x00,0x00,
   0x00,0x00,0x00, 0xFF,0x00,0x00, 0x00,0xFF,0x00, 0x00,0xFF,0x00, 0x00,0xFF,0x00,
   0x00,0xFF,0x00, 0x00,0xFF,0x00, 0xFF,0x00,0x00, 0x00,0x00,0x00,
   0x00,0x00,0x00, 0x00,0x00,0x00, 0xFF,0x00,0x00, 0x00,0xFF,0x00, 0x00,0xFF,0x00,
   0x00,0xFF,0x00, 0xFF,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xFF,0x00,0x00, 0x00,0xFF,0x00,
   0xFF,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xFF,0x00,0x00,
   0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00};

Delphi:

triangle : array [1..45*3] of byte = (
   $FF,$00,$00, $FF,$00,$00, $FF,$00,$00, $FF,$00,$00, $FF,$00,$00,
   $FF,$00,$00, $FF,$00,$00, $FF,$00,$00, $FF $00,$00,
   $00,$00,$00, $FF,$00,$00, $00,$FF,$00, $00,$FF,$00, $00,$FF,$00,
   $00,$FF,$00, $00,$FF,$00, $FF,$00,$00, $00,$00,$00,
   $00,$00,$00, $00,$00,$00, $FF,$00,$00, $00,$FF,$00, $00,$FF,$00,
   $00,$FF,$00, $FF,$00,$00, $00,$00,$00, $00,$00,$00,
   $00,$00,$00, $00,$00,$00, $00,$00,$00, $FF,$00,$00, $00,$FF,$00,
   $FF,$00,$00, $00,$00,$00, $00,$00,$00, $00,$00,$00,
   $00,$00,$00, $00,$00,$00, $00,$00,$00, $00,$00,$00, $FF,$00,$00,
   $00,$00,$00, $00,$00,$00, $00,$00,$00, $00,$00,$00);

For high color virtual buffers, programs usually access direct color bitmaps in units of two bytes, as this is the amount of memory needed to store one pixel. It then makes sense to store direct color bitmaps in C/C++ and Delphi word arrays or Visual Basic Integer arrays.

For true color virtual buffers, it's usually best to store direct color bitmaps in byte arrays, just as with 256-color bitmaps. You may instead prefer to set up a structure with three one-byte fields, one per RGB component, to hold each pixel.

<< Prev

Next >>

Contents
Fastgraph Home Page

 

copyright 2001 Ted Gruber Software, Inc.