www.pudn.com > vehiclehsv.rar > Hdib.cpp, change:2002-03-20,size:13240b


// HDib.cpp: implementation of the CDib class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "HDib.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CDib::CDib() 
{ 
	m_BmpLoaded=FALSE; 
	m_Buffer=0; 
	m_Buffer1=0; 
	m_BmpInfo=0; 
	m_Quad=0; 
	m_hPal=0; 
	BmpMarker=('M'<<8)|'B'; 
	Width=0; 
	Height=0; 
} 
 
CDib::~CDib() 
{ 
	Free(); 
} 
 
//释放所有动态分配的内存: 
void CDib::Free() 
{ 
	if(m_Buffer) 
	{ 
		delete [] m_Buffer; 
		m_Buffer=0; 
	} 
	if(m_Buffer1) 
	{ 
		delete [] m_Buffer1; 
		m_Buffer1=0; 
	} 
	if(m_BmpInfo) 
	{ 
		delete [] m_BmpInfo; 
		m_BmpInfo=0; 
	} 
	if(m_Quad) 
	{ 
		delete [] m_Quad; 
		m_Quad=0; 
	} 
} 
 
void CDib::Resize(int sz) 
{ 
	if(m_Buffer) 
	{ 
		delete [] m_Buffer; 
		m_Buffer=0; 
	} 
	if(m_Buffer1) 
	{ 
		delete [] m_Buffer1; 
		m_Buffer1=0; 
	} 
	m_Buffer=new BYTE[sz]; 
	m_Buffer1=new BYTE[sz]; 
//位图每一行占据的字节数: 
	Bpl=(DWORD)WIDTHBYTES(BPP*Width); //一种使bpl为4的整数倍的技巧 
	//位图数据区尺寸(字节): 
	BufferSize=Bpl*Height; 
} 
 
//从文件中读取位图: 
BOOL CDib::LoadBmp(LPCTSTR fn) 
{ 
	int j; 
	if(fn=="") 
	{ 
		return FALSE; 
	} 
	Free(); 
    arcFileName=fn; 
	//打开bmp文件: 
	ifstream files(fn,ios::binary|ios::nocreate); 
	if(!files.is_open()) 
	{ 
		return FALSE; 
	} 
 
	//读入BITMAPFILEHEADER: 
	files.read((LPSTR)&m_BmpFH, sizeof(BITMAPFILEHEADER)); 
 
	//判断是否是bmp文件: 
	if (m_BmpFH.bfType != BmpMarker) 
	{ 
		return FALSE; 
	} 
 
	//读入BITMAPINFO: 
	DWORD bmpinfosz; 
	bmpinfosz=m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)  
		      +256*sizeof(RGBQUAD);  //40+256*4 
	m_BmpInfo=(LPBITMAPINFO) new BYTE[bmpinfosz]; 
	files.read((char *)m_BmpInfo,m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)); //m_BmpFH.bfOffBits-sizeof(BITMAPFILEHEADER)=40 
 
	//计算位图的相关数据信息: 
	CalBmpData(); 
	//只支持8位以上的位图: 
	if(BPP>32) 
	{ 
		Free(); 
		return FALSE; 
	} 
	//读入位图数据: 
	m_Buffer=new BYTE[BufferSize]; 
	m_Buffer1=new BYTE[BufferSize]; 
	files.read((char *)m_Buffer,BufferSize); 
	if(m_BmpInfo->bmiHeader.biCompression!=BI_RGB) 
	{ 
		Free(); 
		return FALSE; 
	} 
	if(!CreatePalette()) 
	{ 
		Free(); 
		return FALSE; 
	} 
    for ( j=0;j<(int)BufferSize;j++) 
	{ 
	   	*(m_Buffer1+j)=*(m_Buffer+j); 
	} 
	m_BmpLoaded=TRUE; 
	return TRUE; 
} 
 
//将内存中的位图存入文件: 
BOOL CDib::SaveBmp(LPCTSTR fn) 
{ 
	if(fn=="") 
	{ 
		return FALSE; 
	} 
	if(!m_BmpLoaded) 
	{ 
		return FALSE; 
	} 
	if(m_BmpInfo==0||m_Buffer==0) 
	{ 
		return FALSE; 
	} 
 
//1. 更改m_BmpInfo->bmiHeader.biSizeImage: 
	//1. biSizeImage=位图数据的大小: 
	m_BmpInfo->bmiHeader.biSizeImage=BufferSize; 
 
//2. 填充bmpfh结构; 
	BITMAPFILEHEADER bmpfh; 
	memset(&bmpfh,0,sizeof(BITMAPFILEHEADER)); 
	bmpfh.bfType=BmpMarker; 
	//bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+调色板+BufferSize: 
	bmpfh.bfSize=sizeof(BITMAPFILEHEADER)+ 
			       sizeof(BITMAPINFO)+ 
		           (NumberOfColors-1)*sizeof(RGBQUAD)+ 
				   BufferSize; 
 
	bmpfh.bfReserved1=0; 
	bmpfh.bfReserved2=0; 
	bmpfh.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+ 
		              m_BmpInfo->bmiHeader.biSize+ 
					  PaletteSize(); 
//3. 写文件: 
	FILE * fp; 
	size_t sz; 
	if((fp=fopen(fn,"wb"))==NULL) 
	{ 
		return FALSE; 
	} 
	//1). 写入BITMAPFILEHEADER: 
	sz=fwrite((void *)&bmpfh,sizeof(BITMAPFILEHEADER),1,fp); 
	if(sz!=1) 
	{ 
		fclose(fp); 
		return FALSE; 
	} 
	//2). 写入BITMAPINFO: 
	sz=fwrite((void *)m_BmpInfo,sizeof(BITMAPINFO)+(NumberOfColors-1)*sizeof(RGBQUAD),1,fp); 
	if(sz!=1) 
	{ 
		fclose(fp); 
		return FALSE; 
	} 
	//3). 写入位图数据: 
	sz=fwrite(m_Buffer,1,BufferSize,fp); 
	if(sz!=BufferSize) 
	{ 
		fclose(fp); 
		return FALSE; 
	} 
	fclose(fp); 
	return TRUE; 
} 
 
//获取位图内存地址: 
BYTE * CDib::GetBuffer() 
{ 
	return m_Buffer; 
} 
 
//根据像素在位图中的位置求像素在内存中的地址: 
BYTE * CDib::FindPos(DWORD x, DWORD y) 
{ 
	BYTE * pos; 
	if(!m_BmpLoaded) 
	{ 
		return 0; 
	} 
	pos=m_Buffer+Bpl*(Height-1-y)+x*BPP/8; 
	return pos; 
} 
 
