请教vc++高手讲解一下下面的图像处理程序

请教vc++高手讲解一下下面的图像处理程序,第1张

.旋转图像(含对话框 这里对话框需要自己建立) void CCimageProcessingView::OnGeomRota() { //获取指向文档的指针 CCimageProcessingDoc* pDoc = GetDocument()//指向DIB的指针 LPSTR lpDIB//锁定DIB lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB())// 缩放比率 int iRotaAngle// 创建对话框 CDlgGeoRota dlgPara// 初始化变量值 dlgPara.m_iRotaAngle = 90// 显示对话框,提示用户设定旋转角度 if (dlgPara.DoModal() != IDOK) { // 返回 return} // 获取用户设定的平移量 iRotaAngle = dlgPara.m_iRotaAngle// 删除对话框 delete dlgPara//创建新DIB HDIB hNewDIB=NULL//设置光标状态为等待状态 BeginWaitCursor()//调用RotateDIB函数旋转DIB图象 hNewDIB=(HDIB)::RotateDIB(lpDIB,iRotaAngle)//旋转成功 if (hNewDIB) { //替换原来的DIB图象为新的DIB pDoc->ReplaceHDIB(hNewDIB)//更新DIB图象的大小和调色板 pDoc->InitDIBData()//设置文档修改标记 pDoc->SetModifiedFlag(TRUE)//调节滚动视图大小 SetScrollSizes(MM_TEXT,pDoc->GetDocSize())//更新所有视图 pDoc->UpdateAllViews(NULL)} else { //提示信息 MessageBox("实现图象旋转失败!")} //解除锁定 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB())//结束光标等待状态 EndWaitCursor()} /************************************************************************* * * 函数名称: * * RotateDIB () * * 参数: * * LPSTR lpDIB //指向源DIB图像指针 * * int iAngle * 说明: * * 该函数用来实现DIB图像的旋转。 * ************************************************************************/ HGLOBAL WINAPI RotateDIB(LPSTR lpDIB,int iAngle) { //原图象宽度 LONG lWidth//原图象高度 LONG lHeight//旋转后图象宽度 LONG lNewWidth//旋转后图象高度 LONG lNewHeight//原图象的颜色数 WORD wNumColors//原图象的信息头结构指针 LPBITMAPINFOHEADER lpbmi,lpbmi0//指向原图象和目的图象的像素的指针 LPBYTE lpSrc,lpDst//指向原图像像素的指针 LPBYTE lpDIBBits//指向旋转后图像(像素)的指针 LPBYTE lpNewDIBBitsLPSTR lpNewDIB//旋转后新的DIB句柄 HDIB hDIB

打开VC程序——文件——新建——工程中的MFC AppWizard(exe),在工程下面的框中输入工程名(假定工程名为111),点确定——选多重文档,点下一个——后面都点下一个直到完成确定,基本框架就完成了,下面就加代码

这时VC界面上左边框的下面有三个按钮:ClassView、ResourceView和FileView,ClassView里面是工程111的类:CAdoutDlg、CChildFrame、CMy111App、CMy111Doc、CMy111View和Globals;点ResourceView里面是资源类:Accelerator、Dialog、Icon、Menu、String Table、Toolbar和Version;点开FileView里面是文件类:Source File、Header Files、Resource Files和ReadMe.txt。

点界面的“工程”按钮——添加工程——新建——选C++ Source File,在文件下面的框里输入文件名(如DIBAPI),点“结束”,这样在FileView中的Source Files里面就多了一个DIBAPI.cpp文件,所有的代码都加在该文件中。再点界面的“工程”按钮——添加工程——新建——选C/C++ Header File,在文件下面的框里输入文件名(和前面的文件名必须一致),点“结束”,这样在FileView中的Header Files里面就多了一个DIBAPI.h文件,该文件是DIBAPI.cpp的头文件。

点开DIBAPI.h文件,里面是空白的,把如下代码考入文件中:

//DIBAPI.h

#ifndef _INC_DIBAPI

#define _INC_DIBAPI

DECLARE_HANDLE(HDIB)

#define PALVERSION 0x300

#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi))==sizeof(BITMAPINFOHEADER))

#define RECTWIDTH(lpRect) ((lpRect)->right-(lpRect)->left)

#define RECTHEIGHT(lpRect) ((lpRect)->bottom-(lpRect)->top)

#define WIDTHBYTES(bits) (((bits)+31)/32*4)

#define DIB_HEADER_MARKER ((WORD)('M'<<8)|'B')

BOOL WINAPI PaintDIB(HDC,LPRECT,HDIB,LPRECT,CPalette* pPal)

BOOL WINAPI CreateDIBPalette(HDIB hDIB,CPalette* cPal)

LPSTR WINAPI FindDIBBits(LPSTR lpbi)

DWORD WINAPI DIBWidth(LPSTR lpDIB)

DWORD WINAPI DIBHeight(LPSTR lpDIB)

WORD WINAPI PaletteSize(LPSTR lpbi)

WORD WINAPI DIBNumColors(LPSTR lpbi)

HGLOBAL WINAPI CopyHandle(HGLOBAL h)

BOOL WINAPI SaveDIB(HDIB hDib,CFile&file)

HDIB WINAPI ReadDIBFile(CFile&file)

//在此处输入自己的函数声明

#endif//!_INC_DIBAPI

上面这些函数是实现图像的读取、存储等图像处理的基本功能的,你将自己需要的函数也输入到“//在此处输入自己的函数声明”的下面。

点开DIBAPI.cpp文件,里面是空白的,将如下代码加入其中:

//DIBAPI.cpp

#include "stdafx.h"

#include "DIBAPI.h"

WORD WINAPI DIBNumColors(LPSTR lpbi)

{

WORD wBitCount

if(IS_WIN30_DIB(lpbi))

{

DWORD dwClrUsed

dwClrUsed=((LPBITMAPINFOHEADER)lpbi)->biClrUsed

if(dwClrUsed)

return (WORD)dwClrUsed

}

if(IS_WIN30_DIB(lpbi))

wBitCount=((LPBITMAPINFOHEADER)lpbi)->biBitCount

else

wBitCount=((LPBITMAPCOREHEADER)lpbi)->bcBitCount

switch(wBitCount)

{

case 1:

return 2

case 4:

return 16

case 8:

return 256

default:

return 0

}

}

WORD WINAPI PaletteSize(LPSTR lpbi)

{

if(IS_WIN30_DIB(lpbi))

return (WORD)(DIBNumColors(lpbi)*sizeof(RGBQUAD))

else

return (WORD)(DIBNumColors(lpbi)*sizeof(RGBTRIPLE))

}

LPSTR WINAPI FindDIBBits(LPSTR lpbi)

{

return (lpbi+*(LPDWORD)lpbi+::PaletteSize(lpbi))

}

DWORD WINAPI DIBWidth(LPSTR lpDIB)

{

LPBITMAPINFOHEADER lpbmi

LPBITMAPCOREHEADER lpbmc

lpbmi=(LPBITMAPINFOHEADER)lpDIB

lpbmc=(LPBITMAPCOREHEADER)lpDIB

if(IS_WIN30_DIB(lpDIB))

return lpbmi->biWidth

else

return (DWORD)lpbmc->bcWidth

}

DWORD WINAPI DIBHeight(LPSTR lpDIB)

{

LPBITMAPINFOHEADER lpbmi

LPBITMAPCOREHEADER lpbmc

lpbmi=(LPBITMAPINFOHEADER)lpDIB

lpbmc=(LPBITMAPCOREHEADER)lpDIB

if(IS_WIN30_DIB(lpDIB))

return lpbmi->biHeight

else

return (DWORD)lpbmc->bcHeight

}

BOOL WINAPI PaintDIB(HDC hDC,LPRECT lpDCRect,HDIB hDIB,LPRECT lpDIBRect,CPalette* pPal)

{

LPSTR lpDIBHdr

LPSTR lpDIBBits

BOOL bSuccess=FALSE

HPALETTE hPal=NULL

HPALETTE hOldPal=NULL

if(hDIB==NULL)

return FALSE

lpDIBHdr=(LPSTR)::GlobalLock((HGLOBAL)hDIB)

lpDIBBits=FindDIBBits(lpDIBHdr)

if(pPal!=NULL)

{

hPal=(HPALETTE)pPal->m_hObject

hOldPal=::SelectPalette(hDC,hPal,TRUE)

}

::SetStretchBltMode(hDC,COLORONCOLOR)

if((RECTWIDTH(lpDCRect)==RECTWIDTH(lpDIBRect))&&(RECTHEIGHT(lpDCRect)==RECTHEIGHT(lpDIBRect)))

{

bSuccess=::SetDIBitsToDevice(hDC,lpDCRect->left,lpDCRect->top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect->left,\

(int)DIBHeight(lpDIBHdr)-lpDIBRect->top-RECTHEIGHT(lpDIBRect),0,(WORD)DIBHeight(lpDIBHdr),\

lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS)

}

else

{

bSuccess=::StretchDIBits(hDC,lpDCRect->left,lpDCRect->top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect->left,\

lpDIBRect->top,RECTWIDTH(lpDIBRect),RECTHEIGHT(lpDIBRect),\

lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY)

}

::GlobalUnlock((HGLOBAL)hDIB)

if(hOldPal)

::SelectPalette(hDC,hOldPal,TRUE)

GlobalUnlock(hDIB)

return bSuccess

}

BOOL WINAPI CreateDIBPalette(HDIB hDIB,CPalette* pPal)

{

LPLOGPALETTE lpPal

HANDLE hLogPal

HPALETTE hPal=NULL

LPSTR lpbi

LPBITMAPINFO lpbmi

LPBITMAPCOREINFO lpbmc

BOOL bWinStyleDIB

int i

WORD wNumColors

BOOL bResult=FALSE

if(hDIB==NULL)

return FALSE

lpbi=(LPSTR)::GlobalLock((HGLOBAL)hDIB)

lpbmi=(LPBITMAPINFO)lpbi

lpbmc=(LPBITMAPCOREINFO)lpbi

wNumColors=DIBNumColors(lpbi)

bWinStyleDIB=IS_WIN30_DIB(lpbi)

if(wNumColors!=0)

{

hLogPal=::GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*wNumColors)

if(hLogPal==0)

{

::GlobalUnlock((HGLOBAL)hDIB)

return FALSE

}

lpPal=(LPLOGPALETTE)::GlobalLock(hLogPal)

lpPal->palVersion=PALVERSION

lpPal->palNumEntries=(WORD)wNumColors

bWinStyleDIB=IS_WIN30_DIB(lpbi)

for(i=0i<(int)wNumColorsi++)

{

if(bWinStyleDIB)

{

lpPal->palPalEntry[i].peRed=lpbmi->bmiColors[i].rgbRed

lpPal->palPalEntry[i].peGreen=lpbmi->bmiColors[i].rgbGreen

lpPal->palPalEntry[i].peBlue=lpbmi->bmiColors[i].rgbBlue

lpPal->palPalEntry[i].peFlags=0

}

else

{

lpPal->palPalEntry[i].peRed=lpbmc->bmciColors[i].rgbtRed

lpPal->palPalEntry[i].peGreen=lpbmc->bmciColors[i].rgbtGreen

lpPal->palPalEntry[i].peBlue=lpbmc->bmciColors[i].rgbtBlue

lpPal->palPalEntry[i].peFlags=0

}

}

bResult=pPal->CreatePalette(lpPal)

::GlobalUnlock((HGLOBAL)hLogPal)

::GlobalFree((HGLOBAL)hLogPal)

}

::GlobalUnlock((HGLOBAL)hDIB)

return bResult

}

HGLOBAL WINAPI CopyHandle(HGLOBAL h)

{

if(h==NULL)

return NULL

DWORD dwLen=::GlobalSize((HGLOBAL)h)

HGLOBAL hCopy=::GlobalAlloc(GHND,dwLen)

if(hCopy!=NULL)

{

void* lpCopy=::GlobalLock((HGLOBAL)hCopy)

void* lp=::GlobalLock((HGLOBAL)h)

memcpy(lpCopy,lp,dwLen)

::GlobalUnlock(hCopy)

::GlobalUnlock(h)

}

return hCopy

}

BOOL WINAPI SaveDIB(HDIB hDib,CFile&file)

{

BITMAPFILEHEADER bmfHdr

LPBITMAPINFOHEADER lpBI

DWORD dwDIBSize

if(!hDib)

return FALSE

lpBI=(LPBITMAPINFOHEADER)::GlobalLock((HGLOBAL)hDib)

if(lpBI==NULL)

return FALSE

if(!IS_WIN30_DIB(lpBI))

{

::GlobalUnlock((HGLOBAL)hDib)

return FALSE

}

bmfHdr.bfType=DIB_HEADER_MARKER

dwDIBSize=*(LPDWORD)lpBI+::PaletteSize((LPSTR)lpBI)

if((lpBI->biCompression==BI_RLE8)||(lpBI->biCompression==BI_RLE4))

dwDIBSize+=lpBI->biSizeImage

else

{

DWORD dwBmBitsSize

dwBmBitsSize=WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount))*lpBI->biHeight

dwDIBSize+=dwBmBitsSize

lpBI->biSizeImage=dwBmBitsSize

}

bmfHdr.bfSize=dwDIBSize+sizeof(BITMAPFILEHEADER)

bmfHdr.bfReserved1=0

bmfHdr.bfReserved2=0

bmfHdr.bfOffBits=(DWORD)sizeof(BITMAPFILEHEADER)+lpBI->biSize+::PaletteSize((LPSTR)lpBI)

TRY

{

file.Write((LPSTR)&bmfHdr,sizeof(BITMAPFILEHEADER))

file.WriteHuge(lpBI,dwDIBSize)

}

CATCH(CFileException,e)

{

::GlobalUnlock((HGLOBAL)hDib)

THROW_LAST()

}

END_CATCH

::GlobalUnlock((HGLOBAL)hDib)

return TRUE

}

HDIB WINAPI ReadDIBFile(CFile&file)

{

BITMAPFILEHEADER bmfHeader

DWORD dwBitsSize

HDIB hDIB

LPSTR pDIB

dwBitsSize=file.GetLength()

if(file.Read((LPSTR)&bmfHeader,sizeof(bmfHeader))!=sizeof(bmfHeader))

return NULL

if(bmfHeader.bfType!=DIB_HEADER_MARKER)

return NULL

hDIB=(HDIB)::GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,dwBitsSize)

