您当前位置:设计在线网 >> 矢量图像技术 >> 浏览文章

引用 浅谈用VC6.0单文档进行数字图像处理(下)

分享到:
本文章讲述了引用 浅谈用VC6.0单文档进行数字图像处理(下).

2010年

08月09日

引用 彭天 的 浅谈用VC6.0单文档进行数字图像处理(下)

作者:彭天

上回书说到了,用VC6.0单文档进行数字图像处理。但是,每次都是在一个View类的派生视图类上进行显示,看不出和源图像的对比性,为此,我们可以用CSplitterWnd类来讲单文档窗口分割为两个视图类,这样,左边的视图类显示源图像,右边的视图类就可以显示处理后的图像。这样对比性就一目了然了。也就是常说的用CSplitterWnd类来实现单文档多视图(一文档多视图)的效果。为此,我们还需要对我们的DIB类做一定的修改。

1、DIB类中需要两个保存像素数据的内存,一个存放源图像的像素数据,一个存放处理后图像的像素数据。并且要为它们各自设置一个取得指针和设置其像素数据的方法。

2、在DIB类的Read函数中,同时将源图像的像素数据复制到两个保存像素数据的内存,并在析构函数中对这两块内存进行删除。

3、两个视图类之间的切换。采用的CSplitterWnd类的对象的ActiveNext函数来实现,而且在两个视图类的OnDraw函数中绘制位图。

4、DIB类需要两个画图函数,以便在不同的视图类上画图。