//将位图的子画面存入文件: 
BOOL CDib::PickBitmapToFile(LPCTSTR fn, DWORD xt, DWORD yt,  
							DWORD xb, DWORD yb) 
{ 
	BYTE * buf; 
	DWORD w,h,bpl,bufsize,n0; 
	if(!m_BmpLoaded) 
	{ 
		return FALSE; 
	} 
 
	if(m_BmpInfo==0||m_Buffer==0) 
	{ 
		return FALSE; 
	} 
 
	if(fn=="") 
	{ 
		return FALSE; 
	} 
 
//1. 计算基本参数: 
	Sort(xt,xb); 
	Sort(yt,yb); 
	if(xt>Width) 
	{ 
		return FALSE; 
	} 
	if(yt>Width) 
	{ 
		return FALSE; 
	} 
	if(xb>Width) 
	{ 
		xb=Width; 
	} 
	if(yb>Height) 
	{ 
		yb=Height; 
	} 
	w=xb-xt;//子画面宽度; 
	h=yb-yt;//子画面高度; 
	bpl=(w*(BPP/8)+3)&~3;//每一行大小; 
	n0=bpl-w*BPP/8;//需要在每一行末尾添加的0的数目; 
	bufsize=bpl*h;//位图数据区大小; 
 
//2. 填写位图区: 
	BYTE * pos,* bufpos; 
	pos=FindPos(xt,yt);//找到(xt,yt)像素在内存中的位置; 
	buf=new BYTE[bufsize]; 
	memset((void *)buf,0,bufsize); 
	UINT i; 
	bufpos=buf+bpl*(h-1); 
	for(i=0;i<h;i++) 
	{ 
		memcpy(bufpos,pos,w*BPP/8); 
		bufpos-=bpl; 
		pos-=Bpl; 
	} 
 
//3. 填写位图结构: 
	BITMAPFILEHEADER fh; 
	BITMAPINFO       info; 
	memset(&fh  ,0,sizeof(BITMAPFILEHEADER)); 
	memset(&info,0,sizeof(BITMAPINFO)); 
	//1. 填充BITMAPINFO结构: 
	info.bmiHeader.biBitCount=(WORD)BPP; 
	info.bmiHeader.biClrImportant=m_BmpInfo->bmiHeader.biClrImportant; 
	info.bmiHeader.biClrUsed=m_BmpInfo->bmiHeader.biClrUsed; 
	info.bmiHeader.biCompression=BI_RGB; 
	info.bmiHeader.biHeight=h; 
	info.bmiHeader.biPlanes=m_BmpInfo->bmiHeader.biPlanes; 
	info.bmiHeader.biSize=m_BmpInfo->bmiHeader.biSize; 
	info.bmiHeader.biSizeImage=bufsize; 
	info.bmiHeader.biWidth=w; 
	info.bmiHeader.biXPelsPerMeter=m_BmpInfo->bmiHeader.biXPelsPerMeter; 
	info.bmiHeader.biYPelsPerMeter=m_BmpInfo->bmiHeader.biYPelsPerMeter; 
	info.bmiColors[0]=m_BmpInfo->bmiColors[0]; 
	//2. 填充bmpfh结构; 
	fh.bfType=BmpMarker; 
	//bmpfh.bfSize=BITMAPFILEHEADER+BITMAPINFO+调色板+BufferSize: 
	fh.bfSize=sizeof(BITMAPFILEHEADER)+ 
			       sizeof(BITMAPINFO)+ 
		           (NumberOfColors-1)*sizeof(RGBQUAD)+ 
				   bufsize; 
 
	fh.bfReserved1=0; 
	fh.bfReserved2=0; 
	fh.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+ 
		              m_BmpInfo->bmiHeader.biSize+ 
					  PaletteSize(); 
//4. 写文件: 
	FILE * fp; 
	if((fp=fopen(fn,"wb"))==NULL) 
	{ 
		return FALSE; 
	} 
	//1). 写入BITMAPFILEHEADER: 
	fwrite((char *)&fh,sizeof(BITMAPFILEHEADER),1,fp); 
	//2). 写入BITMAPINFOHEADER部分: 
	fwrite((char *)&info.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp); 
	//3). //写入彩色表部分: 
	if(BPP<16) 
	{ 
		fwrite((char *)&m_Quad[0],NumberOfColors*sizeof(RGBQUAD),1,fp); 
	} 
	//4). 写入位图数据: 
	fwrite((char *)buf,bufsize,1,fp); 
	delete buf; 
	fclose(fp); 
	return TRUE; 
}	 
 
void CDib::CalBmpData() 
{ 
	if(m_BmpInfo==0) 
	{ 
		return; 
	} 
//1. 位图宽度(像素): 
	Width=m_BmpInfo->bmiHeader.biWidth; 
//位图高度(像素): 
	Height=m_BmpInfo->bmiHeader.biHeight; 
//位图色彩深度: 
	BPP=m_BmpInfo->bmiHeader.biBitCount; //取值可为1,4,8,16,24,32,如取值16,24,32,则彩色表不是必须的 
//位图每一行占据的字节数: 
	Bpl=(DWORD)WIDTHBYTES(BPP*Width); //一种使bpl为4的整数倍的技巧 
	//位图数据区尺寸(字节): 
	BufferSize=Bpl*Height; 
//为m_Quad分配内存: 
	//如果色彩数目大于8 则返回: 
	if(m_BmpInfo->bmiHeader.biBitCount>=16) 
	{ 
		NumberOfColors=0; 
		return; 
	} 
 
	if(m_BmpInfo->bmiHeader.biClrUsed!=0) 
	{ 
		NumberOfColors=m_BmpInfo->bmiHeader.biClrUsed; 
	} 
	else 
	{ 
		switch(BPP){ 
		case 1: 
			NumberOfColors=2; 
			break; 
		case 4: 
			NumberOfColors=16; 
			break; 
		case 8: 
			NumberOfColors=256; 
			break; 
		default: 
			return; 
		} 
	} 
	//读取 logical palette 
	m_Quad=new RGBQUAD[NumberOfColors]; 
	for(DWORD i=0;i<NumberOfColors;i++) 
	{ 
		m_Quad[i]=m_BmpInfo->bmiColors[i]; 
	} 
} 
 
