If you ever need to maniipulate the bits and the information in a bitmap file you will need to go beyond the standard loading and saving functions available in Delphi. The following page describes the Bitmap file format and includes code for directly reading a bitmap file. Note that the code only applies to Windows bitmaps (not OS/2 bitmaps) and at the moment while it reads in Run Length Encoded bitmaps it does not decompress them (what you get is some garbled pixels along the bottom of the bitmap.) If you try to use the routine on an OS/2 bitmap, however, as it is currently written right now it will raise an exception. What I find I need at the moment is a way to directly manipulate Windows formatted bitmaps, and that is what the procedural code included here does.
You can download the source as a Delphi 3/ Delphi 5 project here -> bitmap.zip 9 KB
You can also download the source as a simple text file here -> bitmap.txt
Note that these files are also included in the larger zip files posted at the top of the Main Delphi index page on this site...
The Bitmap file format begins with a file header, declared in the code as follows:
type
TBitmapFileHeader = record
bmfIdentifier : Word; {'BM'}
bmfFileSize : dWord;
bmfReserved : dWord;
bmfBitMapDataOffset : dWord; {from begin of file}
end;
The first two bytes identify the file as a bitmap file, and contain the byte values for the letters 'BM'. OS/2 formatted bitmaps are supposed to use their own tags in this field, but I have found that they can also start with the letters 'BM', which isn't helpful if you want to avoid loading an OS/2 formatted bitmap, if you want to identify the bitmap as being in OS/2 format. The other possible values for this field are supposed to be as follows : ‘BA’ : OS/2 Bitmap Array; ‘CI’ : OS/2 Color Icon; ‘CP’ : OS/2 Color Pointer; ‘IC’ : OS/2 Icon; ‘PT’ : OS/2 Pointer... I have not encountered any OS/2 files matching these types, but as I mentioned, I have found that OS/2 bitmaps, rather than beginning with 'BA' can be found to start with 'BM' which is the Microsoft Windows format tag for their version of the Bitmap format (thus raising an exception when the code expects data in the specified format but finds something else instead.)
The Filesize field specifies the total size of the file, including the header data, and the Offset field indicates where the actual bits that describe the bitmap begin, offset from the very beginning of the file.
The file header is followed immediately by the Bitmap info header, declared in the accompanying code segment as follows:
TBitmapInfoHeader = record
biSize: Longint; {size of tbitmapinfoheader = 40}
biWidth: Longint; {bitmap width}
biHeight: Longint; ( height of bitmap)
biPlanes: Word; {always 1}
biBitCount: Word; {number color bits 4 = 16 colors, 8 = 256 pixel is a byte}
biCompression: Longint; {compression used, 0 }
biSizeImage: Longint; ( size of the pixel data)
biXPelsPerMeter: Longint; {not used, 0 }
biYPelsPerMeter: Longint; {not used, 0 }
biClrUsed: Longint; {number of colors used}
biClrImportant: Longint; {important colors}
end;
The first few fields are self explanatory. The Bitcount field specifies how a pixel is encoded in the pixel data. For example a nibble (4 bits) specifies that each 8 bit byte encodes two pixels, and so on, and the bitcount also directly relates to the color count (4 bits can encode 16 possible values giving the bitmap a total of 16 colors.) This field corresponds to the ClrUsed field if the bitmap is actually using all its possible colors, however if, for example an 8 bit bitmap, with 256 possible colors, has '200' in the ClrUsed field, then the size of the palette of the bitmap will be '200' and the additional 56 possible values are ignored. The PelsPerMeter fields doesn't seem to be particularly important, is often just set to zero, and is supposed to describe how many pixels are to be displayed in one meter of space (in case anyone has a monitor a meter wide). This seems to relate to how the bitmap was intended to be displayed and viewed. The ClrImportant field is intended to describe how many colors in the palette are important to properly display the bitmap, since it is possible for an operating system to map a bitmap to the system palette. The 'important colors' are supposed to be the first ones entered into the palette data of the bitmap which immediately follows the bitmap info header.
The compression field can contain information on whether or not the bitmap is RLE compressed, and is also supposed to identify certain types of OS/2 compression (thus giving a person a second chance to identify an OS/2 encoded bitmap and avoid raising an exception). The possible values for the compression field are described as being :
0 (or BI_RGB) : none
1 (or BI_RLE8) : RLE 8-bits per pixel
2 (or BI_ RLE4) : 4-bit / pixel
3 (or BI_BITFIELDS) : Bitfields
You should note here that it is possible that the information I base this on was in error and that the values for 1 and 2 should be swapped (1 = RLE 4 and 2 = RLE 8). The only way to be sure is to decode a Run Length Encoded bitmap and see what happens, something I have not yet done, but I just mention this because it seems to me that 4 should come before 8. The algorithms for Run Length Encoding are standard and confirming this information one way or another is simply a matter of implementing the code. For the purposes of this code this field should be '0' (an uncompressed bitmap).
The Bitmap info header is followed by a color palette if the bitcount of the graphic file is less than or equal to 8. Bitmaps with a palette of more than 256 colors do not include a palette but rather the bits of the map for each pixel encode values that are mapped to the system palette. Each entry in the palette consists of 4 bytes, a red value, a green value, and a blue value, and a normally unused value referred to as a 'flag'. The fourth value in the RGB quad appears to be in place because of the architecture of the Intel processors (which align data on four byte boundaries or something to that effect). However I have found that by setting the flag byte a bit map can be covered with a colored 'film', which seems to be a clue that if one wants to 'select' an icon, this can be done by setting a value in the flag section of the RGB quad, resulting in a blue 'film' over the selected object. (By setting this value to '255' if I remember right, I got a purplish film over an icon, not the familiar blue, and I haven't explored the matter much more after that, but as I said, this seems to be a clue as to how to go about changing the color of a selected graphic).
The structure of an RGB quad is as follows:
TRGBQuad = record
rgbRed: Byte;
rgbGreen: Byte;
rgbBlue: Byte;
rgbReserved: Byte;
end;
It is not actually required to declare an RGB quad in code, since it is encapsulated in Logical Palette structure of the API. RGB quads are not used directly by the system, but rather are converted to system color values by the API. In order to get a RGB quad palette converted by the API into a form actually used by the system it must be encapsulated in a 'LogPalette' structure:
tagLogPalette = record
palVersion : word; { $300 hex is the standard version at present}
palNumEntries : word; {the Color Count, number of entries in palette}
palPalEntry : PALETTEENTRY; {first member of array of RGB quad structures}
end;
An example of declaring this structure, reading in the palette values, converting it to system palette, and then passing the handle to this palette to a bitmap is included in the source code related to this page. It seems strange to me, but if you read in an RGB quad in the order, red, green, blue, you get a backwards colored bitmap, while if you read it in as 'blue, green, red' you get a normal colored bitmap after creating the palette.
After the RGB quads which describe the palette (if the bitmap uses 8 bits or less and a palette exists) comes the actual bits which describe the pixels of the bitmap (the size of which is described in the 'SizeImage' field of the Bitmap Info Header). If there are more than 8 bits and more than 256 colors in the Bitmap the pixel data immediately follows the header.
The code segment that accompanies this page should be pretty straightforward and easy to understand. Two memos are used to display the file header info, and the bitmap info header entries. The procedure opens the bitmap file as an untyped binary file set to read 1 byte and then proceeds to read in the values of the headers. It then allocates memory for the Logical Palette structure based on the color count and the number of entries in the palette (if one exists on disk). It then reads in the palette bytes, filling in the structure, calls the API to create the system palette, and uses the returned handle to assign this palette to the bitmap being created. The height, width, and pixel format of the bitmap are set as specified in the header file. Bitmaps are stored upside down (much as the palette seems to be as described above) and so finally the routine reads in each line of the bitmap from disk and fills in the created bitmap from the bottom up. The completed bitmap is displayed in an image.
A Unified Field Theory
![]()
The Unified Field Theory
is also available as a zip file -> unified.zip
Introduction :The Pioneer Effect and the New Physics. A brief description of the new physics required to explain the 'Pioneer Effect', which is the constant deceleration of space craft as they fly through space.

