Save Bitmap-Resource
Introduction:
This function saves a bitmap resource to disk as a bmp-file. As arguments you have to specify the name of
the file to save the resource to and the handle of the resource you want to save. You get the
handle of the resource using the FindResource function.
Note that this function does not implement error handling for the sake of simplicity.
The Code:
void CreateBMFileFromResource(const char* file, HRSRC hres)
{
// get pointer to bitmap resource
HGLOBAL hresbm = LoadResource(GetModuleHandle(0), hres);
LPVOID lpresbm = LockResource(hresbm);
// use BITMAPINFO structure to read info about resource
BITMAPINFO *bmInfo = (BITMAPINFO *) lpresbm;
// calculate the size (in bytes) of the palette and the pixel data
int sizeclrtbl=0;
switch (bmInfo->bmiHeader.biBitCount) {
case 1: sizeclrtbl=2*4; break;
case 4: sizeclrtbl=16*4; break;
case 8: sizeclrtbl=256*4; break;
}
int bpl = (bmInfo->bmiHeader.biWidth * bmInfo->bmiHeader.biBitCount) / 8;
int rest=4-(bpl % 4);
if (rest==4) rest=0;
int BytesPerLine = bpl + rest;
int sizepxldata = BytesPerLine * bmInfo->bmiHeader.biHeight;
// fill the BITMAPFILEHEADER for the file
BITMAPFILEHEADER bmFileHeader;
bmFileHeader.bfType = 19778;
bmFileHeader.bfSize = 14 + 40 + sizeclrtbl + sizepxldata;
bmFileHeader.bfReserved1 = 0;
bmFileHeader.bfReserved2 = 0;
bmFileHeader.bfOffBits = 54;
// write BITMAPFILEHEADER and bitmap data to file
int bmfile = open(file, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
write(bmfile, &bmFileHeader, 14);
write(bmfile, lpresbm, 40 + sizeclrtbl + sizepxldata);
// clean up
close(bmfile);
HGLOBAL dummy = GlobalFree(hresbm);
}
Explanation:
The function LoadResource loads the given resource into global memory. The function call GetModuleHandle(0) returns the handle of the current
module, which is needed as the first parameter in the LoadResource call. The return value of LoadResource is the handle of a global
memory object. The next thing to do is to get a pointer to the resource (in the global memory) using the LockResource function. The LPVOID
value in lpresbm points to the location in the global memory at which the bitmap resource starts.
In the next line of
code, the value in lpresbm is used to initialize a BITMAPINFO structure. This works because a bitmap resource in the
global memory consists of the following elements: a BITMAPINFO structure (including the palette, if there is one) and
the pixel data itself.
The next thing to do is to find out how many bytes the colortable uses. This is done using the
biBitCount member of the BITMAPINFOHEADER-structure which itself is a member of the BITMAPINFO-structure
(see the bmp-format).
Every entry in a colortable uses four bytes. The number of entries in a colortable is 2 in 1-Bit images, 16 in 4-Bit images and
256 in 8-Bit images. So the absolute size of the colortable in bytes is the number of entries multiplied with 4. In 24-Bit
(truecolor) images there is no colortable so sizeclrtbl will contain the value zero.
The next part of the function calculates the size
of the pixel data. This is rather complicated because different values of biBitCount, as well as the rule that the number
of bytes in a line must be a multiple of four must be taken into consideration (see the
bmp-format). The variable bpl is the number of bytes per line without taking into consideration the rule
mentioned above. For example: for a 4-bit bitmap with a width of 42 pixel bpl would contain a value of
(42 * 4) / 8 = 21 bytes. The variable rest contains the number of bytes
needed to add to bpl to reach the next 4-byte boundary. For the example above, rest would contain a value
of 4 - (21 % 4) = 3. That means that 3 bytes must be added to a line of 21 bytes
to reach the next 4-byte boundary (24 bytes). The byte number of the next 4-byte boundary is stored in
BytesPerLine. The absolute size of the pixel data is calculated by simply multiplying BytesPerLine with
the number of Lines (biHeight).
In the next section a BITMAPFILEHEADER-structure, which is the first structure in a bitmap
file, is prepared and filled with the appropriate values.
Then the file specified as parameter is opened. The first write
command writes the BITMAPFILEHEADER-structure to the file. The second write command uses the pointer to the
resource (in the global memory) to write the whole resource (the BITMAPINFO-structure (with colortable, if a colortable is
used) and the pixeldata) to the file. This simple way of saving a bitmap resource to a file by just using a pointer to the
resource is only possible because of the internal format of bitmap resources, as described above.
In the 'clean up' section of the function the file is closed and the memory which was allocated for the bitmap resource
by LoadResource is set free.
Back to the main page
Copyright 1998 Stefan Hetzl. If you have questions or comments or have discovered an error,
send mail to [email protected]. You may forward this document or publish it on
your webpage as long as you don't change it and leave this notice at the end.