图片处理的一些函数


自己经常写的,写多了就慢慢总结下来,方便:

//---------------------------------------------------
// 函数介绍:把资源写入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,

优质内容筛选与推荐>>
1、Windows与Linux下进程间通信技术比较
2、mysql查询优化
3、Apache Tika:通用的内容分析工具
4、Asp.net WebServer
5、hadoop配置远程客户端


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号