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;i j){start=j;break;} } } for(j=ImageWidth-1;j>0;j--) { if (*(lpDIBBits+i*ImageWidth+j)==255) { if (end j){start=j;break;} } } for(j=ImageWidth-1;j>0;j--) { if (*(lpDIBBits+j*ImageWidth+i)==255) { if (botton