图片处理的一些函数
自己经常写的,写多了就慢慢总结下来,方便:
//---------------------------------------------------
// 函数介绍:把资源写入lpImage,支持BMP,PNG,JPG.
// 输入参数:
// 输出参数:
// 返回值:
//---------------------------------------------------
BOOL CImageManager::LoadResImage(UINT nResID, LPCTSTR lpType, Bitmap *&lpImage, HINSTANCE hInstance) { lpImage = NULL; hInstance = (NULL == hInstance) ? ::AfxGetResourceHandle() : hInstance; // If bmp,use system load. if (RT_BITMAP == lpType) { HBITMAP hBmp = ::LoadBitmap(hInstance, MAKEINTRESOURCE(nResID)); lpImage = Bitmap::FromHBITMAP(hBmp, 0); ::DeleteObject(hBmp); if (!lpImage) { TRACE("lpImage is NULL\n"); return FALSE; } else { if (Gdiplus::Ok != lpImage->GetLastStatus()) { TRACE("lpImage is error\n"); return FALSE; } else { return TRUE; } } } // User-Defined HRSRC hRsrc = ::FindResource(hInstance, MAKEINTRESOURCE(nResID), lpType); if (!hRsrc) { TRACE("hRscs is NULL\n"); return FALSE; } // Load resource into memory --------------------------------- DWORD len = ::SizeofResource(hInstance, hRsrc); BYTE *lpRsrc = (BYTE*)::LoadResource(hInstance, hRsrc); if (!lpRsrc) { TRACE("lpRsrc is NULL\n"); return FALSE; } // Allocate global memory on which to create stream ---------- HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, len); BYTE *pMem = (BYTE*)::GlobalLock(hMem); memcpy(pMem, lpRsrc, len); IStream *pStream = NULL; // You can query MSDN,why I use TRUE, -- hgy notes. HRESULT ht = ::CreateStreamOnHGlobal(hMem, TRUE, &pStream); if (S_OK != ht) { TRACE("ht is error\n"); return FALSE; } // Load from stream ------------------------------------------- lpImage = Gdiplus::Bitmap::FromStream(pStream); // free/release stuff ----------------------------------------- ::GlobalUnlock(hMem); pStream->Release(); ::FreeResource(lpRsrc); if (!lpImage) { TRACE("lpImage is NULL\n"); return FALSE; } else { if (Gdiplus::Ok != lpImage->GetLastStatus()) { TRACE("lpImage is error\n"); return FALSE; } else { return TRUE; } } }
//---------------------------------------------------
// 函数介绍:抓取当前窗口的图片
// 输入参数: 传NULL抓的是这个窗口下面的屏幕背景.(如果是透明的,就是透明的背景)
// 输出参数:
// 返回值:
//---------------------------------------------------
HBITMAP CImageManager::GetWindowBitmap(HWND hWnd, LPRECT lpRect) { if (!lpRect) { return NULL; } HDC hDC = NULL; if (NULL == hWnd) { hDC = ::GetDC(HWND_DESKTOP); } else { hDC = ::GetWindowDC(hWnd); } if (NULL == hDC) { return NULL; } HDC hMemDC = ::CreateCompatibleDC(hDC); HBITMAP hBitmap = ::CreateCompatibleBitmap(hDC, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top); if (NULL == hBitmap) { return NULL; } HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemDC, hBitmap); ::BitBlt(hMemDC, 0, 0, lpRect->right-lpRect->left, lpRect->bottom-lpRect->top, hDC, lpRect->left, lpRect->top, SRCCOPY); ::SelectObject(hMemDC, hOldBitmap); ::DeleteDC(hMemDC); ::ReleaseDC(hWnd, hDC); return hBitmap; }
//---------------------------------------------------
// 函数介绍:把HBITMAP保存成文件
// 输入参数:
// 输出参数:
// 返回值:
//---------------------------------------------------
BOOL CImageManager::SaveBitmapToFile(HBITMAP hBitmap, CString FileName) { if (hBitmap==NULL || FileName.IsEmpty()) { return false; } // ----------------------------------------------------- //DIB文件有四个主要部分: // 文件表头 // 信息表头 // RGB色彩对照表(不一定有) // 位图图素位 //Windows中DIB的扩展版本: // 以BITMAPFILEHEADER结构开始,接着是BITMAPINFOHEADER结构 // // ----------------------------------------------------- //指向位图信息头结构 LPBITMAPINFOHEADER lpbi; //定义文件,分配内存句柄,调色板句柄 HANDLE fh, hDib, hPal,hOldPal=NULL; //计算位图文件每个像素所占字节数 HDC hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); //当前分辨率下每象素所占字节数 int iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); DeleteDC(hDC); WORD wBitCount; if (iBits <= 1) { wBitCount = 1; } else if (iBits <= 4) { wBitCount = 4; } else if (iBits <= 8) { wBitCount = 8; } else { wBitCount = 24; } //定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数 DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; //位图属性结构 BITMAP Bitmap; ::GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap); //位图信息头结构 /* -------------------------------------------------------------- struct tagBITMAPINFOHEADER{ DWORD biSize;//40 LONG biWidth;//BITMAP::bmWidth LONG biHeight;//BITMAP::bmHeight WORD biPlanes;//1 WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER ----------------------------------------------------------------*/ BITMAPINFOHEADER bi; 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.biClrImportant = 0; bi.biClrUsed = 0; // ------------------------------------------------------- // 以字节为单位的每行长度始终是4的倍数。行的长度可以计算为: // RowLength = 4 * ((bmch.bcWidth * bmch.bcBitCount + 31) / 32) ; // 或者在C内用更有效的方法: // RowLength = ((bmch.bcWidth * bmch.bcBitCount + 31) & ~31) >> 3 ; // ------------------------------------------------------- //图素数据的总字节数等于RowLength和Bitmap.bmHeight的乘积。 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(FileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (fh == INVALID_HANDLE_VALUE) return FALSE; //位图文件头结构 /* -------------------------------------------------------------- struct tagBITMAPFILEHEADER { WORD bfType;// "BM" 或 0x4D42 DWORD bfSize;//整个文件的大小. WORD bfReserved1;//0 WORD bfReserved2;//0 DWORD bfOffBits;//指出了文件中图素位开始位置的字节偏移量,此数值来自DIB信息表头中的信息,为了使用的方便提供在这里 //这样,我们可以很快定位到图形数据的起始位. } BITMAPFILEHEADER --------------------------------------------------------------*/ BITMAPFILEHEADER bmfHdr; // 设置位图文件头 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; }
//---------------------------------------------------
// 函数介绍:改变HBITMAP中所有的A值
// 输入参数:
// 输出参数:
// 返回值:
//---------------------------------------------------
void CImageManager::ChangeHBitmapAlpha(HBITMAP hBitmap, int alpha) { DWORD dwSize = ::GetBitmapBits(hBitmap, 0, NULL); char *lpBuffer = new char[dwSize]; ::GetBitmapBits(hBitmap,dwSize,lpBuffer); for(int i = 0; i+3<dwSize; i+=4) { lpBuffer[i+3] = alpha; //lpBuffer[i+0] = 0;//B //lpBuffer[i+1] = 0;//G //lpBuffer[i+2] = 0;//R } ::SetBitmapBits(hBitmap,dwSize, lpBuffer); delete[] lpBuffer; }
过几天贴个DEMO,