主要程序如下:(下载全部源程序:http://download.csdn.net/source/1217835)

我新添加的派生于CView类的派生类名为CDstView类。

void CDstView::OnDraw(CDC* pDC)

{

/* CDocument* pDoc = GetDocument();*/

// TODO: add draw code here

CMainFrame *pMain=(CMainFrame*)AfxGetApp()->m_pMainWnd;

CVampireImageDoc *pDoc=(CVampireImageDoc*)pMain->GetActiveDocument() ;

if(pDoc->GetDibInstance()->m_bRead==TRUE)

{//如果已经读入位图,则显示位图

pDoc->GetDibInstance()->Draw(pDC);

}

}

CVampireImageDoc* CDstView::GetDocument()

{//重载GetDocument方法

return (CVampireImageDoc*)m_pDocument;

}

新的DIB类的全部源程序:

// Dib.h: interface for the CDib class.

//

////////////////////////////////////////////////// ////////////////////

#if !defined(AFX_DIB_H__1065C5DA_1C47_464F_A225_AAF8D2 F15064__INCLUDED_)

#define AFX_DIB_H__1065C5DA_1C47_464F_A225_AAF8D2F15064__I NCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

class CDib

{

public:

CDib();//构造函数

virtual ~CDib();//析构函数

private:

BITMAPFILEHEADER *m_pBmfh;

BYTE *m_pBmInfo;

BYTE *m_pPixel;

BITMAPINFOHEADER *m_pBmih;

BYTE *m_pPrev;

public:

BOOL m_bRead;

public:

int Read(CString filename);

void Draw(CDC *pDC);

void DrawPrev(CDC *pDC);//显示源图像

int Write(CString filename);

public:

DWORD GetWidth() const;

DWORD GetHeight() const;

WORD GetBitCount() const;

DWORD GetLineBytes() const;

BYTE* GetPixelPointer() const;//得到目的图像的像素矩阵的指针

void SetPixelMatrix(BYTE *newPixel);//设置目的图像的像素矩阵的指针

BYTE* GetPrevPixelPointer() const;//得到源图像的像素矩阵的指针

void SetPrevPixelMatrix(BYTE *newPixel);//设置源图像的像素矩阵的指针

};

#endif // !defined(AFX_DIB_H__1065C5DA_1C47_464F_A225_AAF8D2 F15064__INCLUDED_)

// Dib.cpp: implementation of the CDib class.

//

////////////////////////////////////////////////// ////////////////////

#include "stdafx.h"

#include "VampireImage.h"

#include "Dib.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

////////////////////////////////////////////////// ////////////////////

// Construction/Destruction

////////////////////////////////////////////////// ////////////////////

CDib::CDib()

{

m_pBmfh=new BITMAPFILEHEADER;

m_pBmih=new BITMAPINFOHEADER;

m_pBmInfo=NULL;

m_pPixel=NULL;

m_pPrev=NULL;

m_bRead=FALSE;

}

CDib::~CDib()

{

if(m_pBmfh)

{

delete m_pBmfh;

m_pBmfh=NULL;

}

if(m_pBmih)

{

delete m_pBmih;

m_pBmih=NULL;

}

if(m_pBmInfo)

{

delete[] m_pBmInfo;

m_pBmInfo=NULL;

}

if(m_pPixel)

{

delete[] m_pPixel;

m_pPixel=NULL;

}

if(m_pPrev)

{

delete[] m_pPrev;

m_pPrev=NULL;

}

}

////////////////////////////////////////////////// ////////////////////

// Methods

////////////////////////////////////////////////// ////////////////////

int CDib::Read(CString filename)

{//读取位图

CFile dib;

if(!dib.Open(filename,CFile::modeRead))

{

return -1;

}

if(dib.Read(m_pBmfh,sizeof(BITMAPFILEHEADER))!=siz eof(BITMAPFILEHEADER))

{

dib.Close();

return -1;

}

m_pBmInfo=new BYTE[m_pBmfh->bfOffBits-14];

if(!m_pBmInfo)

{

dib.Close();

return -1;

}

if(dib.Read(m_pBmInfo,m_pBmfh->bfOffBits-14)!=(m_pB mfh->bfOffBits-14))

{

delete[] m_pBmInfo;

m_pBmInfo=NULL;

dib.Close();

return -1;

}

memcpy(m_pBmih,m_pBmInfo,sizeof(BITMAPINFOHEADER)) ;

WORD bitCount=m_pBmih->biBitCount;

DWORD width=m_pBmih->biWidth;

DWORD height=m_pBmih->biHeight;

DWORD lineBytes=(width*bitCount+31)/32*4;

m_pPixel=new BYTE[height*lineBytes*sizeof(BYTE)];

if(!m_pPixel)

{

dib.Close();

return -1;

}

m_pPrev=new BYTE[height*lineBytes*sizeof(BYTE)];

if(!m_pPrev)

{

dib.Close();

return -1;

}

if(dib.Read(m_pPixel,height*lineBytes*sizeof(BYTE) )!=(height*lineBytes*sizeof(BYTE)))

{

dib.Close();

delete[] m_pBmInfo;

m_pBmInfo=NULL;

delete[] m_pPixel;

m_pPixel=NULL;

return -1;

}

dib.Close();

m_bRead=TRUE;

memcpy(m_pPrev,m_pPixel,height*lineBytes*sizeof(BY TE));

return 0;

}

int CDib::Write(CString filename)

{//写出位图

CFile dib;

if(!dib.Open(filename,CFile::modeWrite | CFile::modeCreate | CFile::typeBinary))

{

return -1;

}

dib.Write(m_pBmfh,sizeof(BITMAPFILEHEADER));

dib.Write(m_pBmInfo,m_pBmfh->bfOffBits-14);

dib.Write(m_pPixel,GetHeight()*GetLineBytes()*size of(BYTE));

dib.Close();

return 0;

}

void CDib::Draw(CDC *pDC)

{//显示目的图像

DWORD width=GetWidth();

DWORD height=GetHeight();

StretchDIBits(pDC->m_hDC,0,0,width,height,0,0,width ,height,m_pPixel,(BITMAPINFO*)m_pBmInfo,DIB_RGB_COL ORS,SRCCOPY);

}

void CDib::DrawPrev(CDC *pDC)

{//显示源图像

DWORD width=GetWidth();

DWORD height=GetHeight();

StretchDIBits(pDC->m_hDC,0,0,width,height,0,0,width ,height,m_pPrev,(BITMAPINFO*)m_pBmInfo,DIB_RGB_COLO RS,SRCCOPY);

}

////////////////////////////////////////////////// ////////////////////

// Get/Set Functions

////////////////////////////////////////////////// ////////////////////

WORD CDib::GetBitCount() const

{

return m_pBmih->biBitCount;

}

DWORD CDib::GetWidth() const

{

return m_pBmih->biWidth;

}

DWORD CDib::GetHeight() const

{

return m_pBmih->biHeight;

}

DWORD CDib::GetLineBytes() const

{

return (GetWidth()*GetBitCount()+31)/32*4;

}

BYTE* CDib::GetPixelPointer() const

{

return m_pPixel;

}

void CDib::SetPixelMatrix(BYTE *newPixel)

{

delete[] m_pPixel;

m_pPixel=NULL;

m_pPixel=new BYTE[GetHeight()*GetLineBytes()];

if(!m_pPixel)

{

return;

}

memcpy(m_pPixel,newPixel,GetHeight()*GetLineBytes( ));

}

BYTE* CDib::GetPrevPixelPointer() const

{

return m_pPrev;

} void CDib::SetPrevPixelMatrix(BYTE *newPixel)

{

delete[] m_pPrev;

m_pPrev=NULL;

m_pPrev=new BYTE[GetHeight()*GetLineBytes()];

if(!m_pPrev)

{

return;

}

memcpy(m_pPrev,newPixel,GetHeight()*GetLineBytes() );

} 在MainFrame类中添加如下成员变量:

protected:// control bar embedded members

CStatusBarm_wndStatusBar;

CToolBarm_wndToolBar;

CSplitterWnd m_wndSplitter;

在MainFrame类的OnCreateClient函数中的程序:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

// TODO: Add your specialized code here and/or call the base class

CRect rc;

GetClientRect(&rc);

m_wndSplitter.CreateStatic(this,1,2);//分割窗口

m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CVampir eImageView),CSize(rc.Width()/2-16,rc.Height()/2-16) ,pContext);

m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CDstVie w),CSize(rc.Width()/2-16,rc.Height()/2-16),pContext );

return TRUE;//必须返回TRUE,否则不能显示分割后的窗口

/* return CFrameWnd::OnCreateClient(lpcs, pContext);*/

}

转化为灰度的程序:

void CMainFrame::OnGrayimage()

{

// TODO: Add your command handler code here

CVampireImageDoc *pDoc=(CVampireImageDoc*)this->GetActiveDocument();

if(pDoc->GetDibInstance()->m_bRead==FALSE)

{//如果还没有读入位图,则返回

return;

}

DWORD width=(pDoc->GetDibInstance())->GetWidth();

DWORD height=(pDoc->GetDibInstance())->GetHeight();

WORD bitCount=(pDoc->GetDibInstance())->GetBitCount();

DWORD lineBytes=(pDoc->GetDibInstance())->GetLineBytes();

BYTE *dib=(pDoc->GetDibInstance())->GetPrevPixelPointer() ;//得到源图像的像素矩阵的指针

BYTE *newDib=new BYTE[height*lineBytes];

if(!newDib)

{

return;

}

memcpy(newDib,dib,height*lineBytes);//拷贝至新分配的内存

if(bitCount==8)

{

AfxMessageBox("已经是8位的灰度图了,没有必要再转换。");

delete[] newDib;

newDib=NULL;

return;

}

else if(bitCount==24)

{

for(DWORD i=0;i=255) avg=255;

*(newDib+lineBytes*(height-1-i)+n)=(BYTE)avg;

n++;

*(newDib+lineBytes*(height-1-i)+n)=(BYTE)avg;

n++;

*(newDib+lineBytes*(height-1-i)+n)=(BYTE)avg;

}

}

}

else

{

AfxMessageBox("暂时只支持8或24位位图.");

delete[] newDib;

newDib=NULL;

return;

}

pDoc->GetDibInstance()->SetPixelMatrix(newDib);//设置目的图像的像素矩阵

delete[] newDib;

newDib=NULL;

m_wndSplitter.ActivateNext();//激活CDstView的CSplitterWnd的窗口

CDstView* pView=(CDstView*)this->GetActiveView();//获得CDstView的指针

pView->OnDraw(pView->GetDC());//将目的图像画到CDstView的CSplitterWnd窗口中

m_wndSplitter.ActivateNext();//还原CVampireImageView为激活的窗口

}

转化为二值化的程序:

void CMainFrame::OnBinaryimage()

{

// TODO: Add your command handler code here

CVampireImageDoc *pDoc=(CVampireImageDoc*)this->GetActiveDocument();

if(pDoc->GetDibInstance()->m_bRead==FALSE)

{

return;

}

DWORD width=(pDoc->GetDibInstance())->GetWidth();

DWORD height=(pDoc->GetDibInstance())->GetHeight();

WORD bitCount=(pDoc->GetDibInstance())->GetBitCount();

DWORD lineBytes=(pDoc->GetDibInstance())->GetLineBytes();

BYTE *dib=(pDoc->GetDibInstance())->GetPrevPixelPointer() ;

BYTE *newDib=new BYTE[height*lineBytes];

if(!newDib)

{

return;

}

memcpy(newDib,dib,height*lineBytes);

if(bitCount==8)

{

for(DWORD i=0;i128)

{

*(newDib+lineBytes*(height-1-i)+j)=255;

}

else

{

*(newDib+lineBytes*(height-1-i)+j)=0;

}

}

}

}

else if(bitCount==24)

{

for(DWORD i=0;i128) avg=255;

if(avgGetDibInstance()->SetPixelMatrix(newDib);

delete[] newDib;

newDib=NULL;

m_wndSplitter.ActivateNext();

CDstView *pView=(CDstView*)this->GetActiveView();

pView->OnDraw(pView->GetDC());

m_wndSplitter.ActivateNext();

}

运行效果:

点击浏览下一页

推荐阅读:
VC编程实现数字图像的边缘检测
VC++中调用matlab函数(调用engine)
VC++和VC++.net中与图像处理有关的几个概念、结构和类
推荐文章  
赞助商链接  
热门排行  
主题推广  
中国设计在线网 All Rights Reserved. 互联网违法和不良信息举报
信息产业部备案号:湘ICP备09001063号