void CDib::SetBmpMarker(DWORD b, DWORD m) 
{ 
	BmpMarker=(WORD)((m<<8)|b); //'m'左移8位 and 'b' 再强制类型转换 
} 
 
DWORD CDib::PaletteSize() 
{ 
	if (m_BmpInfo==0) 
	{ 
		return 0; 
	} 
	return (DWORD)NumberOfColors*sizeof(RGBQUAD);//256*4 
} 
//using bmp file's QUAD to change phisical palette 
BOOL CDib::CreatePalette() 
{ 
	if (m_BmpInfo==0) 
	{ 
		return FALSE; 
	} 
	//16位以下的位图均需要 logical palette 
	if(BPP>=16) 
	{ 
		return TRUE; 
	} 
 
	DWORD i; 
	// allocate memory block for 逻辑彩色区logical palette 
	LPLOGPALETTE lpPal = (LPLOGPALETTE) new BYTE[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*NumberOfColors]; //sizeof(PALETTEENTRY)*NumberOfColors=4*256 bytes 
	// if not enough memory, clean up and return NULL 
	if (lpPal == 0) 
	{ 
		return FALSE; 
	} 
 
	// set version and number of palette entries 
	lpPal->palVersion = PALVERSION; 
	lpPal->palNumEntries = (WORD)NumberOfColors; 
	for (i=0;i<NumberOfColors;i++) 
	{ 
		lpPal->palPalEntry[i].peRed   = m_Quad[i].rgbRed; 
		lpPal->palPalEntry[i].peGreen = m_Quad[i].rgbGreen; 
		lpPal->palPalEntry[i].peBlue  = m_Quad[i].rgbBlue; 
		lpPal->palPalEntry[i].peFlags = 0; 
	} 
 
	/* according to bmp file palette table,create the palette and  
	get handle to it */ 
	if (m_hPal) 
	{ 
		::DeleteObject((HGDIOBJ)m_hPal); //删除老的逻辑调色对象 
	} 
	m_hPal=::CreatePalette(lpPal); //创建新的逻辑调色对象 
	if(!m_hPal) 
	{ 
		return FALSE; 
	} 
 
	delete [] lpPal; //作用完即destroy logical Palette 
	return TRUE; 
} 
 
BOOL CDib::Draw(HDC hDC, LPRECT rcDest, LPRECT rcSrc) 
{ 
	if (!m_BmpLoaded) 
	{ 
		return FALSE; 
	} 
 
	HPALETTE hOldPal = 0;        // Previous palette 
 
	// Get the DIB's palette, then select it into DC 
	if (m_hPal!=0) 
	{ 
		// Select as background since we have 
		// already realized in forground if needed 
		hOldPal = ::SelectPalette(hDC,m_hPal,TRUE); //selects the specified logical palette into a device context 
	} 
 
	/* Make sure to use the stretching mode best for color pictures */ 
	::SetStretchBltMode(hDC, COLORONCOLOR); 
 
	/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */ 
	BOOL Ok; 
	if ((RECTWIDTH(rcDest)  == RECTWIDTH(rcSrc)) && 
	    (RECTHEIGHT(rcDest) == RECTHEIGHT(rcSrc))) 
	{ 
		Ok = ::SetDIBitsToDevice(hDC,                                 // hDC 
								 rcDest->left,                        // DestX 
								 rcDest->top,                         // DestY 
								 RECTWIDTH(rcDest),                   // nDestWidth 
								 RECTHEIGHT(rcDest),                  // nDestHeight 
								 rcSrc->left,                         // SrcX 
								 Height-rcSrc->top -RECTHEIGHT(rcSrc),// SrcY 
								 0,                                   // nStartScan 
								 (WORD)Height,                        // nNumScans 
								 m_Buffer,                            // lpBits 
								 m_BmpInfo,                           // lpBitsInfo 
								 DIB_RGB_COLORS);                     // wUsage 
	} 
   else 
   { 
	  Ok = ::StretchDIBits(hDC,                            // hDC 
							   rcDest->left,               // DestX 
							   rcDest->top,                // DestY 
							   RECTWIDTH(rcDest),          // nDestWidth 
							   RECTHEIGHT(rcDest),         // nDestHeight 
							   rcSrc->left,                // SrcX 
							   rcSrc->top,                 // SrcY 
							   RECTWIDTH(rcSrc),           // wSrcWidth 
							   RECTHEIGHT(rcSrc),          // wSrcHeight 
							   m_Buffer,                   // lpBits 
							   m_BmpInfo,                   // lpBitsInfo 
							   DIB_RGB_COLORS,             // wUsage 
							   SRCCOPY);                   // dwROP 
   } 
	/* Reselect old palette */ 
	if (hOldPal != 0) 
	{ 
		::SelectPalette(hDC, hOldPal, TRUE); //恢复老的调色板 
	} 
   return Ok; 
} 
 
void CDib::Sort(DWORD &x0, DWORD &x1) 
{ 
	DWORD t; 
	if(x0>x1) 
	{ 
		t=x1; 
		x1=x0; 
		x0=t; 
	} 
} 
 
BITMAPINFOHEADER CDib::GetImageInfo(LPCTSTR fn, DWORD &w, DWORD &h) 
{ 
	BITMAPFILEHEADER bmpfilehdr; 
	BITMAPINFOHEADER bmpinfohdr; 
	w=0; 
	h=0; 
	memset(&bmpfilehdr,0,sizeof(BITMAPFILEHEADER)); //初始化内存并得到内存指针; 
	memset(&bmpinfohdr,0,sizeof(BITMAPINFOHEADER)); 
 
	ifstream file( fn, ios::binary | ios::nocreate ); //打开已存在的且二进制的文件; 
	if (!file.is_open()) 
	{ 
		return bmpinfohdr; 
	} 
 
	file.read( (char*)&bmpfilehdr, sizeof(bmpfilehdr) ); 
 
	if (bmpfilehdr.bfType!=(WORD)BmpMarker) 
	{ 
		return bmpinfohdr; 
	} 
 
	file.read( (char*)&bmpinfohdr, sizeof(bmpinfohdr) ); 
 
	w=bmpinfohdr.biWidth; 
	h=bmpinfohdr.biHeight; 
 
	return bmpinfohdr; 
} 
 
void CDib::restoreimage() 
{ 
	int j; 
    for ( j=0;j<(int)BufferSize;j++) 
	{ 
	   	*(m_Buffer+j)=*(m_Buffer1+j); 
	} 
} 
 
BOOL CDib::GetBlueImg() 
{ 
    if (BPP<=8) 
	   return FALSE; 
	int i,j; 
	for(i=0;i<(int)Height;i++) 
	{ 
		for ( j=0;j<(int)Bpl-2;j=j+3) 
		{ 
	   		*(m_Buffer+i*Bpl+j+1)=0; 
			*(m_Buffer+i*Bpl+j+2)=0; 
		} 
	} 
    return TRUE; 
} 
 
 
BOOL CDib::GetGreenImg() 
{ 
    if (BPP<=8) 
	   return FALSE; 
	int i,j; 
	for(i=0;i<(int)Height;i++) 
	{ 
		for ( j=0;j<(int)Bpl-2;j=j+3) 
		{ 
		   	*(m_Buffer+i*Bpl+j)=0; 
			*(m_Buffer+i*Bpl+j+2)=0; 
		} 
	} 
    return TRUE; 
} 
 
BOOL CDib::GetRedImg() 
{ 
    if (BPP<=8) 
	   return FALSE; 
	int i,j; 
	for(i=0;i<(int)Height;i++) 
	{ 
		for ( j=0;j<(int)Bpl-2;j=j+3) 
		{ 
		   	*(m_Buffer+i*Bpl+j)=0; 
			*(m_Buffer+i*Bpl+j+1)=0; 
		} 
	} 
    return TRUE; 
}