www.pudn.com > 人体步态跟踪识别bate版.rar > DIBAPI.CPP


//  dibapi.cpp 
//  原文件函数如下: 
//  PaintDIB()          - DIB的显示函数 
//  CreateDIBPalette()  - 从一个DIB位图创建调色板 
//  FindDIBBits()       - 计算DIB位图的的位数 
//  DIBWidth()          - 获得DIB位图的宽度 
//  DIBHeight()         - 获得DIB位图的长度 
//  PaletteSize()       - 获取存储DIB调色板的尺寸 
//  DIBNumColors()      - 计算DIB颜色表的颜色数 
//  CopyHandle()        - 对一个内存环境进行拷贝 
// 
#include "stdafx.h" 
#include "dibapi.h" 
#include  
#include  
#include  
#include  
/************************************************************************* 
 * 
 * PaintDIB() 
 * 
 * 参数 
 * HDC hDC          - 设备上下文指针 
 * LPRECT lpDCRect  - 设备中的矩形域 
 * HDIB hDIB        - 指向一个存储DIB位内存环境的指针 
 * LPRECT lpDIBRect - 放置DIB位图矩形域 
 * CPalette* pPal   - 指向一个DIB调色板的指针 
 * 返回值: 
 * 真表示DIB位图已经画出, 否则为假 
 * 注释: 
 *   显示DIB位图。调用StretchDIBits或SetDIBitsToDevice()  
 *   来实现。 
 ************************************************************************/ 
BOOL  PaintDIB(HDC   hDC, 
			   LPRECT  lpDCRect, 
			   HDIB    hDIB, 
			   LPRECT  lpDIBRect, 
			   CPalette* pPal) 
{ 
	LPSTR    lpDIBHdr;            // 指向BITMAPINFOHEADER的指针 
	LPSTR    lpDIBBits;           // 指向一个DIB位 
	BOOL     bSuccess=FALSE;      // 成功与失败的标记 
	HPALETTE hPal=NULL;           // DIB调色板 
	HPALETTE hOldPal=NULL;        // 旧的调色板 
 
	//检查DIB句柄是否有效 
	if (hDIB == NULL) 
		return FALSE; 
 
	//锁住DIB,取得一个起始指针 
	lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	lpDIBBits = ::FindDIBBits(lpDIBHdr); 
 
	//取得DIB的调色板,并将其选进设备 
	if (pPal != NULL) 
	{ 
		hPal = (HPALETTE) pPal->m_hObject; 
 
		//选取背景  
		hOldPal = ::SelectPalette(hDC, hPal, TRUE); 
	} 
 
	//确定使用模式 
	::SetStretchBltMode(hDC, COLORONCOLOR); 
 
	//决定调用StretchDIBits()或SetDIBitsToDevice()函数 
	if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) && 
	   (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect))) 
		bSuccess = ::SetDIBitsToDevice(hDC,			 // 显示设备上下文句柄 
				   lpDCRect->left,           // 目的区左上x坐标 
				   lpDCRect->top,            // 目的区左上y坐标 
				   RECTWIDTH(lpDCRect),      // 原矩形宽度 
				   RECTHEIGHT(lpDCRect),     // 原矩形高度 
				   lpDIBRect->left,          // 原矩形左下角x坐标 
				   (int)DIBHeight(lpDIBHdr) - 
					  lpDIBRect->top - 
					  RECTHEIGHT(lpDIBRect), // 原矩形左下角y坐标 
				   0,                        // 第一扫描线位置 
				   (WORD)DIBHeight(lpDIBHdr),// 扫描线数 
				   lpDIBBits,                // DIB像素数据指针 
				   (LPBITMAPINFO)lpDIBHdr,   // BITMAPINFO结构指针 
				   DIB_RGB_COLORS);          // 使用颜色的方式 
   else 
	  bSuccess = ::StretchDIBits(hDC,        // 显示设备上下文句柄 
				   lpDCRect->left,           // 目的区左上x坐标 
				   lpDCRect->top,            // 目的区左上y坐标 
				   RECTWIDTH(lpDCRect),      // 目的矩形宽度 
				   RECTHEIGHT(lpDCRect),     // 目的矩形高度 
				   lpDIBRect->left,          // 原矩形左下角x坐标 
				   lpDIBRect->top,           // 原矩形左下角y坐标 
				   RECTWIDTH(lpDIBRect),     // 原矩形宽度 
				   RECTHEIGHT(lpDIBRect),    // 原矩形高度 
				   lpDIBBits,                // DIB像素数据指针 
				   (LPBITMAPINFO)lpDIBHdr,   // BITMAPINFO结构指针 
				   DIB_RGB_COLORS,           // 使用颜色的方式 
				   SRCCOPY);                 //光栅操作码 
  ::GlobalUnlock((HGLOBAL) hDIB); 
 
	//重选旧的调色板  
	if (hOldPal != NULL) 
	{ 
		::SelectPalette(hDC, hOldPal, TRUE); 
	} 
 
   return bSuccess; 
} 
/************************************************************************* 
 * 
 * CreateDIBPalette() 
 * Parameter: 
 * HDIB hDIB        - DIB位图 
 * HPALETTE         -调色板 
 * 注释: 
 * 这个函数首先创建调色板,从颜色表中读取并存储颜色数; 
 *然后创建调色板,并返回调色板的句柄。 
 ************************************************************************/ 
BOOL  CreateDIBPalette(HDIB hDIB, CPalette* pPal) 
{ 
	LPLOGPALETTE lpPal;      // 指向逻辑调色板的指针 
	HANDLE hLogPal;          // 逻辑调色板句柄 
	HPALETTE hPal = NULL;    // 调色板句柄 
	int i;                   // 索引 
	WORD wNumColors;         // 颜色表中的颜色数 
	LPSTR lpbi;              // 指向一个DIB的指针 
	LPBITMAPINFO lpbmi;      // 指向BITMAPINFO结构的指针 
	LPBITMAPCOREINFO lpbmc;  // 指向BITMAPCOREINFO结构的指针 
	BOOL bWinStyleDIB;       // 区分是否为Win3.0 DIB的一个标记  
	BOOL bResult = FALSE; 
 
	//如果DIB句柄无效, 返回FALSE 
 
	if (hDIB == NULL) 
	  return FALSE; 
 
   lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
 
   //得到BITMAPINFO (Win 3.0)指针  
   lpbmi = (LPBITMAPINFO)lpbi; 
 
   //得到BITMAPCOREINFO (old 1.x)指针  
   lpbmc = (LPBITMAPCOREINFO)lpbi; 
 
   //得到DIB的颜色数 
   wNumColors = ::DIBNumColors(lpbi); 
 
   if (wNumColors != 0) 
   { 
		//为逻辑调色板分配内存 
		hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) 
									+ sizeof(PALETTEENTRY) 
									* wNumColors); 
 
		//如果没有足够得空间清除并返回 NULL 
		if (hLogPal == 0) 
		{ 
			::GlobalUnlock((HGLOBAL) hDIB); 
			return FALSE; 
		} 
 
		lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal); 
 
		//设置版本号和调色板口数目  
		lpPal->palVersion = PALVERSION; 
		lpPal->palNumEntries = (WORD)wNumColors; 
 
		//是否为Win 3.0 DIB? 
		bWinStyleDIB = IS_WIN30_DIB(lpbi); 
		for (i = 0; i < (int)wNumColors; i++) 
		{ 
			if (bWinStyleDIB) 
			{ 
				lpPal->palPalEntry[i].peRed =  
					lpbmi->bmiColors[i].rgbRed; 
				lpPal->palPalEntry[i].peGreen =  
					lpbmi->bmiColors[i].rgbGreen; 
				lpPal->palPalEntry[i].peBlue =  
					lpbmi->bmiColors[i].rgbBlue; 
				lpPal->palPalEntry[i].peFlags = 0; 
			} 
			else 
			{ 
				lpPal->palPalEntry[i].peRed =  
					lpbmc->bmciColors[i].rgbtRed; 
				lpPal->palPalEntry[i].peGreen =  
					lpbmc->bmciColors[i].rgbtGreen; 
				lpPal->palPalEntry[i].peBlue =  
					lpbmc->bmciColors[i].rgbtBlue; 
				lpPal->palPalEntry[i].peFlags = 0; 
			} 
		} 
 
		//创建调色板并得到句柄  
		bResult = pPal->CreatePalette(lpPal); 
		::GlobalUnlock((HGLOBAL) hLogPal); 
		::GlobalFree((HGLOBAL) hLogPal); 
	} 
 
	::GlobalUnlock((HGLOBAL) hDIB); 
 
	return bResult; 
} 
 
/************************************************************************* 
 * 
 * FindDIBBits() 
 * 参数: 
 * LPSTR lpbi       - 指向DIB内存的指针 
 * 返回值: 
 * LPSTR            - 指向DIB的位数 
 ************************************************************************/ 
 
 
LPSTR  FindDIBBits(LPSTR lpbi) 
{ 
	//test: 
	WORD lpbi_tmp = *(LPDWORD)lpbi; 
	WORD lpbi_tmp_2 = ::PaletteSize(lpbi); 
	return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi)); 
} 
 
 
/************************************************************************* 
 * 
 * DIBWidth() 
 * 参数: 
 * LPSTR lpbi       - 指向DIB内存的指针 
 *返回值: 
 * DWORD            - DIB的宽度 
 * 注释: 
 * 这个函数取得DIB的宽度 
 ************************************************************************/ 
 
DWORD  DIBWidth(LPSTR lpDIB) 
{ 
	LPBITMAPINFOHEADER lpbmi;  // 指向Win 3.0 DIB 
	LPBITMAPCOREHEADER lpbmc;  // 指向其它格式 DIB 
 
	//指向头 
 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	// 如果为Win 3.0 DIB,则返回其宽度  
	if (IS_WIN30_DIB(lpDIB)) 
		return lpbmi->biWidth; 
	else  // 如果为其它格式的DIB, 也返回其宽度  
		return (DWORD)lpbmc->bcWidth; 
} 
 
 
/************************************************************************* 
 * 
 * DIBHeight() 
 * 参数: 
 * LPSTR lpbi       - 指向DIB内存的指针 
 * 返回值: 
 * DWORD            - DIB的高度 
 * 注释: 
 * 这个函数取得DIB的高度 
 ************************************************************************/ 
 
 
DWORD  DIBHeight(LPSTR lpDIB) 
{ 
	LPBITMAPINFOHEADER lpbmi;  // 指向Win 3.0格式的DIB 
	LPBITMAPCOREHEADER lpbmc;  // 指向其它格式的DIB 
 
	//指向头 
 
	lpbmi = (LPBITMAPINFOHEADER)lpDIB; 
	lpbmc = (LPBITMAPCOREHEADER)lpDIB; 
 
	// 如果为Win 3.0 DIB,则返回其高度 
	if (IS_WIN30_DIB(lpDIB)) 
		return lpbmi->biHeight; 
	else // i如果为其它格式DIB, 也返回其高度  
		return (DWORD)lpbmc->bcHeight; 
} 
 
 
/************************************************************************* 
 * 
 * PaletteSize() 
 * 参数: 
 * LPSTR lpbi       - 指向DIB内存的指针 
 * 返回值: 
 * WORD             - 颜色调色板的尺寸 
 * 注释: 
 * 这个函数得到存储调色板的尺寸 
 ************************************************************************/ 
 
 
