?? dib.cpp
字號:
// DIB.cpp: implementation of the DIB class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DIB.h"
#include"math.h"
#define WIDTHBYTES(bits) ((bits+31)/32*4)
#define RECTWIDTH(x) (x->right-x->left)
#define RECTHEIGHT(x) (x->bottom-x->top)
#define THRESHOLDCONTRAST 40
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define PI 3.1415926
extern int locax,locay;
#define m_WIDTH 600
#define m_HEIGHT 600
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////////////////////
HDIB DIB::ReadDIBFile(HANDLE hFile)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HANDLE hDIB;
HANDLE hDIBtmp;
LPBITMAPINFOHEADER lpbi;
DWORD dwRead;
//得到文件大小
dwBitsSize = GetFileSize(hFile,NULL);
hDIB = GlobalAlloc(GMEM_MOVEABLE,(DWORD)(sizeof(BITMAPINFOHEADER)));
if(!hDIB)
return NULL;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
if(!lpbi)
{
GlobalFree(hDIB);
return NULL;
}
if(!ReadFile(hFile,(LPBYTE)&bmfHeader,sizeof(BITMAPFILEHEADER),&dwRead,NULL))
goto ErrExit;
if(sizeof(BITMAPFILEHEADER)!=dwRead)//讀取文件出錯
goto ErrExit;
if(bmfHeader.bfType != 0x4d42)//文件類型不匹配
goto ErrExit;
if(!ReadFile(hFile,(LPBYTE)lpbi,sizeof(BITMAPINFOHEADER),&dwRead,NULL))
goto ErrExit;
if(sizeof(BITMAPINFOHEADER)!= dwRead)//讀取數據出錯
goto ErrExit;
GlobalUnlock(hDIB);
if(lpbi->biSizeImage==0)
lpbi->biSizeImage = (this->BytePerLine(hDIB))*lpbi->biHeight;
hDIBtmp = GlobalReAlloc(hDIB,lpbi->biSize+lpbi->biSizeImage,0);
if(!hDIBtmp)
goto ErrExitNoUnlock;
else
hDIB = hDIBtmp;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
//根據情況設定文件指針
if(bmfHeader.bfOffBits != 0L)
SetFilePointer(hFile,bmfHeader.bfOffBits,NULL,FILE_BEGIN);
//讀取文件的象素顏色數據
if(ReadFile(hFile,(LPBYTE)lpbi+lpbi->biSize,lpbi->biSizeImage,&dwRead,NULL))
goto OKExit;
ErrExit:
GlobalUnlock(hDIB);
ErrExitNoUnlock:
GlobalFree(hDIB); //釋放內存
return NULL;
OKExit:
GlobalUnlock(hDIB);
return hDIB;
}
HDIB DIB::LoadDIB(LPCTSTR lpFileName)
{
HANDLE hDIB;
HANDLE hFile;
//創建文件句柄
if((hFile = CreateFile(lpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,NULL))!= INVALID_HANDLE_VALUE)
{
//讀取數據
hDIB = ReadDIBFile(hFile);
//關閉文件句柄
CloseHandle(hFile);
return hDIB;
}
return NULL;
}
BOOL DIB::PaintDIBTrue(HDC hDC,LPRECT lpDCRect,HANDLE hDIB,LPRECT lpDIBRect ,DWORD dwRop)
{
LPBYTE lpDIBHdr;
LPBYTE lpDIBBits;
BOOL bSuccess = FALSE;
if(!hDIB)
return FALSE;
lpDIBHdr = (LPBYTE)GlobalLock(hDIB);
lpDIBBits = lpDIBHdr + sizeof(BITMAPINFOHEADER);
bSuccess = StretchDIBits(hDC,lpDCRect->left,
lpDCRect->top,
RECTWIDTH(lpDCRect),
RECTHEIGHT(lpDCRect),
lpDIBRect->left,
((LPBITMAPINFOHEADER)lpDIBHdr)->biHeight-lpDIBRect->top-RECTHEIGHT(lpDIBRect),
RECTWIDTH(lpDIBRect),
RECTHEIGHT(lpDIBRect),
lpDIBBits,
(LPBITMAPINFO)lpDIBHdr,
DIB_RGB_COLORS,
SRCCOPY);
GlobalUnlock(hDIB);
return bSuccess;
}
WORD DIB::BytePerLine(HANDLE hDIB)
{
WORD i;
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
i = WIDTHBYTES((lpbi->biWidth)*24);
GlobalUnlock(hDIB);
return i;
}
//函數實現圖片從彩色到黑白的轉換
HDIB DIB::ToGray(HANDLE hDIB)
{
HDIB hNewDIB = NULL;
LPBITMAPINFOHEADER lpSrc,lpDest;
LPBYTE lpS,lpD;
DWORD dwBytesPerLine;
DWORD dwImgSize;
WORD wBytesPerLine;
unsigned i ,j,height,width;
if(!hDIB)
return NULL;
lpSrc = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
dwBytesPerLine = WIDTHBYTES(24*(lpSrc->biWidth));
dwImgSize = lpSrc->biHeight * dwBytesPerLine;
//申請新的內存,大小等于原來圖象的大小
hNewDIB = GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)+dwImgSize);
lpDest = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
//保存圖片的長寬、顏色深度等信息
memcpy((void*)lpDest,(void*)lpSrc,sizeof(BITMAPINFOHEADER));
DWORD dwSBytesPerLine;
dwSBytesPerLine = (24*(lpSrc->biWidth)+31)/32*4;
height = lpDest->biHeight;
width = lpDest->biWidth;
lpS = (LPBYTE)lpSrc;
wBytesPerLine = this->BytePerLine(hDIB);
lpD = (LPBYTE)lpDest;
lpS = lpS + sizeof(BITMAPINFOHEADER);
lpD = lpD + sizeof(BITMAPINFOHEADER);
unsigned r , g ,b,gray ;
//掃描整個圖片,實現灰度化
for(i = 0 ;i<height; i++)
{
for(j = 0 ;j<(unsigned )lpDest->biWidth;j++)
{
//獲得原來圖片的顏色值
r = *(lpS++);
g = *(lpS++);
b = *(lpS++);
//計算灰度值
gray = (g*50+r*39+b*11)/100;
//保存灰度值到目標圖片
*(lpD++)=gray;
*(lpD++) = gray;
*(lpD++) = gray;
}
//處理四字節對齊問題
unsigned k ;
for(k=0;k<dwSBytesPerLine-lpSrc->biWidth*3;k++)
{
lpS++;
lpD++;
}
}
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
return hNewDIB;
}
LPBYTE DIB::FindDIBBits(HANDLE hDIB)
{
LPBYTE lpDIB,lpDIBtmp;
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
lpDIBtmp = (LPBYTE)lpbi;
lpDIB = lpDIBtmp + sizeof(BITMAPINFOHEADER);
GlobalUnlock(hDIB);
return lpDIB;
}
long DIB::PixelOffset(int i,int j,WORD wBytePerLine)
{
long Offset;
Offset = i*wBytePerLine + j*3;
return Offset;
}
int DIB::BOUND(int a ,int b ,int rgb)
{
if(rgb<0)
return BOUND(a,b,abs(rgb));
if(rgb>b)
return b;
return rgb;
}
//實現圖片的黑白二值化
void DIB::WhiteBlack(HANDLE hDIB,unsigned n)
{
LPBITMAPINFOHEADER lpbi;
LPBYTE lpS;
int width,height;
long lOffset;
WORD wBytesPerLine;
if(!hDIB)
return ;
wBytesPerLine = this->BytePerLine(hDIB);
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
//得到圖片的長寬信息
width = lpbi->biWidth;
height = lpbi->biHeight;
lpS = (LPBYTE)lpbi;
//lps指向數據區
lpS = lpS + sizeof(BITMAPINFOHEADER);
//掃描整個圖片,實現二值化
for(int i = 0;i<height;i++)
for(int j = 0 ;j<width;j++)
{ //得到象素數據在數據區中的偏移
lOffset = this->PixelOffset(i,j,wBytesPerLine);
if(*(lpS+lOffset)<n)//象素值小于臨界值
{ //把象素填充為黑色
*(lpS+lOffset++) = 0;
*(lpS+lOffset++) = 0;
*(lpS+lOffset) = 0;
}
else //象素值大于臨界值
{
//把象素填充為白色
*(lpS+lOffset++) = 255;
*(lpS+lOffset++) = 255;
*(lpS+lOffset) = 255;
}
}
GlobalUnlock(hDIB);
}
DIB::DIB()
{
for(int i=0;i<ImgRange; i++)
for (int j=0; j<ImgRange; j++)
this->lab[i][j] = false;
}
DIB::~DIB()
{
}
BOOL DIB:: SaveDIB(HANDLE hDib, CFile& file)
{
// Bitmap文件頭
BITMAPFILEHEADER bmfHdr;
// 指向BITMAPINFOHEADER的指針
LPBITMAPINFOHEADER lpBI;
// DIB大小
DWORD dwDIBSize =0;
if (hDib == NULL)
{
// 如果DIB為空,返回FALSE
return FALSE;
}
// 讀取BITMAPINFO結構,并鎖定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
{
// 為空,返回FALSE
return FALSE;
}
// 判斷是否是WIN3.0 DIB
// if (!IS_WIN30_DIB(lpBI))
// {
// 不支持其它類型的DIB保存
// 解除鎖定
// ::GlobalUnlock((HGLOBAL) hDib);
// 返回FALSE
// return FALSE;
// }
// 填充文件頭
// 文件類型"BM"
bmfHdr.bfType = 0x4d42; //DIB_HEADER_MARKER;
// 計算DIB大小時,最簡單的方法是調用GlobalSize()函數。但是全局內存大小并
// 不是DIB真正的大小,它總是多幾個字節。這樣就需要計算一下DIB的真實大小。
// 文件頭大小+顏色表大小
// (BITMAPINFOHEADER和BITMAPCOREHEADER結構的第一個DWORD都是該結構的大小)
// dwDIBSize = *(LPDWORD)lpBI; //+ ::PaletteSize((LPSTR)lpBI);
dwDIBSize = sizeof(BITMAPINFOHEADER);//+lpBI->biSizeImage;
// 計算圖像大小
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// 對于RLE位圖,沒法計算大小,只能信任biSizeImage內的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
// 象素的大小
DWORD dwBmBitsSize;
// 大小為Width * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*24) * lpBI->biHeight;
// 計算出DIB真正的大小
dwDIBSize += dwBmBitsSize;
// 更新biSizeImage(很多BMP文件頭中biSizeImage的值是錯誤的)
lpBI->biSizeImage = dwBmBitsSize;
}
// 計算文件大小:DIB大小+BITMAPFILEHEADER結構大小
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
// 兩個保留字
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
// 計算偏移量bfOffBits,它的大小為Bitmap文件頭大小+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);
// 返回TRUE
return TRUE;
}
HANDLE DIB::CopyHandle( HANDLE hSrc)
{
HANDLE hDst;
LPBITMAPINFOHEADER lpbi;
int width,height;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hSrc);
width = lpbi->biWidth;
height = lpbi->biHeight;
hDst = GlobalAlloc(GMEM_MOVEABLE,lpbi->biSize+lpbi->biSizeImage);
if(!hDst)
return NULL;
LPBYTE lpDest;
lpDest = (LPBYTE)GlobalLock(hDst);
memcpy(lpDest,(LPBYTE)lpbi,lpbi->biSize+lpbi->biSizeImage);
GlobalUnlock(hSrc);
GlobalUnlock(hDst);
return hDst;
}
//函數尋找圖片中的特征區域的中心點
#define THRESHOLD (RADIUS*2+1)*(RADIUS*2+1)*15
//函數在一幅圖片中尋找匹配的中心點
BOOL DIB::MatchImportantPoint(HANDLE hDIB,int CharaterInfo[RADIUS*2+1][RADIUS*2+1][3],CPoint *ImPoint)
{
LPBITMAPINFOHEADER lpbi;
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
int width = lpbi->biWidth;
int height = lpbi->biHeight;
LPBYTE lpData = this->FindDIBBits(hDIB);
WORD wBytesPerLine = this->BytePerLine(hDIB);
long lOffset;
long sum =100000,tempsum;
//掃描整個圖片(邊緣點)除外
for(int i=RADIUS ;i<height-RADIUS;i++)
for(int j=RADIUS;j<width-RADIUS;j++)
{
tempsum =0;
//掃描以RADIUS*2+1為邊長的正方形區域
for(int k=-RADIUS;k<=RADIUS;k++)
for(int kk=-RADIUS;kk<=RADIUS;kk++)
{
//計算當前正方形和已知特征區域的顏色差值
lOffset = this->PixelOffset(i+k,j+kk,wBytesPerLine);
int colorblue = abs(*(lpData+lOffset++)-CharaterInfo[k+RADIUS][kk+RADIUS][0]);
int colorgreen = abs(*(lpData+lOffset++)-CharaterInfo[k+RADIUS][kk+RADIUS][1]);
int colorred = abs(*(lpData+lOffset++)-CharaterInfo[k+RADIUS][kk+RADIUS][2]);
tempsum +=colorgreen+colorblue+colorred;
}
if(tempsum<sum)
{ //更新差值
sum = tempsum;
//更改特征坐標點
ImPoint->x = j;
ImPoint->y = i;
}
}
if(sum <THRESHOLD){//找到滿足條件的區域
//下面的代碼把找到的區域的邊框設置成為白色
for(i =-RADIUS;i<=RADIUS;i++)
{
lOffset = this->PixelOffset(ImPoint->y-RADIUS,ImPoint->x+i,wBytesPerLine);
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
}
for(i =-RADIUS;i<=RADIUS;i++)
{
lOffset = this->PixelOffset(ImPoint->y+RADIUS,ImPoint->x+i,wBytesPerLine);
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
}
for(i =-RADIUS;i<=RADIUS;i++)
{
lOffset = this->PixelOffset(ImPoint->y+i,ImPoint->x+RADIUS,wBytesPerLine);
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
}
for(i =-RADIUS;i<=RADIUS;i++)
{
lOffset = this->PixelOffset(ImPoint->y+i,ImPoint->x-RADIUS,wBytesPerLine);
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
*(lpData+lOffset++) = 255;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -