2021-04-08

标题MFC图像二值化处理

一、新建一个MFC工程,添加两个picture控件和一个按钮控件。
二、添加变量1.为两个picture控件添加control变量,类型为CStatic,变量名分别为m_picture1和m_picture2.
2.添加保存图片路径和名称变量,CString类型,变量名strFilePath,strFileName.
三、添加按钮消息映射函数双击“打开图片”按钮进入消息映射函数
为按钮添加打开文件的功能,并默认打开.png格式的文件,并在打开文件右下角添加文件类型选项。
将打开的图片显示在picture控件上。
对图片进行简单二值化处理。
使用前先在.cpp文件中添加 #include “vector”
代码如下:
// bmp2zhiDlg.cpp : 实现文件
//

#include “stdafx.h”
#include “bmp2zhi.h”
#include “bmp2zhiDlg.h”

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
CAboutDlg();

// 对话框数据
enum { IDD = IDD_ABOUTBOX };

protected:
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()

// Cbmp2zhiDlg 对话框

Cbmp2zhiDlg::Cbmp2zhiDlg(CWnd* pParent / =NULL/)
CDialog(Cbmp2zhiDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void Cbmp2zhiDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(Cbmp2zhiDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, &Cbmp2zhiDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &Cbmp2zhiDlg::OnBnClickedButton2)
END_MESSAGE_MAP()

// Cbmp2zhiDlg 消息处理程序

BOOL Cbmp2zhiDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
	BOOL bNameValid;
	CString strAboutMenu;
	bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
	ASSERT(bNameValid);
	if (!strAboutMenu.IsEmpty())
	{
		pSysMenu->AppendMenu(MF_SEPARATOR);
		pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
	}
}

// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE);			// 设置大图标
SetIcon(m_hIcon, FALSE);		// 设置小图标

// TODO: 在此添加额外的初始化代码

return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE

}

void Cbmp2zhiDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。

void Cbmp2zhiDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文

	SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

	// 使图标在工作区矩形中居中
	int cxIcon = GetSystemMetrics(SM_CXICON);
	int cyIcon = GetSystemMetrics(SM_CYICON);
	CRect rect;
	GetClientRect(&rect);
	int x = (rect.Width() - cxIcon + 1) / 2;
	int y = (rect.Height() - cyIcon + 1) / 2;

	// 绘制图标
	dc.DrawIcon(x, y, m_hIcon);
}
else
{
	CDialog::OnPaint();
}

}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR Cbmp2zhiDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}

void Cbmp2zhiDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
int threshold=100;
FILE* stream=fopen(“D:\1.bmp”,“rb”);
if(stream==NULL)
{
//cout<<“文件不存在”<<endl;
AfxMessageBox(“文件不存在”);
return;
}

int sizeFileHeader=sizeof(BITMAPFILEHEADER);  
int sizeInfoHeader=sizeof(BITMAPINFOHEADER);  

BITMAPFILEHEADER* bitmapFileHeader=new BITMAPFILEHEADER[sizeFileHeader+1];  

BITMAPINFOHEADER* bitmapInfoHeader=new BITMAPINFOHEADER[sizeInfoHeader+1];  

memset(bitmapFileHeader,0,sizeFileHeader+1);  
memset(bitmapInfoHeader,0,sizeInfoHeader+1);  
fread(bitmapFileHeader,sizeof(char),sizeFileHeader,stream);  
fseek(stream,sizeFileHeader,0);  
fread(bitmapInfoHeader,sizeof(char),sizeInfoHeader,stream);  
fseek(stream,sizeInfoHeader+sizeFileHeader,0);  
RGBQUAD* pRgbQuards=new RGBQUAD[256];  
for (int k=0;k<256;k++)  
{  
	fread(&pRgbQuards[k],sizeof(RGBQUAD),1,stream);  
}  

int count=(((bitmapInfoHeader->biWidth)*8+31)/32)*4-bitmapInfoHeader->biWidth*(bitmapInfoHeader->biBitCount/8);  
BYTE* tempData=new BYTE[count+1];  
memset(tempData,0,count+1);  
fseek(stream,sizeFileHeader+sizeInfoHeader+256*sizeof(RGBQUAD),0);  
BYTE** data=new BYTE*[bitmapInfoHeader->biHeight];  
for(int i=0;i<bitmapInfoHeader->biHeight;i++)  
{  
	data[i]=new BYTE[bitmapInfoHeader->biWidth];  
	for (int j=0;j<bitmapInfoHeader->biWidth;j++)  
	{  
		fread(&data[i][j],sizeof(char),1,stream);  
		if(data[i][j]>threshold)  
			data[i][j]=255;  
		else  
			data[i][j]=0;  
	}  
	for (int n=0;n<count;n++)  
	{  
		fread(&tempData[n],sizeof(char),1,stream);  
	}  
}  

fclose(stream);  



//写入。。  
FILE* fileWrite=fopen("D:\\09.bmp","a+");  
fwrite(bitmapFileHeader,sizeof(char),sizeof(BITMAPFILEHEADER),fileWrite);  
fwrite(bitmapInfoHeader,sizeof(char),sizeof(BITMAPINFOHEADER),fileWrite);  
fwrite(pRgbQuards,sizeof(RGBQUAD),256,fileWrite);  

for(int i=0;i<bitmapInfoHeader->biHeight;i++)  
{  
	for(int j=0;j<bitmapInfoHeader->biWidth;j++)  
	{  
		fwrite(&data[i][j],sizeof(BYTE),1,fileWrite);  
	}  
	for(int m=0;m<count;m++)  
		fwrite(&tempData[m],sizeof(char),1,fileWrite);  
}  
fclose(fileWrite);  

