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

📄 hdib.cpp

📁 车牌识别及定位
💻 CPP
字号:
// 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;
}

⌨️ 快捷键说明

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