VC 数字图像处理实验(VC 单文档)

更新时间:2024-06-16 10:19:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

数字图像处理 实验指导书

山东大学威海分校机电与信息工程学院

2012年3月

概述

实验项目:数字图像处理程序编程 运行环境:Windows XP/7 编程工具:Visual C++ 6.0 主要内容:

(1) 建立程序框架,实现图像的读取、保存、显示;

(2) 编写颜色处理、几何变换、平滑锐化等图像处理代码,并实现其调用; (3) 自行编写实现扩展的图像处理功能。

第一节 建立程序框架

预备工作:在本机的硬盘上以自己完整的学号和姓名建立一个文件夹。上机编程的内容全部保存在该文件夹中。每次下机前将该文件夹拷贝到网络服务器上本班的文件夹中;下次上机时再从服务器上将文件夹拷贝到本机。 1. 新建应用程序

1.1运行Visual C++ 6.0;

1.2 点击菜单“文件——新建”,打开“新建”对话框(Ctrl+N); 点击“工程”选项页;选中“MFC AppWizard(exe)”;在“位置”编辑框中选中自己所建立的文件夹;在“工程名称”编辑框中输入DIPXXX,其中XXX为自己姓名的拼音缩写和学号,如DIPJQ;按“确定”按钮,进入向导过程。

2. 应用程序向导

步骤1:选择“单文档”,其它不变,

步骤2:不作改变,点击“下一步”;

步骤3:不作改变,

步骤4:按下“高级”按钮,在“文件扩展名”编辑框中输入bmp,关闭;点击“下一步”;

步骤5:选择“作为静态的DLL”,点击“下一步”;

步骤6:将CDIPJQView类的基类选择为CScrollView,其它不变,点击“完成”。

点击“确定”。

3. 应用程序框架及基本操作

在完成向导过程后,将建立一套应用程序框架,该框架中包含如下几个类:

CDIPJQApp ——应用程序类 CMainFrame ——主窗口框架类 CDIPJQDoc ——文档类 CDIPJQView ——视图类 CAboutDlg ——关于对话框类

(其中JQ应换为自己姓名的拼音缩写和学号,后同) 每个类都有一个类定义文件.h,和类实现文件.cpp。

在VC主界面左侧的组合窗口中,切换到“ClassViev”选项页,点击展开“DIPJQ Classes”,将列出该应用程序的所有类。双击某个类,将在编辑窗口中打开该类的.h文件;点击展开类,双击类中已实现的某个成员函数,将打开该类的.cpp文件。

4. 修改“关于”对话框

在VC主界面左侧的组合窗口中,切换到“ResourceView”选项页,展开“DIPJQresources”,展开“Dialog”,双击“IDD_ABOUTBOX”,对“关于”对话框进行编辑,在“版权所有 (C) 2009”之前加上自己的学号和姓名,然后保存。

5. 组建和运行程序

点击菜单“组建——组建”,或点击相应的工具条按钮(F7),生成可执行程序(exe);

点击菜单“组建—执行”,或点击相应的工具条按钮(Ctrl+F5),运行该程序,在程序中打开“关于”对话框。

第二节 建立图像类

1. 建立类文件

点击菜单“插入—类”,打开“新建类”对话框;在类的类型中选中“Generic Class”;在名称中输入“SDImage”;确定。建立起SDImage类的头文件SDImage.h和源文件SDImage.cpp。

2. 编写类定义代码

打开SDImage.h文件,将SDImage类的定义代码添加到该头文件中(灰底部分为文件中已有的代码,后同):

class SDImage {

public: BOOL CopyFrom(SDImage *a_pImg);

BOOL Create(int a_Width,int a_Height);

int FitBlt(HDC a_DestDC,int a_DestX,int a_DestY,int a_DestWidth,int a_DestHeight,int a_SrcX,int a_SrcY,int a_SrcWidth,int a_SrcHeight,DWORD a_Rop=SRCCOPY); BOOL StretchBlt(HDC a_DestDC,int a_DestX,int a_DestY,int a_DestWidth,int a_DestHeight,int a_SrcX,int a_SrcY,int a_SrcWidth,int a_SrcHeight,DWORD a_Rop=SRCCOPY); BOOL BitBlt(HDC a_DestDC,int a_DestX,int a_DestY,int a_Width,int a_Height,int a_SrcX,int a_SrcY,DWORD a_Rop=SRCCOPY); BOOL SaveBitmap(CString a_Filename);

BOOL IsValid(); void Destroy(); CDC m_DC; BYTE * m_pBits; int m_ImageSize; int m_WidthBytes; int m_Height; BOOL LoadBmpFile(CString a_Filename); int m_Width; SDImage(); virtual ~SDImage(); protected: HDC m_hMemDC; HBITMAP m_hBitmap; private: HBITMAP m_hOldBitmap; };

#endif

// !defined(AFX_SDIMAGE_H__BA98791A_D437_4687_AAEA_B988391C2FCC__INCLUDED_)

***添加成员变量和成员函数

右键单击左侧类中SDImage类,选择添加成员变量。

右键单击左侧类中SDImage类,选择添加成员函数。

3. 编写类实现代码

打开SDImage.cpp文件,将SDImage类的实现代码添加到该文件中。

(1) 构造及析构函数 SDImage:: SDImage() { m_hBitmap = NULL; m_pBits = NULL; m_hMemDC = NULL; }

SDmage::~ SDmage() { Destroy(); }

(2) 图像空间创建函数

按给定的图像尺寸分配图像的内存空间,并定义相关参数。 BOOL SDImage::Create(int a_Width, int a_Height) { Destroy(); if( a_Width==0 || a_Height==0 ) return FALSE; if( a_Width<0 ) a_Width = -a_Width; if( a_Height<0 ) a_Height = -a_Height;

BITMAPINFO bi; bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bi.bmiHeader.biWidth = a_Width; bi.bmiHeader.biHeight = -a_Height; bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 24; bi.bmiHeader.biCompression = BI_RGB; bi.bmiHeader.biSizeImage = 0; bi.bmiHeader.biXPelsPerMeter = 11810; bi.bmiHeader.biYPelsPerMeter = 11810; bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; HDC hdc=CreateCompatibleDC(NULL); m_hBitmap

CreateDIBSection(hdc,&bi,DIB_RGB_COLORS,(void**)&m_pBits,NULL,0); DeleteDC(hdc); if( m_hBitmap==NULL || m_pBits==NULL ) { m_hBitmap = NULL; m_pBits = NULL; return FALSE; } BITMAP bm; GetObject(m_hBitmap,sizeof(BITMAP),&bm); m_Width = bm.bmWidth; m_Height = bm.bmHeight; m_WidthBytes = bm.bmWidthBytes; m_ImageSize = m_WidthBytes*m_Height; m_hMemDC = CreateCompatibleDC(NULL); if( m_hMemDC==NULL ) { DeleteObject(m_hBitmap); m_hBitmap = NULL; m_pBits = NULL; m_hMemDC = NULL; return FALSE; } m_hOldBitmap = (HBITMAP)SelectObject(m_hMemDC,m_hBitmap); m_DC.Attach(m_hMemDC); return TRUE; }

=

(3) 图像空间释放函数 void SDImage::Destroy() { }

if( m_hBitmap!=NULL && m_pBits!=NULL && m_hMemDC!=NULL ) { m_DC.Detach(); SelectObject(m_hMemDC,m_hOldBitmap); DeleteDC(m_hMemDC); DeleteObject(m_hBitmap); }

m_hBitmap = NULL; m_pBits = NULL;

m_hMemDC = NULL;

(4) 图像有效性判别及图像复制函数

BOOL SDImage::IsValid() { return ( m_hBitmap!=NULL && m_pBits!=NULL && m_hMemDC!=NULL ); }

BOOL SDImage::CopyFrom(SDImage *a_pImg) { if( a_pImg==NULL || !a_pImg->IsValid() ) return FALSE; if( !Create(a_pImg->m_Width, a_pImg->m_Height) ) return FALSE; memcpy( (void*)m_pBits, (void*)a_pImg->m_pBits, m_WidthBytes*m_Height ); return TRUE; }

(5) 图像显示函数

直接显示,缩放显示,按适合窗口的尺寸显示图像。

BOOL SDImage::BitBlt(HDC a_DestDC, int a_DestX, int a_DestY, int a_Width, int a_Height, int a_SrcX, int a_SrcY, DWORD a_Rop) { return ::BitBlt(a_DestDC, a_DestX, a_DestY, a_Width, a_Height,m_hMemDC, a_SrcX, a_SrcY, a_Rop) }

BOOL SDImage::StretchBlt(HDC a_DestDC, int a_DestX, int a_DestY, int a_DestWidth, int a_DestHeight, int a_SrcX, int a_SrcY, int a_SrcWidth, int a_SrcHeight, DWORD a_Rop)

{ ::SetStretchBltMode(a_DestDC,COLORONCOLOR); return ::StretchBlt(a_DestDC, a_DestX, a_DestY, a_DestWidth, a_DestHeight,m_hMemDC, a_SrcX, a_SrcY, a_SrcWidth, a_SrcHeight, a_Rop); }

(6) Bmp文件读入函数

BOOL SDImage::LoadBmpFile(CString a_Filename) { FILE *pf = fopen(a_Filename,\ if( pf==NULL ) return FALSE; BITMAPFILEHEADER bmfHeader; if ( fread((LPSTR)&bmfHeader,1,sizeof(bmfHeader),pf) != sizeof(bmfHeader) ) { fclose(pf); return FALSE; } if( bmfHeader.bfType != ((WORD)('M'<<8) | 'B') ) { fclose(pf); return FALSE; } int leng = bmfHeader.bfSize - sizeof(bmfHeader); BYTE *pBmp = (BYTE *)calloc(leng,1); if( pBmp == NULL ) { fclose(pf); return FALSE; } if ( (int)fread(pBmp,1,leng,pf) != leng ) { free(pBmp); fclose(pf); return FALSE; } fclose(pf); BYTE *pImg=(BYTE*)(pBmp + bmfHeader.bfOffBits - sizeof(BITMAPFILEHEADER)); BITMAPINFO *pbi; pbi = (BITMAPINFO*)pBmp; if( pbi->bmiHeader.biBitCount != 24 ) { free(pBmp); return FALSE; } int widthBytes = ((pbi->bmiHeader.biWidth*pbi->bmiHeader.biBitCount+31)/32)*4; int i; BYTE *p1,*p2; RGBQUAD *ci = pbi->bmiColors; if( Create( pbi->bmiHeader.biWidth, abs(pbi->bmiHeader.biHeight) ) ) { int bytes = m_WidthBytes;

if( bytes>widthBytes ) bytes = widthBytes; for(i=0;ibmiHeader.biHeight<0 ) p2 = pImg + i*widthBytes; else p2 = pImg + (m_Height-1-i)*widthBytes; memcpy(p1,p2,bytes); } free(pBmp); return TRUE; } else {free(pBmp); return FALSE; } }

(7) Bmp文件保存函数

BOOL SDImage::SaveBitmap(CString a_Filename) { if( !IsValid() ) return FALSE; FILE *pf = fopen(a_Filename,\ if( pf==NULL ) return FALSE; BITMAPINFO *pbmi; pbmi = (BITMAPINFO*)calloc(1, sizeof(BITMAPINFOHEADER)); pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biWidth = m_Width; pbmi->bmiHeader.biHeight = m_Height; pbmi->bmiHeader.biPlanes = 1; pbmi->bmiHeader.biBitCount = 24;

pbmi->bmiHeader.biCompression = BI_RGB; UINT widthBytes = ((m_Width * 24 +31)/32)*4;

pbmi->bmiHeader.biSizeImage = widthBytes * m_Height; pbmi->bmiHeader.biXPelsPerMeter = 11810; pbmi->bmiHeader.biYPelsPerMeter = 11810; pbmi->bmiHeader.biClrUsed = 0; pbmi->bmiHeader.biClrImportant = 0;

BITMAPFILEHEADER hdr; BITMAPINFOHEADER *pbih;

pbih = (BITMAPINFOHEADER*)pbmi;

hdr.bfType = 0x4d42; // 0x42 = \

hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biSizeImage); hdr.bfReserved1 = 0;

hdr.bfReserved2 = 0;

hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize; fwrite(&hdr, sizeof(BITMAPFILEHEADER), 1, pf); fwrite(pbih, sizeof(BITMAPINFOHEADER), 1, pf); int i; BYTE *p1; for(i=m_Height-1;i>=0;i--) { p1 = m_pBits + m_WidthBytes * i; if( fwrite(p1, 1, widthBytes, pf) != widthBytes ) { free((HLOCAL)pbmi); fclose(pf); return FALSE; } } free((HLOCAL)pbmi); fclose(pf); return TRUE; }

4. 组建程序

在SDImage.cpp处于当前编辑窗口时,点击菜单“组建—编译”,或点击相应的工具栏图标,对SDImage.cpp进行编译。在VC主界面下侧的组合窗口中将显示编译的状态。当编译中出现错误时,按F4键将依次定位到源程序的错误处,请检查并改正错误。

第四节 定义图像文档实现图像读/写

1. 添加头文件

在DIPJQ.h文件中添加如下一行代码:(其中灰色部分为程序中已有的代码,后同) #include \ // main symbols #include \

2. 定义图像类指针

在DIPJQDoc.h文件中添加如下一行代码: // Attributes public:

class SDImage *m_pCurImage,*m_pLastImage;

注:定义两个图像类的指针,以使程序具备对最近一次处理的恢复功能。

3. 图像对象的建立和释放

在“ClassView”选项页中,点击展开“CDIPJQDoc”,双击“CDIPJQDoc()”,打开DIPJQDoc.cpp文件,在文件中修改添加如下代码: CDIPJQDoc::CDIPJQDoc() { }

CDIPJQDoc::~CDIPJQDoc() { }

delete m_pCurImage; delete m_pLastImage;

4. 进行消息映射

点击菜单“查看—建立类向导”,打开“MFC ClassWizard”对话框(Ctrl+w)。在“Class Name”下拉框中选中“CDIPJQDoc”,在“Object IDs”列表框中选中“CDIPJQDoc”,然后在“Messgaes”列表框中,选中“OnOpenDocument”并双击,建立起相应的消息映射函数;再选中“OnSaveDocument”双击。

// TODO: add one-time construction code here m_pCurImage = new SDImage; m_pLastImage = new SDImage;

在“Object IDs”列表框中选中“ID_EDIT_UNDO”,然后在“Message”列表框中双击“COMMAND”,建立起相应的消息映射函数。

5. 添加消息映射函数代码

在“ClassView”选项页中,点击展开“CDIPJQDoc”,双击“OnOpenDocument(LPCTSTR lpszPathName)”,打开DIPJQDoc.cpp文件,在文件中添加如下代码: BOOL CDIPJQDoc::OnOpenDocument(LPCTSTR lpszPathName) { if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; // TODO: Add your specialized creation code here return m_pCurImage->LoadBmpFile(lpszPathName); }

BOOL CDIPJQDoc::OnSaveDocument(LPCTSTR lpszPathName) { // TODO: Add your specialized code here and/or call the base class return m_pCurImage->SaveBitmap(lpszPathName); }

void CDIPJQDoc::OnEditUndo() { // TODO: Add your command handler code here if( m_pCurImage->IsValid() && m_pLastImage->IsValid() ) { SDImage *p = m_pCurImage; m_pCurImage = m_pLastImage; m_pLastImage = p;

}

}

UpdateAllViews(NULL);

点击菜单“组建——组建”,再次组建整个程序,排除组建过程中出现的错误。

***此时运行程序,图像数据可以读入,但是无法显示图像。

第五节 实现图像显示

1. 定义显示控制变量

在DIPJQView.h文件中添加两个显示控制变量。 public: CDIPJQDoc* GetDocument(); int m_ShowMode; int m_ShowScale;

在DIPJQView.cpp文件中定义两个显示模式枚举常量,在构造函数中给显示控制参数赋初值。

enum {SHOWMODE_SCALE, SHOWMODE_FIT}; CDIPJQView::CDIPJQView() { // TODO: add construction code here m_ShowMode = SHOWMODE_FIT; m_ShowScale = 100; }

2. 图像显示代码

在CDIPJQView类的OnDraw()函数中添加图像显示代码。

void CDIPJQView::OnDraw(CDC* pDC) { CDIPJQDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here CRect rect; if( m_ShowMode == SHOWMODE_FIT ) { GetClientRect(&rect); m_ShowScale = pDoc->m_pCurImage->FitBlt(pDC->m_hDC,0,0,rect.Width(), rect.Height(),0,0,pDoc->m_pCurImage->m_Width, pDoc->m_pCurImage->m_Height); } else { CSize size; size = GetTotalSize(); GetClientRect(&rect); int x0=0,y0=0; if( rect.Width()>size.cx ) x0 = (rect.Width()-size.cx)/2; if( rect.Height()>size.cy )

y0 = (rect.Height()-size.cy)/2; if( m_ShowScale==100 ) pDoc->m_pCurImage->BitBlt(pDC->m_hDC,x0,y0,pDoc->m_pCurImage->m_Width, pDoc->m_pCurImage->m_Height,0,0); else pDoc->m_pCurImage->StretchBlt(pDC->m_hDC,x0,y0,size.cx,size.cy, 0,0,pDoc->m_pCurImage->m_Width,pDoc->m_pCurImage->m_Height); } }

3. 图像区域设置代码

在CDIPJQView类的OnInitialUpdate()函数中添加视图滚动区域设置代码。

void CDIPJQView::OnInitialUpdate() { CScrollView::OnInitialUpdate(); CDIPJQDoc* pDoc = GetDocument(); CSize sizeTotal; // TODO: calculate the total size of this view if( pDoc->m_pCurImage->IsValid() ) { if( m_ShowMode==SHOWMODE_FIT ) { CRect rect; this->GetClientRect(&rect); sizeTotal.cx = rect.Width(); sizeTotal.cy = rect.Height(); } else { sizeTotal.cx = (int)(pDoc->m_pCurImage->m_Width*m_ShowScale/100.0+0.5); sizeTotal.cy = (int)(pDoc->m_pCurImage->m_Height*m_ShowScale/100.0+0.5); } // ((CMainFrame*)AfxGetApp()->m_pMainWnd)->ShowScale(m_ShowScale); } else { sizeTotal.cx = sizeTotal.cy = 100; }

}

SetScrollSizes(MM_TEXT, sizeTotal);

4. 修整程序菜单

切换到“ResourceView”选项页,展开“DIPJQ resources”,展开“Menu”,双击“IDR_MAINFRAME”,对菜单进行编辑。在各顶层菜单下保留如下菜单项,其余删除。

文件:打开,保存,另存为,最近文件,退出 编辑:撤消 查看:工具栏,状态栏 帮助:关于

5. 添加显示操作菜单

点击顶层菜单“查看”,双击下部空白菜单项,打开“菜单项目 属性”对话框,在ID下拉列表框中输入“ID_SHOW_ENLARGE”,在标明编辑框中输入“放大”,在提示编辑框中输入“放大显示图象\\n放大”。关闭对话框,将该菜单项拖至最上部。

继续依次建立如下三个菜单项:

ID ID_SHOW_REDUCE ID_SHOW_ORIGINAL ID_SHOW_FIT 标明 缩小 原始尺寸 适合窗口 提示 缩小显示图象\\n缩小 按原始尺寸显示图象\\n原始尺寸 使图象完整显示在窗口中\\n适合窗口

点击顶层菜单“查看”,双击下部空白菜单项,在“菜单项目 属性”对话框中,选中“分隔符”,关闭对话框,将分隔符拖至“工具栏”菜单项之上,“适合窗口”之下。

6. 编辑工具栏

切换到“ResourceView”选项页,展开“DIPJQ resources”,展开“Toolbar”,双击“IDR_MAINFRAME”,对工具栏进行编辑。

保留打开、保存、关于三个按钮,删除其它按钮。

添加“撤消”按钮:点中最后的空白按钮,绘制撤消图形,双击该按钮,将ID设为“ID_EDIT_UNDO”,将按钮拖至保存按钮之后。

再依次添加如下四个按钮:

放大——ID_SHOW_ENLARGE 缩小——ID_SHOW_REDUCE

原始尺寸——ID_SHOW_ORIGINAL 适合屏幕——ID_SHOW_FIT 工具栏中个按钮的形状如下:

3. 编写类实现代码

在SDImageProc.cpp中添加如下类实现代码:

#include \

SDImageProc: SDImageProc() { m_pSrcImg = m_pDestImg = NULL; }

SDImageProc::~ SDImageProc() { }

BOOL SDImageProc::ImageIsValid() { if( m_pSrcImg==NULL || m_pDestImg==NULL ) return FALSE; return m_pSrcImg->IsValid(); }

说明:各图像处理函数均将在该类中定义并实现,每添加一个图像处理函数,都应首先在SDImageProc.h文件中加入函数定义代码,然后在SDImageProc.cpp文件中编写函数实现代码。

第七节 实现颜色处理功能

(一) 亮度处理

1. 在图像处理类中实现亮度处理功能

在SDImageProc类中添加并实现亮度处理函数。

首先打开SDImageProc.h文件,在其中加入亮度处理函数的定义,如下: class SDImageProc {

public: SDImageProc(); virtual ~SDImageProc(); class SDImage *m_pSrcImg,*m_pDestImg; BOOL ImageIsValid(); //源和目标图象是否有效 BOOL ModifyLight(float d); //亮度调整,-1~1

};

#endif

// !defined(AFX_SDMAGEPROC_H__CA6A65DD_DBE3_4D8F_AE45_FD6611866EE3__INCLUDED_)

再打开SDImageProc.cpp文件,在最后添加亮度处理函数的实现代码,如下:

BOOL SDmageProc::ModifyLight(float d) { if( !ImageIsValid() ) return FALSE; m_pDestImg->Create(m_pSrcImg->m_Width, m_pSrcImg->m_Height); BYTE *sd = m_pSrcImg->m_pBits; BYTE *dd = m_pDestImg->m_pBits; if(d>1) d=1; if(d<-1) d=-1; d=1+d; int i,v; BYTE colMap[256]; for(i=0;i<256;i++) { v=(INT)(i*d+0.5); if( v>255 ) v=255; colMap[i]=(BYTE)v; } for(i=0;im_ImageSize;i++) dd[i] = colMap[ sd[i] ]; return TRUE; }

***注:

(1) 以上函数中加粗的5行代码,是在后面所要实现的各图像处理函数中都需要固定写出的代码。前4行总是写在函数开始处,后1行总是写在函数结尾处。

(2) 在所有的图像处理函数中,处理得到的图像都是写入新的图像数据块中,原图像数据块的指针总是sd,新图像数据块的指针总是dd。

(3) 在编程中所需用到的图像参数变量为:

原图像的宽度:pSrcImg->m_Width;原图像的高度:pSrcImg->m_Height;原图像每行字节数:pSrcImg->m_WidthBytes;原图像数据总字节数:pSrcImg->m_ImageSize。

新图像的宽度:pDestImg->m_Width;新图像的高度:pDestImg->m_Height;新图像每行字节数:pDestImg->m_WidthBytes;新图像数据总字节数:pDestImg->m_ImageSize。

2. 建立亮度对话框,用于亮度调整参数的输入

(1) 切换到“ResourceView”选项页,展开“DIPJQ Resources”,在“Dialog”上点击右键,选中“插入Dialog”,将新建并编辑一个对话框。

(2) 右键点击对话框上的空白处,选中“属性”,在ID中输入“IDD_DIALOG_LIGHT”,在标题中输入“亮度调整参数”,点击字体按钮,将字体设为Tahoma,字体大小设为10。

(3) 添加、调整对话框上的控件至下图所示状态:

在控件工具栏上按下“静态文本”选择按钮,在对话框的适当位置拉出一个静态文本控件,在控件上点击右键—>属性,ID不变,标题输入为“亮度调整比例系数:”;添加编辑框,ID输入为“IDC_EDIT_LIGHT_D”。编辑完成后,点击保存按钮。

(4) 点击VC菜单“查看—>建立类向导”;选中“Create a new class”,点击OK;在Name编辑框中输入“CDlgLight”,点击OK,将建立CDlgLight类,并打开“MFC Class Wizard”对话框。

(5) 于“Message Maps”选项页,在“Object IDs”列表框的最后选中“IDOK”,然后在“Messages”列表框中选中“BN_CLICKED”,双击,将建立起“确定”按钮对应的消息映射函数。

(6) 切换至“Member Variables”选项页,在“Control IDs”列表框中选中“IDC_EDIT_LIGHT_D”,双击,在Member Variables Name中输入“m_LightD”,在Cagetory中选中“Value”,在Variable type中选中“int”;点击OK。在Minimum Value中输入“-100”,在Maximum Value中输入“100”。点击“确定”按钮。

3. 建立菜单

切换到“ResourceView”选项页,展开“DIPJQ resources”,展开“Menu”,双击“IDR_MAINFRAME”,对菜单进行编辑。

双击最后的空白顶层菜单,在标明编辑框中输入“颜色处理”,选中“弹出”。将该菜单拖至“查看”之后。

点击菜单“颜色处理”,双击下部空白菜单项,打开“菜单项目 属性”对话框,在ID下拉列表框中输入“ID_PROC_LIGHT”,在标明编辑框中输入“调整亮度…”,在提示编辑框中输入“调整亮度\\n亮度”。关闭对话框。

4. 建立消息映射函数

在CDIPJQDoc类中建立“调整亮度”菜单项的消息映射函数:

点击菜单“查看—>建立类向导”,在“Class Name”下拉框中选中“CDIPJQDoc”,在“Object IDs”列表框中选中“ID_PROC_LIGHT”,然后在“Message”列表框中双击“COMMAND”。

5. 在消息映射函数中添加调用代码

打开DIPJQDoc.cpp文件,在文件首部已有的#include语句之后添加一行: #include \#include \#include \

在OnProcLight()函数中加入如下代码:

void CDIPJQDoc::OnProcLight() { // TODO: Add your command handler code here CDlgLight dlg; if( dlg.DoModal()==IDOK ) { LImageProc lip; lip.m_pSrcImg = m_pCurImage; lip.m_pDestImg = m_pLastImage; float d = dlg.m_LightD/100.0; if( lip.ModifyLight(d) ) { LImage *p = m_pCurImage; m_pCurImage = m_pLastImage; m_pLastImage = p; UpdateAllViews(NULL); SetPathName(\ \ } } }

注:在之后其它的消息映射函数中,加粗的三行代码将因处理功能的不同而改变,其它各行代码

则保持不变。

6. 组建程序,运行测试

组建执行文件,排除错误,对亮度调整功能进行运行测试。在对图像进行了一次亮度调整后,可点击工具栏上的撤消按钮,将图像恢复为处理前的状态。

(二) 对比度处理

1. 在图像处理类中实现对比度处理功能

在SDImageProc.h文件中加入对比度处理函数的定义:

在LImageProc.h文件中加入对比度处理函数的定义: BOOL ImageIsValid(); //源和目标图象是否有效 BOOL ModifyLight(float d); //亮度调整,-1~1

BOOL ModifyContrast(float d); //对比度调整,-1~1

在LImageProc.cpp文件的最后,添加对比度处理函数的实现代码,如下: BOOL LImageProc:: ModifyContrast(float d) //对比度调整,-1~1 { }

if( !ImageIsValid() ) return FALSE;

m_pDestImg->Create(m_pSrcImg->m_Width, m_pSrcImg->m_Height); BYTE *sd = m_pSrcImg->m_pBits; BYTE *dd = m_pDestImg->m_pBits;

//中间部分请参照前面的亮度处理函数自行写出 return TRUE;

2. 建立对比度对话框,用于对比度调整参数的的输入

建立对比度对话框。对话框ID设为“IDD_DIALOG_CONTRAST”,对话框标题设为“对比度调整参数”;编辑框的ID设为“IDD_EDIT_CONTRAST_D”;(Ctrl+w)对话框类的名称取为“CDlgContrast”;调整参数的变量名取为“m_ContrastD”。

本文来源:https://www.bwwdw.com/article/iuz3.html

Top