AfxMessageBox("success");

}

//几个全局变量,存放读入图像的位图数据、宽、高、颜色表及每像素所占位数(比特)
//此处定义全局变量主要为了后面的图像数据访问及图像存储作准备
unsigned char *pBmpBuf;//读入图像数据的指针
int bmpWidth;//图像的宽
int bmpHeight;//图像的高
RGBQUAD *pColorTable;//颜色表指针
int biBitCount;//图像类型

void Cbmp2zhiDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
//读入指定BMP文件进内存
char readPath[]=“D:\leangray.bmp”;
readBmp(readPath);

//输出图像的信息
//printf("width=%d,height=%d,biBitCount=%d\n",bmpWidth,bmpHeight,biBitCount);


//循环变量,图像的坐标
int i,j;
//每行字节数
int lineByte=(bmpWidth*biBitCount/8+3)/4*4;

//循环变量,针对彩色图像,遍历每像素的三个分量
int k;

//二值化处理
if(biBitCount==8){//对于灰度图像
	for(i=0;i<bmpHeight;i++){
		for(j=0;j<bmpWidth;j++){

			int p=*(pBmpBuf+i*lineByte+j);
			if(p<=160)
				*(pBmpBuf+i*lineByte+j)=0;
			else
				*(pBmpBuf+i*lineByte+j)=255;				
		}
	}
}
else if(biBitCount==24){//彩色图像
	for(i=0;i<bmpHeight/2;i++){
		for(j=0;j<bmpWidth/2;j++){
			for(k=0;k<3;k++)//每像素RGB三个分量分别置0才变成黑色
				*(pBmpBuf+i*lineByte+j*3+k)=0;
		}
	}
}

//将图像数据存盘
char writePath[]="D:\\lean_threshold_160.bmp";
saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);

//清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
delete []pBmpBuf;
if(biBitCount==8)
	delete []pColorTable;

}

/***********************************************************************

  • 函数名称:
  • readBmp()

*函数参数:

  • char *bmpName -文件名字及路径

*返回值:

  • 0为失败,1为成功

*说明:给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素

  •  位数等数据进内存,存放在相应的全局变量中
    

***********************************************************************/
bool Cbmp2zhiDlg::readBmp(char *bmpName)
{
//二进制读方式打开指定的图像文件
FILE *fp=fopen(bmpName,“rb”);
if(fp==0) return 0;

//跳过位图文件头结构BITMAPFILEHEADER
fseek(fp, sizeof(BITMAPFILEHEADER),0);


//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
BITMAPINFOHEADER head;  
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp); 

//获取图像宽、高、每像素所占位数等信息
bmpWidth = head.biWidth;
bmpHeight = head.biHeight;
biBitCount = head.biBitCount;

//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
int lineByte=(bmpWidth * biBitCount/8+3)/4*4;

//灰度图像有颜色表,且颜色表表项为256
if(biBitCount==8){
	//申请颜色表所需要的空间,读颜色表进内存
	pColorTable=new RGBQUAD[256];
	fread(pColorTable,sizeof(RGBQUAD),256,fp);
}

//申请位图数据所需要的空间,读位图数据进内存
pBmpBuf=new unsigned char[lineByte * bmpHeight];
fread(pBmpBuf,1,lineByte * bmpHeight,fp);

//关闭文件
fclose(fp);

return 1;

}

/***********************************************************************

  • 函数名称:
  • saveBmp()

*函数参数:

  • char *bmpName -文件名字及路径
  • unsigned char *imgBuf -待存盘的位图数据
  • int width -像素为单位待存盘位图的宽
  • int height -像素为单位待存盘位图高
  • int biBitCount -每像素所占位数
  • RGBQUAD *pColorTable -颜色表指针
    *返回值:
  • 0为失败,1为成功

*说明:给定一个图像位图数据、宽、高、颜色表指针及每像素所占的位数等信息,

  •  将其写到指定文件中
    

***********************************************************************/
bool Cbmp2zhiDlg::saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,
int biBitCount, RGBQUAD *pColorTable)
{
//如果位图数据指针为0,则没有数据传入,函数返回
if(!imgBuf)
return 0;

//颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
int colorTablesize=0;
if(biBitCount==8)
	colorTablesize=1024;

//待存储图像数据每行字节数为4的倍数
int lineByte=(width * biBitCount/8+3)/4*4;

//以二进制写的方式打开文件
FILE *fp=fopen(bmpName,"wb");
if(fp==0) return 0;

//申请位图文件头结构变量,填写文件头信息
BITMAPFILEHEADER fileHead;
fileHead.bfType = 0x4D42;//bmp类型

//bfSize是图像文件4个组成部分之和
fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
	+ colorTablesize + lineByte*height;
fileHead.bfReserved1 = 0;
fileHead.bfReserved2 = 0;

//bfOffBits是图像文件前三个部分所需空间之和
fileHead.bfOffBits=54+colorTablesize;

//写文件头进文件
fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);

//申请位图信息头结构变量,填写信息头信息
BITMAPINFOHEADER head; 
head.biBitCount=biBitCount;
head.biClrImportant=0;
head.biClrUsed=0;
head.biCompression=0;
head.biHeight=height;
head.biPlanes=1;
head.biSize=40;
head.biSizeImage=lineByte*height;
head.biWidth=width;
head.biXPelsPerMeter=0;
head.biYPelsPerMeter=0;
//写位图信息头进内存
fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);

//如果灰度图像,有颜色表,写入文件 
if(biBitCount==8)
	fwrite(pColorTable, sizeof(RGBQUAD),256, fp);

//写位图数据进文件
fwrite(imgBuf, height*lineByte, 1, fp);

//关闭文件
fclose(fp);

return 1;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值