📄 zxdib.cpp
字号:
// ZXDib.cpp: implementation of the CZXDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ZXDib.h"
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CZXDib::CZXDib()
{
}
CZXDib::~CZXDib()
{
}
////////////////////////////////////////////////////////////////////////////
// 从内存中装入图像数据到指定的矩阵: (只对256色和24位真彩色)
// FileName 是图像名字
// ppBitmapData 是待存储的图像一维向量的指针地址
// dwWidth , dwHeight 分别是图像的宽度和长度
// flag 返回图像位数(8或者24)
////////////////////////////////////////////////////////////////////////////
bool CZXDib::LoadVectorFromBMPFile(CString &FileName, BYTE *&pBitmapData, DWORD &dwHeight, DWORD &dwWidth,WORD &flag)
{
DWORD i,skip,position;
//打开制定图像文件FileName:
CFile File;
if(!File.Open(FileName,CFile::modeRead|CFile::typeBinary)){
AfxMessageBox(FileName+" 打不开!LoadBitmap"+FileName);
return FALSE;
}
FileName = File.GetFilePath();
//读文件头:
BITMAPFILEHEADER bfh;
File.Read(&bfh,sizeof(BITMAPFILEHEADER));
if(bfh.bfType!=0x4d42) //'BM' 不是bmp位图,返回
return FALSE;
//读位图信息头:
BITMAPINFO bmi;
File.Read(&bmi,sizeof(BITMAPINFO));
dwHeight = bmi.bmiHeader.biHeight;
dwWidth = bmi.bmiHeader.biWidth;
//1,4,8,24 分别对应2,16,256,真彩色
flag = bmi.bmiHeader.biBitCount;
if(flag == 24)
dwWidth *= 3; //若是真彩色,则把宽度变为三倍
DWORD dwSize = dwHeight * dwWidth; //位图矩阵大小
DWORD dReadWidth = (dwWidth+3)/4*4; //实际存储的宽度
//重新申请空间:
if(pBitmapData) delete pBitmapData;
pBitmapData = (BYTE*) new BYTE[dwSize];
if(!pBitmapData) return FALSE;
//设置每行跳转的字节数
skip = dReadWidth - dwWidth;
//设置初始的矩阵存放位置:
position = dwSize - dwWidth;
//读文件:
File.Seek(bfh.bfOffBits,0);
for(i=0;i<dwHeight;i++)
{
File.ReadHuge(pBitmapData+position,dwWidth);
File.Seek(skip,1);
position -= dwWidth; //调整指针
}
File.Close();
if(flag==24)
dwWidth /= 3; //恢复图像的宽度:
return true;
}
////////////////////////////////////////////////////////////////////
//将一维向量图像数据写入文件
// FileName 文件名
// pBitmapData 一维向量指针
// dwWidth,dwHeight 图像的宽度和长度
// flag : 图像的类型
////////////////////////////////////////////////////////////////////
bool CZXDib::WriteBMPFileFromVector(CString &FileName, BYTE *pBitmapData,DWORD dwHeight,DWORD dwWidth,WORD flag)
{
//参数有效性检测:
if(!pBitmapData)
return FALSE;
if((flag!=8)&&(flag!=24))
return FALSE;
if(flag == 24)
dwWidth *= 3;
DWORD dwWriteWidth = (dwWidth+3)/4*4;
DWORD dwWriteSize = dwHeight * dwWriteWidth;
//打开文件:
CFile File;
File.Open(FileName,CFile::modeCreate|CFile::modeWrite);
BITMAPFILEHEADER BitmapFileHeader;
if(flag == 24)
BitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)-4;
else
BitmapFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFO)-4+256*sizeof(RGBQUAD);
BitmapFileHeader.bfReserved1 = 0;
BitmapFileHeader.bfReserved2 = 0;
BitmapFileHeader.bfType = 0x4d42;//'BM'
BitmapFileHeader.bfSize = dwWriteSize + BitmapFileHeader.bfOffBits;
File.Write(&BitmapFileHeader,sizeof(BITMAPFILEHEADER));
BITMAPINFO BitmapInfo;
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO)-4;//无论是黑白图还是彩图都是40
BitmapInfo.bmiHeader.biBitCount = flag;
BitmapInfo.bmiHeader.biHeight = dwHeight;
if(flag ==24)
BitmapInfo.bmiHeader.biWidth = dwWidth/3;
else
BitmapInfo.bmiHeader.biWidth = dwWidth;
BitmapInfo.bmiHeader.biSizeImage = dwWriteSize;
BitmapInfo.bmiHeader.biCompression= 0;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biClrImportant = 0;
BitmapInfo.bmiHeader.biClrUsed = 0;
BitmapInfo.bmiHeader.biXPelsPerMeter =
BitmapInfo.bmiHeader.biYPelsPerMeter=0;
BitmapInfo.bmiColors[0].rgbBlue =
BitmapInfo.bmiColors[0].rgbGreen=
BitmapInfo.bmiColors[0].rgbRed=
BitmapInfo.bmiColors[0].rgbReserved=0;
File.Write(&BitmapInfo,sizeof(BITMAPINFO));
//若是256色图像则,写调色板
if( flag==8 )
{
for(int i=1; i<256; i++)
{
BYTE temp = (BYTE) i;
File.Write(&temp,1);
File.Write(&temp,1);
File.Write(&temp,1);
temp = 0;
File.Write(&temp,1);
}
}
//写文件:
DWORD position = dwWidth*dwHeight - dwWidth;
DWORD skip = dwWriteWidth - dwWidth;
File.Seek(BitmapFileHeader.bfOffBits,0);
for(DWORD i=0; i<dwHeight; i++)
{
File.Write(pBitmapData+position,dwWidth);
File.Seek(skip,1);
position -= dwWidth;
}
char ch='/0';
File.Write(&ch,sizeof(char));
File.Close();
return true;
}
/////////////////////////////////////////////////////////////////////////
//
// 寻找下一个文件名
//
/////////////////////////////////////////////////////////////////////////
bool CZXDib::FindNextFileName(CString &FileName,int iStep)
{
int position = FileName.Find(".bmp");
if(position<0)
position = FileName.Find(".BMP");
position--;
while(iStep>0)
{
char ch = FileName.GetAt(position);
if(ch<'9'){
ch++;
FileName.SetAt(position,ch);
}
else{
FileName.SetAt(position,'0');
ch = FileName.GetAt(position-1);
if(ch<'9') {
ch++;
FileName.SetAt(position-1,ch);
}
else {
FileName.SetAt(position-1,'0');
ch = FileName.GetAt(position-2);
if(ch<'9'){
ch++;
FileName.SetAt(position-2,ch);
}
else{
FileName.SetAt(position-2,'0');
ch = FileName.GetAt(position-3);
ch++;
FileName.SetAt(position-3,ch);
}
}
}
iStep--;
}
return true;
}
////////////////////////////////////////////////////
//
// 将向量数据转换为BMP图像向量:
//
////////////////////////////////////////////////////
bool CZXDib::TranslateVectorToBitmap(DWORD dwHeight,DWORD dwWidth,BYTE* pVector,BYTE*& pBitmapData,WORD flag)
{
DWORD i,j;
if(flag==24) dwWidth *= 3;
else
if(flag!=8) return false;
DWORD dwWriteWidth = (dwWidth+3)/4*4;
if(pBitmapData) delete []pBitmapData;
pBitmapData = (BYTE*) new BYTE[dwHeight*dwWriteWidth];
for(i=0; i<dwHeight; i++)
for(j=0; j<dwWidth; j++)
pBitmapData[(dwHeight-1-i)*dwWriteWidth+j] = pVector[i*dwWidth+j];
return true;
}
////////////////////////////////////////////////////
//
// 将BMP图像向量转换为向量数据:
//
////////////////////////////////////////////////////
bool CZXDib::TranslateBitmapToVector(DWORD dwHeight,DWORD dwWidth,BYTE* pBitmapData,BYTE*& pVector,WORD flag)
{
DWORD i,j;
if(flag==24) dwWidth *= 3;
else
if(flag!=8) return false;
DWORD dwWriteWidth = (dwWidth+3)/4*4;
if(pVector) delete []pVector;
pVector = (BYTE*) new BYTE[dwHeight*dwWriteWidth];
for(i=0; i<dwHeight; i++)
for(j=0; j<dwWidth; j++)
pVector[i*dwWidth+j] = pBitmapData[(dwHeight-1-i)*dwWriteWidth+j];
return true;
}
///////////////////////////////////////////////////////////////////
//
// 得到BMP位图的头信息指针
//
///////////////////////////////////////////////////////////////////
bool CZXDib::GetBMPFileHeader(BITMAPFILEHEADER &bfh,CString &FileName)
{
CFile File;
if(!File.Open(FileName,CFile::modeRead|CFile::typeBinary)){
AfxMessageBox(FileName+" 打不开!LoadBitmap");
return FALSE;
}
File.Read(&bfh,sizeof(BITMAPFILEHEADER));
File.Close();
return true;
}
///////////////////////////////////////////////////////////////////
//
// 得到BMP位图的头信息指针
//
///////////////////////////////////////////////////////////////////
bool CZXDib::GetBitmapInfo(BITMAPINFO *&bmi, CString &FileName)
{
CFile File;
if(!File.Open(FileName,CFile::modeRead|CFile::typeBinary)){
AfxMessageBox(FileName+" 打不开!LoadBitmap");
return FALSE;
}
File.Seek(sizeof(BITMAPFILEHEADER),0);
if(bmi) delete bmi;
bmi = (BITMAPINFO*) new BYTE[sizeof(BITMAPINFO)+256*sizeof(RGBQUAD)];
File.Read(bmi,sizeof(BITMAPINFO)+256*sizeof(RGBQUAD));
File.Close();
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
//
// Sobel算子
/////////////////////////////////////////////////////////////////////////////
bool CZXDib::Sobel(BYTE *& pImage, DWORD dwHeight, DWORD dwWidth)
{
DWORD i,j;
double temp1,temp2;
DWORD Height,Width,dwSize;
Height = dwHeight-1;
Width = dwWidth-1;
dwSize = dwHeight*dwWidth;
double * pResult=NULL;
if(!(pResult = (double*) new double[dwHeight*dwWidth]))
{
AfxMessageBox("分配空间失败!CZXDib::Sobel pResult");
return false;
}
for(i=1; i<Height; i++)
for(j=1; j<Width; j++)
{
//水平方向
temp1 = pImage[j+1+(i-1)*dwWidth]+2*pImage[j+1+i*dwWidth]+pImage[j+1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j-1+i*dwWidth]-pImage[j-1+(i+1)*dwWidth];
temp1 *= temp1;
//竖直方向
temp2 = pImage[j+1+(i+1)*dwWidth]+2*pImage[j+(i+1)*dwWidth]+pImage[j-1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j+(i-1)*dwWidth]-pImage[j+1+(i-1)*dwWidth];
temp2 *= temp2;
pResult[j+i*dwWidth]= sqrt(temp1+temp2);
}
for(i=0;i<dwSize;i+=dwWidth)
{
pImage[i]=0;
pImage[i+dwWidth-1]=0;
}
for(j=0;j<dwWidth;j++)
{
pImage[j]=0;
pImage[dwSize-j-1]=0;
}
for(i=1; i<Height; i++)
for(j=1; j<Width; j++)
{
if(pResult[j+i*dwWidth]>255)
pImage[j+i*dwWidth] = 255;
else
pImage[j+i*dwWidth] = (BYTE) pResult[j+i*dwWidth];
}
delete pResult;
return true;
}
////////////////////////////////////////////////////////////////////////////
//
// Sobel算子
/////////////////////////////////////////////////////////////////////////////
bool CZXDib::Sobel(BYTE* pImage, DWORD dwHeight, DWORD dwWidth,double* &pResult)
{
DWORD i,j;
double temp1,temp2;
DWORD Height,Width,dwSize;
Height = dwHeight-1;
Width = dwWidth-1;
dwSize = dwHeight*dwWidth;
dwSize -= dwWidth;
if(pResult) delete pResult;
if(!(pResult = (double*) new double[dwHeight*dwWidth]))
{
AfxMessageBox("分配空间失败!CZXDib::Sobel pResult");
return false;
}
for(i=1; i<Height; i++)
for(j=1; j<Width; j++)
{
//水平方向
temp1 = pImage[j+1+(i-1)*dwWidth]+2*pImage[j+1+i*dwWidth]+pImage[j+1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j-1+i*dwWidth]-pImage[j-1+(i+1)*dwWidth];
temp1 *= temp1;
//竖直方向
temp2 = pImage[j+1+(i+1)*dwWidth]+2*pImage[j+(i+1)*dwWidth]+pImage[j-1+(i+1)*dwWidth]-pImage[j-1+(i-1)*dwWidth]-2*pImage[j+(i-1)*dwWidth]-pImage[j+1+(i-1)*dwWidth];
temp2 *= temp2;
pResult[j+i*dwWidth]= sqrt(temp1+temp2);
}
for(i=0;i<dwSize;i+=dwWidth)
{
pResult[i]=0;
pResult[i+dwWidth-1]=0;
}
for(j=0;j<dwWidth;j++)
{
pResult[j]=0;
pResult[dwSize-j-1]=0;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////
//
// 求直方图:
//
////////////////////////////////////////////////////////////////////////////////////////
bool CZXDib::Histogram(BYTE *pBitmap, DWORD dwHeight, DWORD dwWidth, BYTE *&pResult)
{
DWORD i,j,max;
if(pResult) delete pResult;
pResult = new BYTE[256];
DWORD pTemp[256];
for(i=0; i<256; i++)
pTemp[i]=0;
for(j=0; j<dwHeight; j++)
for(i=0; i<dwWidth; i++)
pTemp[pBitmap[j*dwWidth+i]]++;
max = 0;
for(i=0;i<256; i++)
if(pTemp[i]>max) max = pTemp[i];
for(i=0; i<256; i++)
pResult[i] = (BYTE) (pTemp[i]*255/max);
return true;
}
//////////////////////////////////////////////////////////////////
//
// 将直方图转化为256*256显示矩阵
//
//////////////////////////////////////////////////////////////////
bool CZXDib::TranslateHistogramToVector(BYTE *pHg, BYTE *&pResult)
{
DWORD i,j,top;
if(pResult) delete pResult;
pResult = new BYTE[256*256];
for(i=0; i<256; i++)
{
top = 256-pHg[i];
for(j=0; j<top; j++)
pResult[j*256+i] = 240;
for(;j<256;j++)
pResult[j*256+i] = 0;
}
return true;
}
////////////////////////////////////////////////////////////////////////
//
// 直方图平滑:
//
////////////////////////////////////////////////////////////////////////
bool CZXDib::HistogramSmoothBy5Points(BYTE *pHg,int level)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -