www.pudn.com > final_6.rar > Dib.cpp


// Dib.cpp: implementation of the CDib class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "CG.h" 
#include "Dib.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDib::CDib() 
{ 
	m_pRGBQuad = NULL;		//RGBQUAD 表项 
    m_pDibData = NULL;		//位图像素数据 
	m_nWidth = 0;			//宽度 
	m_nHeight = 0;			//高度 
	m_nBitCount = 0;		//每个像素占有的位数 
    m_nTotalColors = 0;		//颜色总数 
    m_pBitmapInfoHeader = NULL; 
	m_hDIB = 0; 
} 
 
CDib::~CDib() 
{ 
	DeleteDIB(); 
	m_pRGBQuad = NULL;		//RGBQUAD 表项 
    m_pDibData = NULL;		//位图像素数据 
	m_nWidth = 0;			//宽度 
	m_nHeight = 0;			//高度 
	m_nBitCount = 0;		//每个像素占有的位数 
    m_nTotalColors = 0;		//颜色总数 
    m_pBitmapInfoHeader = NULL; 
	m_hDIB = 0; 
} 
 
void CDib::DeleteDIB() 
{ 
	if (m_hDIB != NULL) 
	{ 
		::GlobalFree((HGLOBAL) m_hDIB); 
		m_hDIB=NULL; 
	} 
	if (m_palDIB != NULL) 
	{ 
//		delete m_palDIB; 
	} 
} 
 
BOOL CDib::Load(LPCTSTR lpszFileName) 
{ 
	HDIB hDIB; 
	CFile file; 
	CFileException fe; 
	if (!file.Open(lpszFileName, CFile::modeRead|CFile::shareDenyWrite, &fe)) 
	{ 
		AfxMessageBox(fe.m_cause); 
		return FALSE; 
	} 
	TRY 
	{ 
		hDIB = ::ReadDIBFile(file); 
	} 
	CATCH (CFileException, eLoad) 
	{ 
		file.Abort();  
		return FALSE; 
	} 
	END_CATCH 
	DeleteDIB(); //清除旧位图 
	m_hDIB=hDIB; 
 
	//获取位图文件头指针 
	BYTE* pbyDib = (BYTE*)::GlobalLock(m_hDIB); 
	m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pbyDib; 
		 
	//宽度和高度 
	m_nWidth = m_pBitmapInfoHeader->biWidth; 
	m_nHeight = m_pBitmapInfoHeader->biHeight; 
	//每像素的颜色位数 
	m_nBitCount = (BYTE)m_pBitmapInfoHeader->biBitCount; 
    //颜色数 
    m_nTotalColors = GetColorNumber(); 
    if (m_pBitmapInfoHeader->biClrUsed == 0) 
		m_pBitmapInfoHeader->biClrUsed = m_nTotalColors; 
	//指向位图颜色索引表项的指针, 如果没有颜色表项, 则该值为NULL 
    m_pRGBQuad = (RGBQUAD*)(pbyDib + m_pBitmapInfoHeader->biSize); 
	//颜色索引表的大小(字节) 
    DWORD dwColorTableSize = m_nTotalColors * sizeof(RGBQUAD); 
    //指向位图数据的指针 
	m_pDibData = pbyDib + m_pBitmapInfoHeader->biSize + dwColorTableSize; 
 
	m_palDIB = new CPalette; 
 
	if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL) 
	{ 
		// DIB有可能没有调色板 
		delete m_palDIB; 
        m_palDIB = NULL; 
	} 
	return TRUE; 
} 
 
BOOL CDib::LoadFromResource(UINT nID) 
{ 
	//从资源中载入DIB 
 	HINSTANCE hResInst = AfxGetResourceHandle(); 
 	HRSRC hFindRes; 
 	HDIB hDIB; 
 	LPSTR pDIB; 
 	LPSTR pRes; 
 	HGLOBAL hRes; 
 
 	//搜寻指定的资源 
 	hFindRes = ::FindResource(hResInst, MAKEINTRESOURCE(nID), RT_BITMAP); 
 	if (hFindRes == NULL) return FALSE; 
	hRes = ::LoadResource(hResInst, hFindRes); //载入位图资源 
	DWORD dwSize=::SizeofResource(hResInst,hFindRes); 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize); 
	if (hDIB == NULL) return FALSE; 
	pDIB = (LPSTR)::GlobalLock((HGLOBAL)hDIB); 
    pRes = (LPSTR) ::LockResource(hRes); 
 	memcpy(pDIB, pRes, dwSize); //把hRes中的内容复制hDIB中 
	::GlobalUnlock((HGLOBAL) hDIB); 
    DeleteDIB(); 
	m_hDIB=hDIB; 
 
	//获取位图文件头指针 
	BYTE* pbyDib = (BYTE*)::GlobalLock(m_hDIB); 
	m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pbyDib; 
		 
	//宽度和高度 
	m_nWidth = m_pBitmapInfoHeader->biWidth; 
	m_nHeight = m_pBitmapInfoHeader->biHeight; 
	//每像素的颜色位数 
	m_nBitCount = (BYTE)m_pBitmapInfoHeader->biBitCount; 
	//颜色数 
	m_nTotalColors = GetColorNumber(); 
    if (m_pBitmapInfoHeader->biClrUsed == 0) 
		m_pBitmapInfoHeader->biClrUsed = m_nTotalColors; 
	//指向位图颜色索引表项的指针, 如果没有颜色表项, 则该值为NULL 
    m_pRGBQuad = (RGBQUAD*)(pbyDib + m_pBitmapInfoHeader->biSize); 
	//颜色索引表的大小(字节) 
    DWORD dwColorTableSize = m_nTotalColors * sizeof(RGBQUAD); 
    //指向位图数据的指针 
	DWORD s= m_pBitmapInfoHeader->biSize; 
	m_pDibData = pbyDib + s+ dwColorTableSize; 
 
	m_palDIB = new CPalette; 
	if (::CreateDIBPalette(m_hDIB, m_palDIB) == NULL) 
	{ 
		// DIB有可能没有调色板 
 		delete m_palDIB; 
 		m_palDIB = NULL; 
 	} 
	return TRUE; 
} 
 
int CDib::Width() 
{ 
	if(m_hDIB==NULL) return 0; 
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); 
	int cxDIB = (int) ::DIBWidth(lpDIB); 
	::GlobalUnlock((HGLOBAL) m_hDIB); 
	return cxDIB; 
} 
 
int CDib::Height() 
{ 
	if(m_hDIB==NULL) return 0; 
	LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) m_hDIB); 
	int cyDIB = (int) ::DIBHeight(lpDIB); // Size of DIB - y 
	::GlobalUnlock((HGLOBAL) m_hDIB); 
	return cyDIB; 
} 
 
BOOL CDib::Draw(CDC *pDC, int x, int y, int cx, int cy) 
{ 
	//显示DIB,该函数具有缩放功能 
    //参数x和y说明了目的矩形的左上角坐标,cx和cy说明了目的矩形的尺寸 
	//cx和cy若有一个为0则该函数按DIB的实际大小绘制,cx和cy的缺省值是0 
	int dx=Width(); 
	int dy=Height(); 
	if(m_hDIB==NULL) return FALSE; 
	CRect rDIB,rDest; 
	rDest.left=x; 
	rDest.top=x; 
	if(cx==0||cy==0) 
	{ 
		cx=dx; 
		cy=dy; 
	} 
	rDest.right=rDest.left+cx; 
	rDest.bottom=rDest.top+cy; 
	rDIB.left=rDIB.top=0; 
	rDIB.right=Width(); 
	rDIB.bottom=Height(); 
 
	return ::PaintDIB(pDC->GetSafeHdc(),&rDest,m_hDIB,&rDIB,m_palDIB); 
} 
 
