vc++ bmp图像二值化
来源:互联网 发布:jquery数组删除元素吗 编辑:程序博客网 时间:2024/06/13 06:48
在网上看到2个例子:
方法一:http://blog.csdn.net/mydreamremindme/article/details/9950453 我生成的不是白色底,是蓝色底不知道为何
方法二:http://download.csdn.net/download/s200692269/2663986
测试Demo
1、新建基于mfc的dialog程序,添加2个按键,分别对应上面那俩方法代码
2、.h的代码
private:bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable);bool readBmp(char *bmpName);public:afx_msg void OnBnClickedButton1();afx_msg void OnBnClickedButton2();
3、.cpp代码
// 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_MAPON_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<HCURSOR>(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;//跳过位图文件头结构BITMAPFILEHEADERfseek(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;//灰度图像有颜色表,且颜色表表项为256if(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字节,彩色图像颜色表大小为0int 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
- vc++ bmp图像二值化
- VC 自绘制BMP图像
- VC改变BMP图像大小
- VC保存和显示数据库图像(BMP)
- VC++创建BMP图像且保存
- VC保存和显示数据库图像(BMP)
- VC 中BMP、JPG、GIF图像的显示
- [Visual C++](一)VC保存和显示数据库图像(BMP)
- (一)VC保存和显示数据库图像(BMP)
- BMP图像
- VC数字图像处理编程讲座之四--BMP图像显示的特效操作
- (转)VC数字图像处理编程讲座之三 ---BMP图像的基本操作
- Bmp图像数据结构
- Bitmap 图像结构(.bmp)
- BMP图像翻转
- bmp图像结构
- bmp图像 蓝桥杯
- 创建BMP图像
- java nio 之FileChannel
- 【Matlab】连接字符串的方法
- Entity Framework Code First数据库连接
- 省市区三级联动
- signal 信号列表 (kill -l)
- vc++ bmp图像二值化
- 理解常量指针和指针常量
- php 下载文件,考虑到各种格式,解决下载时部分出现文件损坏的问题
- 【机器学习实战02】使用k-近邻算法改进约会网站的配对效果
- Gradle 入门知识
- HDU 3466 Proud Merchantss
- 项目中Android https或http请求地址重定向为HTTPS的地址
- 简单的交互式shell(模似shell命令操作)
- 第三届河南省赛