Many applications store images permanently as files. For example, drawing applications store pictures, spreadsheet applications store charts, CAD applications store drawings, and so on.
The following code is a function definition for a function which allocates memory for and initializes members within a BITMAPINFOHEADER data structure:
PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp) {
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
/* Retrieve the bitmap's color format, width, and height. */
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
errhandler("GetObject", hwnd);
/* Convert the color format to a count of bits. */
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else
cClrBits = 32;
/* */
/* Allocate memory for the BITMAPINFO data structure. */
/* (This structure contains a BITMAPINFOHEADER as */
/* well as an array of RGBQUAD data structures.) */
/* */
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * cClrBits);
/* */
/* There is no RGBQUAD array for the 24-bit-per-pel */
/* format. */
/* */
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
/* Initialize the fields in the BITMAPINFO structure */
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
/* If the bitmap is not compressed, set the BI_RGB flag. */
pbmi->bmiHeader.biCompression = BI_RGB;
/* */
/* Compute the number of bytes in the array of color- */
/* indices and store in biSizeImage. */
/* */
pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
* pbmi->bmiHeader.biHeight
* cClrBits;
/* */
/* Set biClrImportant to 0 -- indicating that all of the */
/* device colors are important. */
/* */
/* */
pbmi->bmiHeader.biClrImportant = 0;
return (pbmi);
}
The following code is a function definition for a function which initializes the remaining data structures, retrieves the array of palette indices, opens the file, copies the data, and closes the file:
void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi,
HBITMAP hBMP, HDC hDC)
{
HANDLE hf; /* file handle */
BITMAPFILEHEADER hdr; /* bitmap file-header */
PBITMAPINFOHEADER pbih; /* bitmap info-header */
HANDLE hmem; /* memory handle */
LPBYTE lpBits; /* memory pointer */
DWORD dwTotal; /* total count of bytes */
DWORD cb; /* incremental count of bytes */
BYTE *hp; /* byte pointer */
DWORD dwTmp;
pbih = (PBITMAPINFOHEADER) pbi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
if (!lpBits)
errhandler("GlobalAlloc", hwnd);
/* */
/* Retrieve the color table (RGBQUAD array) and the bits */
/* (ie. array of palette indices) from the DIB. */
/* */
if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight,
lpBits, pbi, DIB_RGB_COLORS))
errhandler("GetDIBits", hwnd);
/* Create the .bmp file */
hf = CreateFile(pszFile,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
(LPSECURITY_ATTRIBUTES) NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
errhandler("CreateFile", hwnd);
hdr.bfType = 0x4d42; /* 0x42 = "B" 0x4d = "M" */
/* Compute the size of the entire file. */
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrImportant
* sizeof(RGBQUAD) + pbih->biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
/* Compute the offset to the array of color indices. */
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrImportant
* sizeof (RGBQUAD);
/* Copy the BITMAPFILEHEADER into the .bmp file. */
if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
errhandler("WriteFile", hwnd);
/* Copy the BITMAPINFOHEADER and RGBQUAD array into file. */
if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
+ pbih->biClrImportant * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
errhandler("WriteFile", hwnd);
/* Copy the array of color indices into the .bmp file */
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;
while (cb > MAXWRITE) {
if (!WriteFile(hf, (LPSTR) hp, (int) MAXWRITE,
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
errhandler("WriteFile", hwnd);
cb-= MAXWRITE;
hp += MAXWRITE;
}
if (!WriteFile(hf, (LPSTR) hp, (int) cb,
(LPDWORD) &dwTmp, (LPOVERLAPPED) NULL))
errhandler("WriteFile", hwnd);
/* Close the .bmp file */
if (!CloseHandle(hf))
errhandler("CloseHandle", hwnd);
/* Unlock and free memory. */
GlobalUnlock(hmem);
GlobalFree(hmem);
}