//将所有格式的数据转换成DDB--32位数据, 存放于lpbyDdb32 
//返回获取数据的总数. 
//32位DDB数据按字节顺序:蓝色--绿色--红色--保留字节-- 
DWORD  CDib::GetDdbData32(LPBYTE lpbyDdb32) 
{ 
	VERIFY(lpbyDdb32); 
 
	//计算DIB位图中一行的字节量 
	DWORD dwDibWidthBytes = GetDibWidthBytes(m_nWidth, m_nBitCount); 
 
	//转换成32位DDB后每行的大小, 注意每位4字节 
	DWORD dwDdbWidthBytes =  m_nWidth * 4; 
 
	if(m_nBitCount == 1) 
	{ 
		//每行实际字节数, 8个像素对应一个字节. 
		long nLineBytes = (m_nWidth + 7) / 8; 
		BYTE abyBitMask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; 
		 
		//DIB位图数据的行头 
		DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes; 
		 
		//DDB 32位位图数据的行头 
		DWORD dwDdbBaseIndex = 0; 
 
		for(long i = 0;i < m_nHeight;i++) 
		{ 
			//指向DIB行数据的指针 
			BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex; 
	 
			//指向 DDB 32位位图的数据的指针 
			BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex; 
			for(long j = 0;j < nLineBytes;j++) 
			{ 
				//8个像素数据的索引值 
				BYTE byBit8 =  *(pbyDibRaw++); 
				for(int n = 0; n < 8;n++) 
				{ 
					BYTE byBitSingle = (byBit8 & abyBitMask[n]) >> (7 - n); 
					 
					*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbBlue;	//蓝色 
					*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbGreen;	//绿色 
					*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbRed;	//红色 
					pbyDdbRaw++;										//保留** 
				} 
			}//end j 
			dwDibBaseIndex -= dwDibWidthBytes; 
			dwDdbBaseIndex += dwDdbWidthBytes; 
		}//end i 
		return (dwDdbWidthBytes * m_nHeight); 
	}// end if(m_nBitCount == 1) 
	else if(m_nBitCount == 4) 
	{ 
		//每行实际字节数 
		long nLineBytes = (m_nWidth + 1) / 2; 
 
		//DIB位图数据的行头 
		DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes; 
		 
		//DDB 32位位图数据的行头 
		DWORD dwDdbBaseIndex = 0; 
 
		for(long i = 0;i < m_nHeight;i++) 
		{ 
			//指向DIB行数据的指针 
			BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex; 
			 
			//指向 DDB 32位位图的数据的指针 
			BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex; 
			for(long j = 0;j < nLineBytes;j++) 
			{ 
				//两个像素数据的索引值, 通过高四位和低四位 
				BYTE byBit8 =  *(pbyDibRaw++); 
				BYTE byBitHigh = (byBit8 & 0xF0) >> 4; 
				BYTE byBitLow = (byBit8 & 0x0F); 
				 
				*(pbyDdbRaw++) = m_pRGBQuad[byBitHigh].rgbBlue;		//蓝色 
				*(pbyDdbRaw++) = m_pRGBQuad[byBitHigh].rgbGreen;	//绿色 
				*(pbyDdbRaw++) = m_pRGBQuad[byBitHigh].rgbRed;		//红色 
				pbyDdbRaw++; 
 
				*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbBlue;		//蓝色 
				*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbGreen;		//绿色 
				*(pbyDdbRaw++) = m_pRGBQuad[byBitLow].rgbRed;		//红色 
				pbyDdbRaw++; 
 
			}//end j 
			dwDibBaseIndex -= dwDibWidthBytes; 
			dwDdbBaseIndex += dwDdbWidthBytes; 
		}//end i 
		return (dwDdbWidthBytes * m_nHeight); 
	}// end if(m_nBitCount == 4) 
	else if(m_nBitCount == 8) 
	{ 
		//DIB位图数据的行头 
		DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes; 
		 
		//DDB 32位位图数据的行头 
		DWORD dwDdbBaseIndex = 0; 
		for(long i = 0;i < m_nHeight;i++) 
		{ 
			//指向DIB行数据的指针 
			BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex; 
		 
			//指向 DDB 32位位图的数据的指针 
			BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex; 
			for(long j = 0;j < m_nWidth;j++) 
			{ 
				//一个像素数据的索引值 
				BYTE byIndex = *(pbyDibRaw++); 
	 
				*(pbyDdbRaw++) = m_pRGBQuad[byIndex].rgbBlue;	//蓝色 
				*(pbyDdbRaw++) = m_pRGBQuad[byIndex].rgbGreen;	//绿色 
				*(pbyDdbRaw++) = m_pRGBQuad[byIndex].rgbRed;	//红色 
				pbyDdbRaw++; 
			}//end j 
			dwDibBaseIndex -= dwDibWidthBytes; 
			dwDdbBaseIndex += dwDdbWidthBytes; 
		}//end i 
		return (dwDdbWidthBytes * m_nHeight); 
	}// end if(m_nBitCount == 8) 
	else if(m_nBitCount == 24) 
	{ 
		//DIB位图数据的行头 
		DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes; 
		 
		//DDB 32位位图数据的行头 
		DWORD dwDdbBaseIndex = 0; 
		for(long i = 0;i < m_nHeight;i++) 
		{ 
						//指向DIB行数据的指针 
			BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex; 
		 
			//指向 DDB 32位位图的数据的指针 
			BYTE* pbyDdbRaw = lpbyDdb32 + dwDdbBaseIndex; 
			for(long j = 0;j < m_nWidth;j++) 
			{ 
				*(pbyDdbRaw++) = *(pbyDibRaw++);	//蓝色 
				*(pbyDdbRaw++) = *(pbyDibRaw++);	//绿色 
				*(pbyDdbRaw++) = *(pbyDibRaw++);	//红色 
				pbyDdbRaw++;						 
			}//end j			 
			dwDibBaseIndex -= dwDibWidthBytes; 
			dwDdbBaseIndex += dwDdbWidthBytes; 
		}//end i 
		return (dwDdbWidthBytes * m_nHeight); 
	}// end if(m_nBitCount == 24) 
 
 
	return (m_nWidth * m_nHeight); 
} 
 
//每行的字节宽度 
DWORD CDib::GetDibWidthBytes(int nWidth,  BYTE byBitCount) 
{ 
	DWORD dwWidthBytes = (DWORD)nWidth;	//8-bits 
	if(byBitCount == 1) dwWidthBytes = (nWidth + 7) / 8; 
	else if(byBitCount == 4) dwWidthBytes = (nWidth + 1) / 2; 
	else if(byBitCount == 24) dwWidthBytes = 3 * nWidth ; 
	 
	while((dwWidthBytes & 3) != 0)dwWidthBytes++; 
 
	return dwWidthBytes; 
} 
 
UINT CDib::GetColorNumber() const 
{	 
	UINT nColors = 0; 
 
    if ((m_pBitmapInfoHeader->biClrUsed == 0) && 
          (m_pBitmapInfoHeader->biBitCount < 9)) 
	{ 
		switch (m_pBitmapInfoHeader->biBitCount) 
		{ 
		    case 1: nColors = 2; break; 
		    case 4: nColors = 16; break; 
		    case 8: nColors = 256;break; 
		} 
	} 
    else 
		nColors = (UINT) m_pBitmapInfoHeader->biClrUsed; 
    return nColors; 
}