if(hDIB==0)

return NULL

pDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB)

if(file.ReadHuge(pDIB,dwBitsSize-sizeof(BITMAPFILEHEADER))!=dwBitsSize-sizeof(BITMAPFILEHEADER))

{

::GlobalUnlock((HGLOBAL)hDIB)

::GlobalFree((HGLOBAL)hDIB)

return NULL

}

::GlobalUnlock((HGLOBAL)hDIB)

return hDIB

}

//在此处输入自己的函数定义

上面是DIBAPI.h头文件中声明的函数的定义,你将自己的函数定义加到“//在此处输入自己的函数定义”后面。

下面加相应的消息映射函数,点Ctrl+W键,会出现MFC ClassWizard对话框,点Message Maps,在Class name下面的框中选择CMy111Doc,在Messages里面选中OnOpenDocument,然后点击Add Function按钮就加入了相应的消息映射函数,同样的方法以此加入OnSaveDocument、DeleteContents、CanCloseFrame相应的消息函数,点“确定”即可。

点开111Doc.cpp文件,里面有相应的消息映射函数定义位置,在函数CMy111Doc::CMy111Doc()里输入以下代码:

m_refColorBKG=0x00808080

m_hDIB=NULL

m_palDIB=NULL

m_sizeDoc=CSize(1,1)

在函数CMy111Doc::~CMy111Doc()里输入以下代码:

if(m_hDIB!=NULL)

::GlobalFree((HGLOBAL)m_hDIB)

if(m_palDIB!=NULL)

delete m_palDIB

在函数BOOL CMy111Doc::OnOpenDocument(LPCTSTR lpszPathName)里/ TODO: Add your specialized creation code here下面添加如下代码:

CFile file

CFileException fe

if(!file.Open(lpszPathName,CFile::modeRead|CFile::shareDenyWrite,&fe))

{

ReportSaveLoadException(lpszPathName,&fe,FALSE,AFX_IDP_FAILED_TO_OPEN_DOC)

return FALSE

}

DeleteContents()

BeginWaitCursor()

TRY

{

m_hDIB=::ReadDIBFile(file)

}

CATCH(CFileException,eLoad)

{

file.Abort()

EndWaitCursor()

ReportSaveLoadException(lpszPathName,eLoad,FALSE,AFX_IDP_FAILED_TO_OPEN_DOC)

m_hDIB=NULL

return FALSE

}

END_CATCH

InitDIBData()

EndWaitCursor()

if(m_hDIB==NULL)

{

CString strMsg

strMsg="读取图像时出错!可能是不支持该类型的图像文件!"

MessageBox(NULL,strMsg,NULL,MB_ICONINFORMATION|MB_OK)

return FALSE

}

SetPathName(lpszPathName)

SetModifiedFlag(FALSE)

在函数BOOL CMy111Doc::OnSaveDocument(LPCTSTR lpszPathName)里// TODO: Add your specialized code here and/or call the base class后面添加如下代码:

CFile file

CFileException fe

if(!file.Open(lpszPathName,CFile::modeCreate|CFile::modeReadWrite|CFile::shareExclusive,&fe))

{

ReportSaveLoadException(lpszPathName,&fe,TRUE,AFX_IDP_INVALID_FILENAME)

return FALSE

}

BOOL bSuccess=FALSE

TRY

{

BeginWaitCursor()

bSuccess=::SaveDIB(m_hDIB,file)

file.Close()

}

CATCH(CException,eSave)

{

file.Abort()

EndWaitCursor()

ReportSaveLoadException(lpszPathName,eSave,TRUE,AFX_IDP_FAILED_TO_SAVE_DOC)

return FALSE

}

END_CATCH

EndWaitCursor()

SetModifiedFlag(FALSE)

if(!bSuccess)

{

CString strMsg

strMsg="无法保存BMP图像"

MessageBox(NULL,strMsg,NULL,MB_ICONINFORMATION|MB_OK)

}

点开ClassView,右键点击CMy111Doc类,点Add Member Variable出现添加成员变量对话框,在Variable Type下的框中输入变量类型名HDIB,在Variable Name中输入变量名m_hDIB,在Access中选中Public就在CMy111Doc中加入了公共成员变量m_hDIB;同样加入int类型的m_nColorIndex、COLORREF类型的m_refColorBKG公共成员变量,再添加保护成员变量(在Access中选中Protected)CSize类的m_sizeDoc、CPalette*类的m_palDIB变量。右键点击CMy111Doc类,点Add Member Function出现添加成员函数对话框,在Function Type下的框中输入函数类型名void,在Function Declaration中输入函数名InitDIBData(),在Access中选中Public就在CMy111Doc中加入了公共成员函数InitDIBData();同样方法加入void类型的公共成员函数ReplaceHDIB(HDIB hDIB)。在111Doc.cpp中加入函数的代码,InitDIBData()里加如下代码:

if(m_palDIB!=NULL)

{

delete m_palDIB

m_palDIB=NULL

}

if(m_hDIB==NULL)

return

LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)m_hDIB)

if(::DIBWidth(lpDIB)>INT_MAX||::DIBHeight(lpDIB)>INT_MAX)

{

::GlobalUnlock((HGLOBAL)m_hDIB)

::GlobalFree((HGLOBAL)m_hDIB)

m_hDIB=NULL

CString strMsg

strMsg="BMP图像太大!"

MessageBox(NULL,strMsg,NULL,MB_ICONINFORMATION|MB_OK)

return

}

m_sizeDoc=CSize((int)::DIBWidth(lpDIB),(int)::DIBHeight(lpDIB))

::GlobalUnlock((HGLOBAL)m_hDIB)

m_palDIB=new CPalette

if(m_palDIB==NULL)

{

::GlobalFree((HGLOBAL)m_hDIB)

m_hDIB=NULL

return

}

if(::CreateDIBPalette(m_hDIB,m_palDIB)==NULL)

{

delete m_palDIB

m_palDIB=NULL

return

}

在函数ReplaceHDIB(HDIB hDIB)中加入如下代码:

if(m_hDIB!=NULL)

::GlobalFree((HGLOBAL)m_hDIB)

m_hDIB=hDIB

在CMy111doc.h的

// Attributes

public:

下面加入如下代码:

HDIB GetHDIB() const

{

return m_hDIB

}

CPalette* GetDocPalette() const

{

return m_palDIB

}

CSize GetDocSize() const

{

return m_sizeDoc

}

注意要在111Doc.h前加上#include "DIBAPI.h"语句(在class CMy111Doc:public CDocument语句前)

下面为CMy111View中的函数 void CMy111View::OnDraw(CDC* pDC)中添加如下代码:

BeginWaitCursor()

CMy111* pDoc = GetDocument()

ASSERT_VALID(pDoc)

// TODO: add draw code for native data here

HDIB hDIB=pDoc->GetHDIB()

if(hDIB!=NULL)

{

LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB)

int cxDIB=(int)::DIBWidth(lpDIB)

int cyDIB=(int)::DIBHeight(lpDIB)

::GlobalUnlock((HGLOBAL)hDIB)

CRect rcDIB

rcDIB.top=rcDIB.left=0

rcDIB.right=cxDIB

rcDIB.bottom=cyDIB

CRect rcDest

if(pDC->IsPrinting())

{

int cxPage=pDC->GetDeviceCaps(HORZRES)

int cyPage=pDC->GetDeviceCaps(VERTRES)

int cxInch=pDC->GetDeviceCaps(LOGPIXELSX)

int cyInch=pDC->GetDeviceCaps(LOGPIXELSY)

rcDest.top=rcDest.left=0

rcDest.bottom=(int)(((double)cyDIB*cxPage*cyInch)/((double)cxDIB*cxInch))

rcDest.right=cxPage

int temp=cyPage-(rcDest.bottom-rcDest.top)

rcDest.bottom+=temp/2

rcDest.top+=temp/2

}

else

{

rcDest=rcDIB

}

::PaintDIB(pDC->m_hDC,&rcDest,pDoc->GetHDIB(),&rcDIB,pDoc->GetDocPalette())

}

EndWaitCursor()

以上是关于图像打开、显示、保存的有关步骤和代码。

在111.cpp文件的InitInstance()函数的ParseCommandLine(cmdInfo)语句下输入语句

cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing

则启动时不自动打开一个空文档。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11343569.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存