WORD  PaletteSize(LPSTR lpbi) 
{ 
   //计算必须的尺寸 
   if (IS_WIN30_DIB (lpbi)) 
	  return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD)); 
   else 
	  return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE)); 
} 
 
 
/************************************************************************* 
 * 
 * DIBNumColors() 
 * 参数: 
 * LPSTR lpbi       - 指向DIB内存的指针 
 * 返回值: 
 * WORD             - 颜色表中的颜色数 
  
 ************************************************************************/ 
 
 
WORD  DIBNumColors(LPSTR lpbi) 
{ 
	WORD wBitCount;  // DIB bit count 
 
	//如果为Windows格式的DIB,颜色数少于像素位数. 
	 //  如果是这种情况,返回合适的值 。 
	  
	if (IS_WIN30_DIB(lpbi)) 
	{ 
		DWORD dwClrUsed; 
 
		dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; 
		if (dwClrUsed != 0) 
			return (WORD)dwClrUsed; 
	} 
 
	// 计算基于像素的颜色数  
	if (IS_WIN30_DIB(lpbi)) 
		wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; 
	else 
		wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; 
 
	// 返回基于像素的颜色数 
	switch(wBitCount) { 
	case 1: 
		return 2; 
	case 4: 
		return 16; 
	case 8: 
		return 256; 
	default: 
		return 0; 
	} 
} 
 
 
/************************************************************************* 
 * 
 * CopyHandle () 
 * 参数: 
 * h       -内存句柄 
 * 返回值: 
 * HGLOBAL  -内存句柄 
  
 ************************************************************************/ 
 
HGLOBAL  CopyHandle (HGLOBAL h) 
{ 
	if (h == NULL) 
		return NULL; 
 
	DWORD dwLen = ::GlobalSize((HGLOBAL) h); 
	HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); 
 
	if (hCopy != NULL) 
	{ 
		void* lpCopy = ::GlobalLock((HGLOBAL) hCopy); 
		void* lp     = ::GlobalLock((HGLOBAL) h); 
		memcpy(lpCopy, lp, dwLen); 
		::GlobalUnlock(hCopy); 
		::GlobalUnlock(h); 
	} 
 
	return hCopy; 
} 
 
/************************************************************************* 
 * SaveDIB() 
 * 参数: 
 * HDIB hDib - 保存的DIB句柄 
 * CFile& file - 打开用来保存DIB的文件 
 * Return value: 成功为真,失败为假 
 * 注释 
 * 将DIB保存到指定的文件中。 
 *************************************************************************/ 
 
 
BOOL  SaveDIB(HDIB hDib, CFile& file) 
{ 
	BITMAPFILEHEADER bmfHdr; // 文件头 
	LPBITMAPINFOHEADER lpBI;   // 指向DIB信息结构的指针 
	DWORD dwDIBSize; 
 
	if (hDib == NULL) 
		return FALSE; 
 
	//得到指向DIB内存的指针, 包括一个BITMAPINFO结构 
	 
	lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); 
	if (lpBI == NULL) 
		return FALSE; 
 
	if (!IS_WIN30_DIB(lpBI)) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		return FALSE;       // 其它格式的DIB不支持  
	} 
 
	// 填写文件头区域 
	  
	// 填写文件类型  
	bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM" 
 
	// 计算DIB的大小。最简单的方法是调用GlobalSize()函数 
	// 一般手工计算。 
	// 先计算头和颜色表之和 
	dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  
 
	// 计算图像大小 
 
	if ((lpBI->biCompression == BI_RLE8) 
		|| (lpBI->biCompression == BI_RLE4)) 
	{ 
		// 为RLE位图, 不能计算尺寸。  
 
		dwDIBSize += lpBI->biSizeImage; 
	} 
	else 
	{ 
		DWORD dwBmBitsSize;  // 位图位的大小 
		// 非RLE, 大小为 宽度*高度 
 
		dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)* 
			((DWORD)lpBI->biBitCount)) * lpBI->biHeight; 
 
		dwDIBSize += dwBmBitsSize; 
 
		lpBI->biSizeImage = dwBmBitsSize; 
	} 
 
 
	// 计算文件大小 
 
	bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); 
	bmfHdr.bfReserved1 = 0; 
	bmfHdr.bfReserved2 = 0; 
 
	// 计算真实的位图位的偏移量,其等于文件头+DIB头+颜色表尺寸 
	  
	bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + 
		lpBI->biSize + PaletteSize((LPSTR)lpBI); 
	TRY 
	{ 
		// 写文件头 
		file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); 
	 
		// 写DIB头内容和大小 
	 
		file.WriteHuge(lpBI, dwDIBSize); 
	} 
	CATCH (CFileException, e) 
	{ 
		::GlobalUnlock((HGLOBAL) hDib); 
		THROW_LAST(); 
	} 
	END_CATCH 
 
	::GlobalUnlock((HGLOBAL) hDib); 
	return TRUE; 
} 
 
