我在进行屏幕抓图后,能够将其保存为真彩色图像,可是,我想将其保存为灰度图像,总不能如愿,已经困扰我很长时间了,各位帮我!
我的保存图像代码为:其中,hBitmap为抓图后得到的图像句柄,
请问我该如何修改下面的保存代码才能将其存为灰度图像呢?BOOL CDibP::SaveAsTrueBmpToFile(HBITMAP hBitmap, CString lpFileName)
{
HDC hDC;  
//设备描述表 
int iBits;  
//当前显示分辨率下每个像素所占字节数 
WORD wBitCount;  
//位图中每个像素所占字节数 
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; 
BITMAP Bitmap;  
//位图属性结构 
BITMAPFILEHEADER bmfHdr;  
//位图文件头结构 
BITMAPINFOHEADER bi;  
//位图信息头结构  
LPBITMAPINFOHEADER lpbi;  
//指向位图信息头结构 
HANDLE fh, hDib, hPal,hOldPal=NULL; 
//定义文件,分配内存句柄,调色板句柄 
//计算位图文件每个像素所占字节数 
hDC = CreateDC("DISPLAY",NULL,NULL,NULL); 
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
DeleteDC(hDC); 
if (iBits <= 1) wBitCount = 1; 
else if (iBits <= 4)  wBitCount = 4; 
else if (iBits <= 8)  wBitCount = 8; 
else   wBitCount = 24; 
//计算调色板大小 ,下面这条语句已经失去意义了
//if (wBitCount <= 8)  dwPaletteSize = (1 << wBitCount) * sizeof(RGBQUAD); 
//设置位图信息头结构 
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap); 
bi.biSize = sizeof(BITMAPINFOHEADER); 
bi.biWidth = Bitmap.bmWidth; 
bi.biHeight = Bitmap.bmHeight; 
bi.biPlanes = 1; 
bi.biBitCount = wBitCount; 
bi.biCompression = BI_RGB; 
bi.biSizeImage = 0; 
bi.biXPelsPerMeter = 0; 
bi.biYPelsPerMeter = 0; 
bi.biClrUsed = 0; 
bi.biClrImportant = 0; 
 
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32)* 4*Bitmap.bmHeight ; 
//为位图内容分配内存 
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize+sizeof(BITMAPINFOHEADER)); 
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
*lpbi = bi; 
// 处理调色板  
hPal = GetStockObject(DEFAULT_PALETTE); 
if (hPal) 

hDC = ::GetDC(NULL); 
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
RealizePalette(hDC); 

// 获取该调色板下新的像素值 
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); 
//恢复调色板  
if (hOldPal) 

::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
RealizePalette(hDC); 
::ReleaseDC(NULL, hDC); 

//创建位图文件  
fh = CreateFile(lpFileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 
if (fh == INVALID_HANDLE_VALUE)  return FALSE; 
// 设置位图文件头 
bmfHdr.bfType = 0x4D42; // "BM" 
dwDIBSize = sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER)+ dwPaletteSize + dwBmBitsSize;  
bmfHdr.bfSize = dwDIBSize; 
bmfHdr.bfReserved1 = 0; 
bmfHdr.bfReserved2 = 0; 
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; 
// 写入位图文件头 
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
// 写入位图文件其余内容 
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); 
//清除  
GlobalUnlock(hDib); 
GlobalFree(hDib); 
CloseHandle(fh); 
return TRUE;
}

解决方案 »

  1.   

    需要说明的是:我从屏幕获取的iBits=32,所以只能将其赋值为24,存为灰度图象了,请大家多多指教!!
      

  2.   

    变成ibits=8
    建一个indexPallete
    然后将每一位变成相应灰度的索引值
      

  3.   

    楼上仁兄的意思我明白,可是,图像数据呢?它是包含RGB三色的,难道我还要把他存为真彩色图像后再打开不成?我建立了新的调色板,可是,图像颜色失真,显然不对,请高手指教!
      

  4.   

    我有一个办法不知是否可行:
    |Y|    |0.299   0.587  0.114| |R|
    |I| =  |0.596  -0.274 -0.322| |G|
    |Q|    |0.211  -0.523  0.312| |B|
    其中的竖线表示矩阵运算。
    这是北美的电视系统所采用的色彩系统,其中的Y为亮度,也就是灰度图中的灰度值,你可以利用上面的算法得出Y的值,它对应的即为0~255。我也没有试过,不过你可以试试看会不会失真??