24位真彩色位图如果想保存位256色,即8位位图,关键是构造合适的调色板,同时考虑程序的运行效率。如果采用Windows自带的调色版来创建,则最后生成的图片失真太大,甚至惨不忍睹。下面采用一个更加优化的方式,使得生成的256色位图基本和24位的原图一致,函数代码如下:
void Save256Bmp(void)
{
// TODO: 在此添加实现代码
//::MessageBox(NULL, _T("test"), _T("Note"), MB_OK);
//准备拷贝桌面图像
HDC hDeskTopDC = ::GetDC(NULL); //取得桌面DC
HDC hMemDC = ::CreateCompatibleDC(hDeskTopDC); //创建兼容DC
int iScreenX = ::GetSystemMetrics(SM_CXSCREEN);
int iScreenY = ::GetSystemMetrics(SM_CYSCREEN);
HBITMAP hMemBmp = ::CreateCompatibleBitmap(hDeskTopDC, iScreenX, iScreenY); //创建兼容位图
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, hMemBmp);
//拷贝图像
::BitBlt(hMemDC, 0, 0, iScreenX, iScreenY, hDeskTopDC, 0, 0, SRCCOPY);
SaveDCToBmp(hMemDC, hMemBmp, _T("C:/temp.bmp"));
//设置位图信息头结构
BITMAPINFOHEADER tInfoHeader;
tInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
tInfoHeader.biWidth = iScreenX;
tInfoHeader.biHeight = iScreenY;
tInfoHeader.biPlanes = 1;
tInfoHeader.biBitCount = 24; // 256色位图是位,即一个颜色点占个字节
tInfoHeader.biCompression = BI_RGB;
tInfoHeader.biSizeImage = 0;
tInfoHeader.biXPelsPerMeter = 0;
tInfoHeader.biYPelsPerMeter = 0;
tInfoHeader.biClrUsed = 0;
tInfoHeader.biClrImportant = 0;
DWORD SrcBufSize; // 源图缓冲区大小
DWORD OffBits;
DWORD DstBufSize;
LPBITMAPINFOHEADER lpImgData;
HLOCAL hTempImgData;
LPBITMAPINFOHEADER lpTempImgData;
HDC hDc;
HFILE hf;
BITMAPFILEHEADER DstBf;
BITMAPINFOHEADER DstBi;
LOGPALETTE *pPal;
HPALETTE hPrevPalette;
HLOCAL hPal;
WORD i,j;
int Red,Green,Blue,ClrIndex;
DWORD ColorHits[4096];
WORD ColorIndex[4096];