【使用GetDIBits函数将DDB转换为使用调色板的DIB的程序】
#include <stdio.h>
#include <Windows.h>
#pragma warning(disable: 4996)
LPBYTE AllocateBits(int nWidth, int nHeight, int nBitcCount, int *pSize)
{
*pSize = (int)((nWidth * nBitcCount + 31) / 32) * 4 * nHeight;
if (*pSize < 0)
*pSize = -*pSize;
return (LPBYTE)malloc(*pSize);
}
// 设置调色板中的颜色
void set_palette(LPBITMAPINFO info)
{
info->bmiColors[0].rgbBlue = 14;
info->bmiColors[0].rgbGreen = 201;
info->bmiColors[0].rgbRed = 255;
info->bmiColors[1].rgbBlue = 235;
info->bmiColors[1].rgbGreen = 35;
info->bmiColors[1].rgbRed = 90;
}
int main(void)
{
BITMAPFILEHEADER fileheader;
FILE *fp;
HBITMAP hbmp;
HDC hdc, hdcMem;
int width, height;
int size, infosize;
LPBITMAPINFO info; // 位图信息和调色板
PBYTE pBits;
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
printf("屏幕分辨率: %dx%d\n", width, height);
hdc = GetDC(NULL);
hbmp = CreateCompatibleBitmap(hdc, width, height);
hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hbmp);
BitBlt(hdcMem, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
ReleaseDC(NULL, hdc);
infosize = sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD);
info = (LPBITMAPINFO)malloc(infosize);
ZeroMemory(info, infosize);
info->bmiHeader.biSize = sizeof(info->bmiHeader);
info->bmiHeader.biPlanes = 1;
info->bmiHeader.biBitCount = 1;
info->bmiHeader.biWidth = width;
info->bmiHeader.biHeight = height;
set_palette(info);
pBits = AllocateBits(width, height, info->bmiHeader.biBitCount, &size);
GetDIBits(hdcMem, hbmp, 0, height, pBits, info, DIB_PAL_COLORS); // DDB -> DIB
set_palette(info); // GetDIBits会修改调色板中的颜色
fileheader.bfReserved1 = fileheader.bfReserved2 = 0;
fileheader.bfSize = sizeof(fileheader) + infosize + size;
fileheader.bfType = *(PWORD)"BM";
fileheader.bfOffBits = sizeof(fileheader) + infosize;
fp = fopen("file.bmp", "wb");
if (fp != NULL)
{
fwrite(&fileheader, sizeof(fileheader), 1, fp);
fwrite(info, infosize, 1, fp);
fwrite(pBits, size, 1, fp);
fclose(fp);
}
else
puts("打开文件失败");
free(info);
free(pBits);
DeleteObject(hbmp);
DeleteDC(hdcMem);
}