⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pic.cpp

📁 一个国人自己实现图像库的程序(有参考价值)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "..\..\Include\Pic\Pic.h"

//===================================================================
BOOL  FCDib::Create (int iWidth, int iHeight, WORD wColorBit)
{
	if ((iHeight < 0) || (iWidth < 0))
		return FALSE ; // 不支持自上而下存储的DIB
	if (pFooDib->hBitmap != NULL)
		this->Unload () ;

	// retrieve screen's setting
	if ((iWidth == 0) || (iHeight == 0) || (wColorBit == 0))
	{
		HDC		hSrcDC = ::CreateIC (TEXT("display"), NULL, NULL, NULL) ;
		if (iWidth == 0)	iWidth = (DWORD) GetDeviceCaps (hSrcDC, HORZRES) ;
		if (iHeight == 0)	iHeight = (DWORD) GetDeviceCaps (hSrcDC, VERTRES) ;
		if (wColorBit == 0)	wColorBit = (WORD) GetDeviceCaps (hSrcDC, BITSPIXEL) ;	
		::DeleteDC(hSrcDC) ;
	}

	// create DIB info header
	BITMAPINFOHEADER *bmhf = (BITMAPINFOHEADER *) new BYTE[sizeof(BITMAPINFO) + ((wColorBit <= 8) ? (4 * (1 << wColorBit)) : 0)] ;
	bmhf->biSize           = sizeof (*bmhf) ;
	bmhf->biWidth          = iWidth ;
	bmhf->biHeight         = iHeight ;
	bmhf->biPlanes         = 1 ;
	bmhf->biBitCount       = wColorBit ;
	bmhf->biCompression    = BI_RGB ;

	// create DIBSection
	pFooDib->hBitmap = CreateDIBSection (NULL, (BITMAPINFO *)bmhf, DIB_RGB_COLORS, (VOID **)(&pFooDib->pByte), NULL, 0) ;
	delete[] bmhf ;
	if (pFooDib->hBitmap == NULL)
		return FALSE ;

	// get created DIB's information
	DIBSECTION		DibInfo ;
	::GetObject (pFooDib->hBitmap, sizeof (DIBSECTION), &DibInfo) ;
	CopyMemory (&pFooDib->DibInfo, &DibInfo.dsBmih, sizeof (BITMAPINFOHEADER)) ;
	pFooDib->DibInfo.biCompression = BI_RGB ; // if color == 16 bit, this field meybe be modified

	// create a line pointer, to accelerate pixel access
	pFooDib->ppLine = (BYTE **) new BYTE [sizeof(BYTE *) * iHeight] ;
	DWORD	dwPitch = this->GetPitch () ;
	pFooDib->ppLine[0] = pFooDib->pByte + (iHeight - 1) * dwPitch ;
	for (int Y = 1 ; Y < iHeight ; Y++)
		pFooDib->ppLine[Y] = pFooDib->ppLine[Y - 1] - dwPitch ;

	// if the DIB's color bit <= 8, set a gray palette to it
	if (this->ColorBits() <= 8)
		this->SetGrayPalette () ;
	return TRUE ;
}
//===================================================================
HBITMAP  FCDib::GetDDB_Handle (HDC hdc)
{
	BITMAPINFOHEADER	* pbmfh ;
	int					  nNum = 1 << this->ColorBits() ;
	HBITMAP				  hBitmap ;
	bool				  bCreate = false ;

	if (this->GetHandle() == NULL)
		return NULL ;

	if (hdc == NULL)
	{
		hdc = ::CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
		bCreate = true ;
	}
	pbmfh = (BITMAPINFOHEADER *) new BYTE [sizeof(BITMAPINFO) + ((ColorBits() <= 8) ? (nNum * 4) : 0)] ;
	CopyMemory (pbmfh, &pFooDib->DibInfo, sizeof(BITMAPINFOHEADER)) ;

	// 8 位以下色设置调色板
	if (this->ColorBits() <= 8)
		this->GetColorTable (0, nNum, (RGBQUAD *)(pbmfh + 1)) ;

	hBitmap = CreateDIBitmap (hdc, (BITMAPINFOHEADER *)pbmfh, CBM_INIT,
							  (VOID *)pFooDib->pByte, (BITMAPINFO *)pbmfh, DIB_RGB_COLORS) ;
	delete[] pbmfh ;
	if (bCreate)
		::DeleteDC (hdc) ;
	return hBitmap ;
}
//===================================================================
void  FCDib::Unload ()
{
	if (pFooDib->ppLine != NULL)
		delete[] pFooDib->ppLine ;
	if (pFooDib->hBitmap != NULL)
		::DeleteObject (pFooDib->hBitmap) ;
	pFooDib->ppLine  = NULL ;
	pFooDib->hBitmap = NULL ;
	pFooDib->pByte   = NULL ;
	::ZeroMemory (&pFooDib->DibInfo, sizeof(pFooDib->DibInfo)) ;
}
//===================================================================
DWORD  FCDib::GetPixelData (int x, int y) const
{
	BYTE		* pPixel = this->GetBits (x, y) ;
	DWORD		dwrgb ;
	switch (this->ColorBits ())
	{
		case  1 :  return 0x01 & (* pPixel >> (7 - (x & 7))) ;
		case  4 :  return 0x0F & (* pPixel >> (x & 1 ? 0 : 4)) ;
		case  8 :  return * (BYTE *) pPixel ;
		case 16 :  return * (WORD *) pPixel ;
		case 24 :  CopyMemory (&dwrgb, pPixel, 3) ; return dwrgb ;
		case 32 :  return * (DWORD *) pPixel ;
	}
	return 0 ;
}
//===================================================================
RGBQUAD  FCDib::ParsePixelData (DWORD dwData) const
{
	RGBQUAD		rgb ;
	// 取得调色板索引
	if (this->ColorBits() <= 8)
		this->GetColorTable ((int)dwData, &rgb) ;
	switch (this->ColorBits())
	{
		case 24 : CopyMemory (&rgb, &dwData, 3) ; break ;
		case 32 : CopyMemory (&rgb, &dwData, 4) ; break ;
		case 16 : rgb = fooSplit16Bit_555 ((WORD)dwData) ; break ;
	}
	return rgb ;
}
//===================================================================
void  FCDib::SetPixelData (int x, int y, DWORD dwPixel)
{
	BYTE	* pPixel = this->GetBits (x, y) ;
	switch (this->ColorBits ())
	{
		case  1 :  * pPixel &= ~(1     << (7 - (x & 7))) ;
				   * pPixel |= dwPixel << (7 - (x & 7)) ;
				   break ;
		case  4 :  * pPixel &= 0x0F    << (x & 1 ? 4 : 0) ;
				   * pPixel |= dwPixel << (x & 1 ? 0 : 4) ;
				   break ;
		case  8 :  * pPixel = (BYTE) dwPixel ;
				   break ;
		case 16 :  * (WORD *) pPixel = (WORD) dwPixel ;
				   break ;
		case 24 :  CopyMemory (pPixel, &dwPixel, 3) ;
				   break ;
		case 32 :  * (DWORD *) pPixel = dwPixel ;
				   break ;
		default :
			return ;
	}
}
//===================================================================
//	只对 16, 24, 32 位色有效
void  FCDib::SetPixelColor (int x, int y, RGBQUAD rgb)
{
	DWORD		dwPixel ;
	switch (this->ColorBits())
	{
		case 24 :
		case 32 : dwPixel = * (DWORD *) &rgb ; break ;
		case 16 : dwPixel = (DWORD) fooCombine16Bit_555 (&rgb) ; break ;
		default :
			return ; // 不支持的格式
	}
	this->SetPixelData (x, y, dwPixel) ;
}
//===================================================================
BOOL  FCDib::GetColorTable (int iFirstIndex, int iNumber, RGBQUAD * pColors) const
{
	if ((this->GetHandle() == NULL) || (this->ColorBits() > 8) || (pColors == NULL))
		return FALSE ;
	HDC		hdcMem = CreateCompatibleDC (NULL) ;
	HBITMAP	hBitmap = (HBITMAP) SelectObject (hdcMem, pFooDib->hBitmap) ;
	BOOL	iReturn = (BOOL)::GetDIBColorTable (hdcMem, iFirstIndex, iNumber, pColors) ;
	SelectObject (hdcMem, hBitmap) ;
	DeleteDC (hdcMem) ;
	return iReturn ;
}
//===================================================================
BOOL  FCDib::SetColorTable (int iFirstIndex, int iNumber, RGBQUAD * pColors)
{
	if ((this->GetHandle() == NULL) || (this->ColorBits() > 8) || (pColors == NULL))
		return FALSE ;
	HDC		hdcMem = CreateCompatibleDC (NULL) ;
	HBITMAP	hBitmap = (HBITMAP) SelectObject (hdcMem, pFooDib->hBitmap) ;
	BOOL	iReturn = (BOOL)::SetDIBColorTable (hdcMem, iFirstIndex, iNumber, pColors) ;
	SelectObject (hdcMem, hBitmap) ;
	DeleteDC (hdcMem) ;
	return iReturn ;
}
//===================================================================
BOOL FCDib::AttachDDB (HBITMAP hBitmap, int iColor)
{
	if (hBitmap == NULL)
		return FALSE ;
	BITMAP		  bm ;
	GetObject (hBitmap, sizeof(BITMAP), &bm) ;
	if (!this->Create ((int)bm.bmWidth, (int)bm.bmHeight, (WORD)iColor))
		return FALSE ;

	// set the dib's header you want to get
	BITMAPINFOHEADER  * pBmif ;
	int				  nNum = 1 << iColor  ;
	pBmif = (BITMAPINFOHEADER *) new BYTE [sizeof(BITMAPINFO) + ((iColor <= 8) ? (4 * nNum) : 0)] ;
	::CopyMemory (pBmif, &pFooDib->DibInfo, sizeof(*pBmif)) ;

	//	<=8会收到调色板, 手动设置
	HDC		hdc = CreateIC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
	::GetDIBits (hdc, hBitmap, 0, bm.bmHeight, this->GetMemStart(), (BITMAPINFO *)pBmif, DIB_RGB_COLORS) ;
	if (iColor <= 8)
		this->SetColorTable (0, nNum, (RGBQUAD*)(pBmif + 1)) ;
	DeleteDC (hdc) ;
	delete[] pBmif ;
	return TRUE ;
}
//===================================================================
BOOL  FCDib::CaptureScreen (LPRECT lpRect)
{
	HDC		hSrcDC = NULL, hMemDC = NULL ;
	BOOL	bRet = FALSE ;

	__try
	{
		hSrcDC = CreateDC (TEXT("DISPLAY"), NULL, NULL, NULL) ;
		if (hSrcDC == NULL)
			__leave ;

		if (GetDeviceCaps (hSrcDC, BITSPIXEL) <= 8) // palette format
			__leave ;

		hMemDC = CreateCompatibleDC (hSrcDC) ;
		if (hMemDC == NULL)
			__leave ;
		
		RECT	rect, rcSrc ;
		rcSrc.left = rcSrc.top = 0 ;
		rcSrc.right = GetDeviceCaps (hSrcDC, HORZRES) ;
		rcSrc.bottom = GetDeviceCaps (hSrcDC, VERTRES) ;
		if (lpRect != NULL)
			::IntersectRect (&rect, &rcSrc, lpRect) ;
		else
			::CopyRect (&rect, &rcSrc) ;

		if (!this->Create (rect.right - rect.left, rect.bottom - rect.top, GetDeviceCaps (hSrcDC, BITSPIXEL)))
			__leave ;

		HBITMAP	hTemp = (HBITMAP) SelectObject (hMemDC, pFooDib->hBitmap) ;
		bRet = ::BitBlt (hMemDC, 0, 0, rect.right - rect.left,
						 rect.bottom - rect.top,
						 hSrcDC, rect.left, rect.top, SRCCOPY) ;
		SelectObject (hMemDC, hTemp) ;	// 置换 hBitmap
	}
	__finally
	{
		if (hMemDC != NULL)		DeleteDC (hMemDC) ;
		if (hSrcDC != NULL)		DeleteDC (hSrcDC) ;
	}
	return bRet ;
}
//===================================================================
void  FCDib::ConvertColorTo (int iColor)
{
	if (this->ColorBits () == iColor)
		return ;

	HBITMAP	hBitmap = this->GetDDB_Handle () ;
	this->AttachDDB (hBitmap, iColor) ;
	::DeleteObject (hBitmap) ;
}
//===================================================================
FCDib & FCDib::operator= (const FCDib & pic)
{
	if ((&pic != this) && (pic.GetHandle () != NULL))
		if (this->Create (pic.Width (), pic.Height (), pic.ColorBits ()))
		{
			// pixel copy
			::CopyMemory (this->GetMemStart (), pic.GetMemStart (), pic.GetPitch () * this->Height ()) ;

			// palette copy
			if (pic.ColorBits() <= 8)
			{
				int			iColor = 1 << pic.ColorBits() ;
				RGBQUAD		* Palette = new RGBQUAD [iColor] ;
				pic.GetColorTable (0, iColor, Palette) ;
				this->SetColorTable (0, iColor, Palette) ;
				delete[] Palette ;
			}
		}
	return *this ;
}
//===================================================================
int  FCDib::ColorsUsed () const
{
	int		iCounter = 0,
			iMaxColor = 1 << (min (ColorBits(), 24)) ;
	BYTE	* pMap = (PBYTE) ::VirtualAlloc (NULL, iMaxColor + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE) ;
	if (pMap != NULL)
	{
		//	VirtualAlloc分配的mem已初始化为0
		for (DWORD y = 0 ; y < this->Height() ; y++)
			for (DWORD x = 0 ; x < this->Width() ; x++)
			{
				if (pMap[this->GetPixelData (x, y) & 0x00FFFFFF] == 0)
				{
					pMap[this->GetPixelData (x, y) & 0x00FFFFFF] = 1 ;
					iCounter++ ;
				}
				if (iCounter == iMaxColor)
					goto CountOver ;
			}
CountOver :
		::VirtualFree (pMap, 0, MEM_RELEASE) ;
	}
	return iCounter ;
}
//===================================================================
BOOL  FCDib::TakeKeyColor (RGBQUAD * rgb)
{
	BOOL		bResult = FALSE ;
	BYTE		* pMap = NULL ;
	if (this->ColorBits() <= 8)
		return FALSE ;

	__try
	{
		int		iCounter = 0,
				iMaxColor = 1 << min(ColorBits(), 24) ;
		pMap = (BYTE *) ::VirtualAlloc (NULL, iMaxColor + 1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE) ;
		if (pMap == NULL)
			__leave ;
		
		//	VirtualAlloc分配的mem已初始化为0
		for (DWORD y = 0 ; y < this->Height() ; y++)
			for (DWORD x = 0 ; x < this->Width() ; x++)
				if (pMap[this->GetPixelData (x, y) & 0x00FFFFFF] == 0)
				{
					pMap[this->GetPixelData (x, y) & 0x00FFFFFF] = 1 ;
					iCounter++ ;
					if (iCounter == iMaxColor)
						__leave ;
				}

		//	查找颜色
		DWORD	idx = 0 ;
		while (!bResult)
			if (pMap[idx] == 0)
			{
				* rgb = this->ParsePixelData (idx) ;
				bResult = TRUE ;
			}
			else
				idx++ ;
	}
	__finally
	{
		if (pMap != NULL)
			::VirtualFree (pMap, 0, MEM_RELEASE) ;
	}
	return bResult ;
}
//===================================================================
void  FCDib::SetGrayPalette ()
{
	if ((this->GetHandle() != NULL) && (this->ColorBits() <= 8))
	{
		// 设置调色板
		int			nNum = 1 << this->ColorBits() ;
		int			nSpan = 255 / (nNum - 1) ;
		RGBQUAD		* palette = new RGBQUAD[nNum] ;
		for (int i=0 ; i < nNum ; i++)
		{
			palette[i].rgbRed = palette[i].rgbGreen = palette[i].rgbBlue = i * nSpan ;
		}
		this->SetColorTable (0, nNum, palette) ;
		delete[] palette ;
	}
}
//===================================================================
void  FCDib::ConvertToGray ()
{
	if ((this->GetHandle() == NULL) || this->IsGrayPalette ())
		return ;

	// <= 8 bit, 直接修改调色板和索引值
	if (this->ColorBits() <= 8)
	{
		int			nNum = 1 << this->ColorBits() ;
		RGBQUAD		* palette = new RGBQUAD[nNum] ;
		this->GetColorTable (0, nNum, palette) ;
		for (int i=0 ; i < nNum ; i++)
		{
			int		gray = FCDib::fooGetGrayscale (palette[i]) ;
			palette[i].rgbBlue = gray ;
			palette[i].rgbGreen = gray ;
			palette[i].rgbRed = gray ;
		}
		// 修改索引
		for (int y=0 ; y < (int)this->Height() ; y++)
			for (int x=0 ; x < (int)this->Width() ; x++)
				this->SetPixelData (x, y, *(DWORD*)&palette[this->GetPixelData (x, y)]);
		delete[] palette ;
		this->SetGrayPalette () ;
		return ;
	}

	// 保存原始数据
	FCDib		OldDib (* (FCDib *) this) ;
	if (this->Create (OldDib.Width(), OldDib.Height(), 8))
	{
		// 设置8位灰度调色板
		this->SetGrayPalette () ;

		// 设置象素
		for (int y=0 ; y < (int)this->Height() ; y++)
		{
			BYTE	* pDest = this->GetBits (y) ;
			for (int x=0 ; x < (int)this->Width() ; x++)
			{
				RGBQUAD		rgb ;
				OldDib.GetPixelColor (x, y, &rgb) ;
				*pDest++ = FCDib::fooGetGrayscale (rgb) ;
			}
		}
	}
}
//===================================================================
void  FCDib::ConvertTo16Bit ()
{
	if ((this->GetHandle() == NULL) || (this->ColorBits () == 16))
		return ;

	// 保存原始数据
	FCDib		OldPic (* (FCDib *) this) ;
	if (this->Create (OldPic.Width(), OldPic.Height(), 16))
	{
		// 获取调色板
		RGBQUAD		* prgb = NULL ;
		if (OldPic.ColorBits() <= 8)
		{
			int		nNum = 1 << OldPic.ColorBits() ;
			prgb = new RGBQUAD [nNum] ;
			OldPic.GetColorTable (0, nNum, prgb) ;
			for (int i=0 ; i < nNum ; i++) // ==> 16
				* (DWORD *) &prgb[i] = (DWORD) FCDib::fooCombine16Bit_555 (&prgb[i]) ;
		}

		// 颜色转换
		int			nOldSpan = OldPic.ColorBits() / 8, x, y ; // 3 or 4
		for (y = 0 ; y < (int)this->Height() ; y++)
		{
			BYTE	* pNew = this->GetBits (y) ;
			BYTE	* pOld = OldPic.GetBits (y) ;
			switch (OldPic.ColorBits())
			{
				case 1 :
				case 4 : // 1,4 ==> 16
					for (x = 0 ; x < (int)this->Width() ; x++)
						this->SetPixelData (x, y, *(DWORD *)&prgb[(BYTE)OldPic.GetPixelData (x, y)]) ;
					break ;
				case 8 : // 8 ==> 16
					for (x = 0 ; x < (int)this->Width() ; x++, pNew += 2)
						CopyMemory (pNew, &prgb[pOld[x]], 2) ;
					break ;
				case 24 :
				case 32 : // 24,32 ==> 16
					for (x = 0 ; x < (int)this->Width() ; x++, pNew += 2, pOld += nOldSpan)
						* (WORD *) pNew = FCDib::fooCombine16Bit_555 ((RGBQUAD *)pOld) ;
					break ;
			}
		}
		if (prgb != NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -