📄 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::MedianFilterDIB(HANDLE hDIB)
{
HDIB hNewDIB;
LPBYTE lpS,lpD;
LPBITMAPINFOHEADER lpbi;
int r,g,b;
DWORD width,height;
WORD wBytesPerLine;
long lOffset;
if(!hDIB)
return;
SetCursor(LoadCursor(NULL,IDC_WAIT));
wBytesPerLine = this->BytePerLine(hDIB);
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
width = lpbi->biWidth;
height = lpbi->biHeight;
//申请一块新的内存
hNewDIB = GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)+lpbi->biSizeImage);
lpD = (LPBYTE)GlobalLock(hNewDIB);
lpS = (LPBYTE)lpbi;
memcpy(lpD,lpS,sizeof(BITMAPINFOHEADER));
lpS = lpS+sizeof(BITMAPINFOHEADER);
lpD = lpD+sizeof(BITMAPINFOHEADER);
//扫描整个图片
for(WORD i=1;i<height-1;i++)
for(WORD j=1;j<width-1;j++)
{ //中值滤波
this->DoMedianFilterDIB(&r,&g,&b,i,j,wBytesPerLine,lpS);
lOffset = this->PixelOffset(i,j,wBytesPerLine);
*(lpD+lOffset++) = r;
*(lpD+lOffset++) = g;
*(lpD+lOffset) = b;
}
//把信息拷贝回原来的句柄
for( i = 1;i<height-1;i++)
for(WORD j = 1;j<width-1;j++)
{
lOffset = this->PixelOffset(i,j,wBytesPerLine);
//活得新图片的颜色
int color1 = *(lpD+lOffset++);
int color2 = *(lpD+lOffset++);
int color3 = *(lpD+lOffset++);
//拷贝到原来图片中
*(lpS+lOffset++) = color1;
*(lpS+lOffset++) = color2;
*(lpS+lOffset++) = color3;
}
SetCursor(LoadCursor(NULL,IDC_ARROW));
GlobalUnlock(hDIB);
GlobalUnlock(hNewDIB);
GlobalFree(hNewDIB);
}
void DIB::DoMedianFilterDIB(int *r,int *g,int*b,WORD i,WORD j,WORD wBytesPerLine,LPBYTE lpDIBBits)
{
long lOffset;
int rgb[9][3];
//把八个方位和当前位置得rgb值保存到数组rgb[9][3]中
lOffset = this->PixelOffset( i-1, j-1, wBytesPerLine);
rgb[0][0] = *(lpDIBBits+lOffset++);
rgb[0][1] = *(lpDIBBits+lOffset++);
rgb[0][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i-1, j, wBytesPerLine);
rgb[1][0] = *(lpDIBBits+lOffset++);
rgb[1][1] = *(lpDIBBits+lOffset++);
rgb[1][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i-1, j+1, wBytesPerLine);
rgb[2][0] = *(lpDIBBits+lOffset++);
rgb[2][1] = *(lpDIBBits+lOffset++);
rgb[2][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i, j-1, wBytesPerLine);
rgb[3][0] = *(lpDIBBits+lOffset++);
rgb[3][1] = *(lpDIBBits+lOffset++);
rgb[3][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i, j, wBytesPerLine);
rgb[4][0] = *(lpDIBBits+lOffset++);
rgb[4][1] = *(lpDIBBits+lOffset++);
rgb[4][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i, j+1, wBytesPerLine);
rgb[5][0] = *(lpDIBBits+lOffset++);
rgb[5][1] = *(lpDIBBits+lOffset++);
rgb[5][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i+1, j-1, wBytesPerLine);
rgb[6][0] = *(lpDIBBits+lOffset++);
rgb[6][1] = *(lpDIBBits+lOffset++);
rgb[6][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i+1, j, wBytesPerLine);
rgb[7][0] = *(lpDIBBits+lOffset++);
rgb[7][1] = *(lpDIBBits+lOffset++);
rgb[7][2] = *(lpDIBBits+lOffset++);
lOffset = this->PixelOffset( i+1, j+1, wBytesPerLine);
rgb[8][0] = *(lpDIBBits+lOffset++);
rgb[8][1] = *(lpDIBBits+lOffset++);
rgb[8][2] = *(lpDIBBits+lOffset++);
this->MedianSearch( rgb,9,b,g,r);
}
int DIB::MedianSearch(int a[9][3],int n,int *r,int *g,int *b)
{
int result,i,j,temp;
//冒泡法排序,找出rgb中间值
for(i=0;i<9;i++)
for(j = 0 ;j<n-i-1;j++)
{
if(a[j][0]>a[j+1][0])
{
temp = a[j][0];
a[j][0] = a[j+1][0];
a[j+1][0]=temp;
}
if(a[j][1]>a[j+1][1])
{
temp = a[j][1];
a[j][1] = a[j+1][1];
a[j+1][1]=temp;
}
if(a[j][2]>a[j+1][2])
{
temp = a[j][2];
a[j][2] = a[j+1][2];
a[j+1][2]=temp;
}
}
//得到rgb得中间值
*b = a[5][0];
*g = a[5][1];
*r = a[5][2];
//根据需要也可以选用灰度值
result = (a[5][0]*39 +a[5][1]*50 + a[5][2]*11)/100;
return result;
}
//实现图片的黑白二值化
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()
{
}
DIB::~DIB()
{
}
CPoint DIB::NextBorderPoint(CPoint CurrentPoint,LPBYTE lpDIBBits,WORD wBytesPerLine)
{
CPoint Pointtmp;
/* Pointtmp.x=-1;
Pointtmp.y=-1;
if(CurrentPoint.x!=this->width-1)
{
Pointtmp.x=CurrentPoint.x+1;
Pointtmp.y=CurrentPoint.y;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if((CurrentPoint.y!=this->height-1)&&(CurrentPoint.x!=this->width-1))
{
Pointtmp.x=CurrentPoint.x+1;
Pointtmp.y=CurrentPoint.y+1;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if(CurrentPoint.y!=this->height-1)
{
Pointtmp.x=CurrentPoint.x;
Pointtmp.y=CurrentPoint.y+1;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if((CurrentPoint.x!=0)&&(CurrentPoint.y!=this->height-1))
{
Pointtmp.x=CurrentPoint.x-1;
Pointtmp.y=CurrentPoint.y+1;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if(CurrentPoint.x!=0)
{
Pointtmp.x=CurrentPoint.x-1;
Pointtmp.y=CurrentPoint.y;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if((CurrentPoint.x!=0)&&(CurrentPoint.y!=0))
{
Pointtmp.x=CurrentPoint.x-1;
Pointtmp.y=CurrentPoint.y-1;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if(CurrentPoint.y != 0)
{
Pointtmp.x = CurrentPoint.x;
Pointtmp.y = CurrentPoint.y-1;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
if((CurrentPoint.y!=0)&&(CurrentPoint.x!=this->width-1))
{
Pointtmp.y=CurrentPoint.y-1;
Pointtmp.x=CurrentPoint.x+1;
if(this->IsBorderPoint(Pointtmp,lpDIBBits, wBytesPerLine))
return Pointtmp;
}
CPoint errorPoint;
errorPoint.x=errorPoint.y=-2;
return errorPoint;
*/
return Pointtmp;
}
BOOL DIB::IsBorderPoint(CPoint CurrentPoint ,LPBYTE lpDIBBits,WORD wBytesPerLine)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -