Ask not what your bitmap can do for you, but what you can do for your bitmap! Once you know how bitmap files are formatted you'll be able to do a whole host of things you could never do before. Compress your bitmaps using your own routines, modify bitmap data/colouring on the fly, create your own bitmap files from scratch (screencaptures!), and many more! Excited? I know I am! :)
The first thing you'll find stored in a bitmap file is what's called the File Header structure:
Private Type BITMAPFILEHEADER
bfType As Integer
bfSize As Long
bfReserved1 As Integer
bfReserved2 As Integer
bfOffBits As Long
End Type
Now for the Info Header structure:
Private Type BITMAPINFOHEADER
biSize As Long
biWidth As Long
biHeight As Long
biPlanes As Integer
biBitCount As Integer
biCompression As Long
biSizeImage As Long
biXPelsPerMeter As Long
biYPelsPerMeter As Long
biClrUsed As Long
biClrImportant As Long
End Type
Now, biBitCount is an important one. It describes the "bit-depth" of this bitmap. It can have any of four values: 1, 4, 8, and 24. A bit depth of one indicates that the bitmap will have only two colours (monochrome), a bit depth of 4 will allow 16 colours, 8bit equals 256 colours, and 24bit is 16.8 million colours. Now the bit depth dictates whether or not a bitmap will use a colour table (discussed later). 24bit bitmaps DO NOT use a colour table, while the other bit formats do.
biCompression indicates whether or not RLE (Run Length Encoding) is used to compress the bitmap data. I won't get into the algorithm here, but if you're really interested feel free to email me about it. Simply set this to zero for no compression. biSizeImage contains the length of the bitmap image data (the actual pixels) in bytes. You might expect this to simply be equal to the width multiplied by the height, but it isn't always... more on that later.
biXPelsPerMeter and biYPelsPerMeter describe the resolution of the bitmap in pixels per meter. To go with standard resolution, just set these to zero. biClrUsed indicates how many of the colour table colours are actually used in the bitmap, set to zero to use all colours. biClrImportant tells the program which colours are most important, this can increase the display speed under some circumstances. Simply set this to zero for standard operation.
Now, we've described the bitmap, all that's left is to list the colours to be used (if it's not 24bit) and then store the actual per-pixel data. First, lets look at the structure used for the colour table (or palette):
Private Type RGBQUAD
rgbBlue As Byte
rgbGreen As Byte
rgbRed As Byte
rgbReserved As Byte
End Type
24bit bitmaps, on the other hand, have no colour table because each pixel is made up of 3bytes, each describing the intensity of a specific colour channel (red, green, or blue). There is no need to look up a colour in the table since 16.8million can be described by each 3byte triplet. An 8bit bitmap, on the other hand, would only be able to display 256 colours without a colour table, since you can only store 256 discrete values within an 8bit span. Similarly, for 4bit bitmaps, only 16 combinations can be stored in the 4bit span. Therefore, having a colour look-up table at the start of the bitmap enables these lower bit formats to display a variety of colours, not simply a fixed set of 256 or 16.
Finally the bitmap data itself can be stored in a simple array of bytes:
Dim BMPData() As Byte
This works just the same for the scan lines at any bit depth, they all have to end on 32bit boundaries. If a 1bit bitmap was 30 pixels wide, then there'd have to be 2bits of padding (30 pixels * 1bit per pixel = 30bits, 2 bits short). I'm sure you get the picture now.
The only other thing you need to know about bitmaps is that the pixel data is stored from the bottom left hand corner and progressing upward with scan lines from left to right. So the whole bottom row is stored first, then the second from the bottom, etc, until the final pixel from the top right-corner of the bitmap is stored at last. Bear this in mind when you store your data or read data from a bitmap, otherwise your picture will come out upside-down.
To open a bitmap and modify or extract the data, simply access it in binary mode:
Open "SAMPLE.BMP" For Binary Access Read Write Lock Write As #1
Dim BMPFileHeader As BITMAPFILEHEADER
Dim BMPInfoHeader As BITMAPINFOHEADERGet #1, 1, BMPFileHeader
Get #1, , BMPInfoHeader
See my Bitmap File Format Project for further information and for an example of how to put these principles to use.