Game Development Reference
// Set all the bits to a known state (black).
memset(m_bits, 0, m_size);
m_width=width; m_height=height; m_bitdepth=bitdepth;
Two things to notice here. First, the code to ensure that our line widths are
exact multiples of 4.
m_swidth =( m_swidth + 3) & ~3;
We do this by adding 3 to the storage width and then bitwise And-ing this
with the bitwise complement of 3. A bitwise complement has every bit in
the number inverted. If we take an example, suppose that the width of the
bitmap is 34 pixels and it is stored as a 24-bit image. A 24-bit image uses
3 bytes of information for each pixel, so if the storage width was simply the
width times 3 then it would be 102. However, 102 is not a multiple of 4. We
need to find the next multiple of 4 greater than 102. Three as a byte wide
binary value is 00000011. The bitwise complement is 11111100. The
algorithm adds 3 to the storage width, making it 105. Now 105 as a binary
value is 01101001; note here that one of the lowest 2 bits is set, which
means it cannot be a multiple of 4. 01101001 And 11111100 = 01101000,
which is 104. This is divisible by 4 as required. The effect of the operation
is to clear the last 2 bits of the number. This kind of alignment is used
regularly in such buffers because it allows a pixel location in memory to be
found with fewer instructions. The memory variable, m_swidth, holds the
storage width of a single line and m_size keeps a check on the buffer size,
so that we can easily check for out of bounds memory errors.
The other curiosity is the call to CreateBMI. Our canvas uses a
Windows structure called BITMAPINFO, so that ultimately we can display
the canvas on the user's screen using a simple Windows API call.
A BITMAPINFO contains a BITMAPINFOHEADER and a single
RGBQUAD. We are only interested in the BITMAPINFOHEADER, so we
cast our member variable to a header to fill in the appropriate details. By
keeping it in a function call, this minimizes the changes necessary to port
this code to another platform.
// Clear any existing header.
If (m_pBMI) delete m_pBMI;