/************************************************************************* 
 * ReadDIBFile () 
 * 将DIB文件读到内存 
 * 返回一个指向DIB的句柄  
*************************************************************************/ 
 
HDIB  ReadDIBFile(CFile& file) 
{ 
	BITMAPFILEHEADER bmfHeader; 
	DWORD dwBitsSize; 
	HDIB hDIB; 
	LPSTR pDIB; 
 
	// 取得DIB的长度 
	  
	dwBitsSize = file.GetLength(); 
 
	// 读DIB文件头,检查是否有效。 
	 
	if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) 
		return NULL; 
 
	if (bmfHeader.bfType != DIB_HEADER_MARKER) 
		return NULL; 
 
	//为DIB分配内存 
	 
	hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); 
	if (hDIB == 0) 
	{ 
		return NULL; 
	} 
	 
	// 读位数 
	pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != 
		dwBitsSize - sizeof(BITMAPFILEHEADER) ) 
	{ 
		::GlobalUnlock((HGLOBAL) hDIB); 
		::GlobalFree((HGLOBAL) hDIB); 
		return NULL; 
	} 
	BITMAPINFOHEADER bmiHeader; 
	memcpy(&bmiHeader,pDIB,sizeof(BITMAPINFOHEADER)); 
	::GlobalUnlock((HGLOBAL) hDIB); 
	return hDIB; 
} 
 
//求模函数,最主要的是它可以求出两个double型的模数 
double DoubleModule(double num1,double num2) 
{ 
	double dtmp; 
	dtmp=num1/num2; 
	int ntmp; 
	ntmp=floor(dtmp); 
	double remainder; 
	remainder=num1-ntmp*num2; 
	return remainder; 
} 
//寻找二值图像中人体运动窗口 
void FindHumanWindows(HDIB hDIB,CPoint p1,CPoint p2) 
{ 
	LPSTR    lpDIBHdr;            // 指向BITMAPINFOHEADER的指针 
	LPSTR    lpDIBBits;           // 指向一个DIB位 
	int ImageWidth,ImageHeight;     
	unsigned char* p=new unsigned char; 
	//锁住DIB,取得一个起始指针 
	lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); 
	lpDIBBits = ::FindDIBBits(lpDIBHdr); 
	ImageHeight=(int)DIBHeight(lpDIBHdr); 
	ImageWidth=(int)DIBWidth(lpDIBHdr); 
	int start=ImageWidth; 
	int end=0; 
	int top=ImageHeight; 
	int botton=0; 
	//找到了左右边界线 
    for(int i=0;ij){start=j;break;} 
			} 
		} 
		 
        for(j=ImageWidth-1;j>0;j--) 
		{ 
			if (*(lpDIBBits+i*ImageWidth+j)==255) { 
				if (endj){start=j;break;} 
			} 
		} 
        for(j=ImageWidth-1;j>0;j--) 
		{ 
			if (*(lpDIBBits+j*ImageWidth+i)==255) { 
				if (botton