#define COLORREF2RGB(Color) (Color & 0xff00) | ((Color >> 16) & 0xff) / | ((Color << 16) & 0xff0000) HBITMAP ReplaceColor (HBITMAP hBmp,COLORREF cOldColor,COLORREF cNewColor) { HBITMAP RetBmp=NULL; if (hBmp) { HDC BufferDC=CreateCompatibleDC(NULL); // 源位图DC if (BufferDC) { SelectObject(BufferDC,hBmp); // 选入DC中 HDC DirectDC=CreateCompatibleDC(NULL); // 目标DC if (DirectDC) { // 获取源位图大小 BITMAP bm; GetObject(hBmp, sizeof(bm), &bm); // 初始化BITMAPINFO信息,以便使用CreateDIBSection BITMAPINFO RGB32BitsBITMAPINFO; ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO)); RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); RGB32BitsBITMAPINFO.bmiHeader.biWidth=bm.bmWidth; RGB32BitsBITMAPINFO.bmiHeader.biHeight=bm.bmHeight; RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1; RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32; UINT * ptPixels; HBITMAP DirectBitmap= CreateDIBSection(DirectDC, (BITMAPINFO *)&RGB32BitsBITMAPINFO, DIB_RGB_COLORS,(void **)&ptPixels, NULL, 0); if (DirectBitmap) { HGDIOBJ PreviousObject=SelectObject(DirectDC, DirectBitmap); BitBlt(DirectDC,0,0,bm.bmWidth,bm.bmHeight,BufferDC,0,0,SRCCOPY); // 转换 COLORREF 为 RGB cOldColor=COLORREF2RGB(cOldColor); cNewColor=COLORREF2RGB(cNewColor); // 替换颜色 for (int i=((bm.bmWidth*bm.bmHeight)-1);i>=0;i--) { if (ptPixels[i]==cOldColor) ptPixels[i]=cNewColor; } // 修改位图 DirectBitmap SelectObject(DirectDC,PreviousObject); // 完成 RetBmp=DirectBitmap; } // 释放DC DeleteDC(DirectDC); } // 释放DC DeleteDC(BufferDC); } } return RetBmp; } 用法: HBITMAP hBmp2 = LoadBitmap(g_hinstance,MAKEINTRESOURCE(IDB_SAMPLEBITMAP)); HBITMAP hBmp = ReplaceColor(hBmp2,0xff0000,0x00ff00); // 替换蓝色为绿色 ...... DeleteObject(hBmp2); DeleteObject(hBmp); 2. 如何转换并保存位图 //******************************************************************************** //* 名称:DDBToDIB //* 作者:徐景周(jingzhou_xu@163.net) //* 功能:设备相关转换为设备无关位图 //******************************************************************************** HANDLE CScreenSnapDlg::DDBToDIB( CBitmap& bitmap, DWORD dwCompression /* = BI_RGB */) { BITMAP bm; BITMAPINFOHEADER bi; LPBITMAPINFOHEADER lpbi; DWORD dwLen; HANDLE hDIB; HANDLE handle; HDC hDC; HPALETTE hPal; CWindowDC dc( this ); CPalette pal; //如果支持调色板的话,则建立它 if( dc.GetDeviceCaps( RASTERCAPS ) & RC_PALETTE ) { UINT nSize = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 ); LOGPALETTE* pLP = (LOGPALETTE*)new BYTE[nSize]; pLP->palVersion = 0x300; pLP->palNumEntries = (unsigned short)GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry ); pal.CreatePalette( pLP ); //释放 delete[] pLP; } ASSERT( bitmap.GetSafeHandle() ); //不支持BI_BITFIELDS类型 if( dwCompression == BI_BITFIELDS ) return NULL; //如果调色板为空,则用默认调色板 hPal = (HPALETTE) pal.GetSafeHandle(); if (hPal==NULL) hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE); //获取位图信息 bitmap.GetObject(sizeof(bm),(LPSTR)&bm); //初始化位图信息头 bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; bi.biBitCount = (unsigned short)(bm.bmPlanes * bm.bmBitsPixel) ; bi.biCompression = dwCompression; bi.biSizeImage = 0; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; //计算信息头及颜色表大小 int nColors = 0; if(bi.biBitCount <= 8) { nColors = (1 << bi.biBitCount); } dwLen = bi.biSize + nColors * sizeof(RGBQUAD); hDC = ::GetDC(NULL); hPal = SelectPalette(hDC,hPal,FALSE); RealizePalette(hDC); //为信息头及颜色表分配内存 hDIB = GlobalAlloc(GMEM_FIXED,dwLen); if (!hDIB){ SelectPalette(hDC,hPal,FALSE); ::ReleaseDC(NULL,hDC); return NULL; } lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB); *lpbi = bi; //调用 GetDIBits 计算图像大小 GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight, (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS); bi = *lpbi; //图像的每一行都对齐(32bit)边界 if (bi.biSizeImage == 0){ bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight; if (dwCompression != BI_RGB) bi.biSizeImage = (bi.biSizeImage * 3) / 2; } //重新分配内存大小,以便放下所有数据 dwLen += bi.biSizeImage; handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE) ; if (handle != NULL) hDIB = handle; else { GlobalFree(hDIB); //重选原始调色板 SelectPalette(hDC,hPal,FALSE); ::ReleaseDC(NULL,hDC); return NULL; } //获取位图数据 lpbi = (LPBITMAPINFOHEADER)hDIB; //最终获得的DIB BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, //扫描行起始处 (DWORD)bi.biHeight, //扫描行数 (LPBYTE)lpbi //位图数据地址 + (bi.biSize + nColors * sizeof(RGBQUAD)), (LPBITMAPINFO)lpbi, //位图信息地址 (DWORD)DIB_RGB_COLORS); //颜色板使用RGB if( !bGotBits ) { GlobalFree(hDIB); SelectPalette(hDC,hPal,FALSE); ::ReleaseDC(NULL,hDC); return NULL; } SelectPalette(hDC,hPal,FALSE); ::ReleaseDC(NULL,hDC); return hDIB; } //******************************************************************************** //* 名称:SaveBitmapToFile //* 修改:徐景周(jingzhou_xu@163.net) //* 功能:保存为位图文件 //******************************************************************************** BOOL CScreenSnapDlg::SaveBitmapToFile(HBITMAP hBitmap , CString lpFileName) { HDC hDC; //设备描述表 int iBits; //当前显示分辨率下每个像素所占字节数 WORD wBitCount; //位图中每个像素所占字节数 DWORD dwPaletteSize=0, //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 dwBmBitsSize, dwDIBSize, dwWritten; 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 if (iBits <= 24) 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, (LPBITMAPINFO)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; }