📄 imageprocessview.cpp
字号:
// ImageProcessView.cpp : implementation of the CImageProcessView class
//
#include "stdafx.h"
#include "ImageProcess.h"
#include "ImageProcessDoc.h"
#include "ImageProcessView.h"
#include "mainfrm.h"
#include "DlgHuffman.h"
#include "DlgRatio.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CImageProcessView
IMPLEMENT_DYNCREATE(CImageProcessView, CScrollView)
BEGIN_MESSAGE_MAP(CImageProcessView, CScrollView)
//{{AFX_MSG_MAP(CImageProcessView)
ON_COMMAND(ID_CODE_HUFFMAN, OnCodeHuffman)
ON_COMMAND(ID_CODE_DEHUFFMAN, OnCodeDehuffman)
//}}AFX_MSG_MAP
// Standard printing commands
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CImageProcessView construction/destruction
CImageProcessView::CImageProcessView()
{
// TODO: add construction code here
}
CImageProcessView::~CImageProcessView()
{
}
BOOL CImageProcessView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CScrollView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CImageProcessView drawing
void CImageProcessView::OnDraw(CDC* pDC)
{
BeginWaitCursor( );
CImageProcessDoc* 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*cyInch));
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( );
}
void CImageProcessView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
// TODO: calculate the total size of this view
sizeTotal.cx = sizeTotal.cy = 100;
SetScrollSizes(MM_TEXT, sizeTotal);
}
/////////////////////////////////////////////////////////////////////////////
// CImageProcessView diagnostics
#ifdef _DEBUG
void CImageProcessView::AssertValid() const
{
CScrollView::AssertValid();
}
void CImageProcessView::Dump(CDumpContext& dc) const
{
CScrollView::Dump(dc);
}
CImageProcessDoc* CImageProcessView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageProcessDoc)));
return (CImageProcessDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CImageProcessView message handlers
BOOL CImageProcessView::OnEraseBkgnd(CDC *pDC)
{ CImageProcessDoc *pDoc=GetDocument();
CBrush brush(pDoc->m_refColorBKG);
CBrush *pOldBrush=pDC->SelectObject(&brush);
CRect rectClip;
pDC->GetClipBox(&rectClip);
pDC->PatBlt(rectClip.left,rectClip.top,rectClip.Width(),rectClip.Height(),PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;
}
LRESULT CImageProcessView::OnDoRealize(WPARAM wParam,LPARAM lParam)
{ ASSERT(wParam!=NULL);
CImageProcessDoc *pDoc=GetDocument( );
if(pDoc->GetHDIB()==NULL)
{ return 0L;
}
CPalette *pPal=pDoc->GetDocPalette();
if(pPal!=NULL)
{ CMainFrame *pAppFrame=(CMainFrame *)AfxGetApp()->m_pMainWnd;
ASSERT_KINDOF(CMainFrame,pAppFrame);
CClientDC appDC(pAppFrame);
CPalette *oldPalette=appDC.SelectPalette(pPal,((HWND)wParam)!=m_hWnd);
if(oldPalette!=NULL)
{ UINT nColorsChanged=appDC.RealizePalette( );
if(nColorsChanged>0)
pDoc->UpdateAllViews(NULL);
appDC.SelectPalette(oldPalette,TRUE);
}
else
{ TRACE0("\tCImageProcessView::OnPaletteChanged中调用SelectPalette()失败!\n");
}
}
return 0L;
}
void CImageProcessView::CalcWindowRect(LPRECT lpClientRect,UINT nAdjustType)
{ CScrollView::OnInitialUpdate ();
ASSERT((GetDocument)!=NULL);
SetScrollSizes(MM_TEXT,GetDocument()->GetDocSize());
}
void CImageProcessView::OnActivateView(BOOL bActivate,CView *pActivateView,
CView *pDeactiveView)
{ CScrollView::OnActivateView(bActivate,pActivateView,pDeactiveView);
if(bActivate)
{ ASSERT(pActivateView==this);
OnDoRealize((WPARAM) m_hWnd,0);
}
}
void CImageProcessView::OnCodeHuffman()
{
CImageProcessDoc *pDoc=GetDocument( ); //获取文档
BYTE * lpSrc; //指向源图像像素的指针
LPSTR lpDIB; //指向DIB的指针
LPSTR lpDIBBits; //指向DIB像素的指针
long lHeight; //DIB的高度
long lWidth; //DIB的宽度
long lLineBytes; //图像每行的字节数
long lCountSum; //图像像素总数
long i; //循环变量
long j;
float *fFreq; //保存各个灰度值频率的数组指针
int iColorNum; //获取当前DIB颜色数目
int ActualColorNum=0; //获取当前DIB实际的颜色数目
lpDIB= (LPSTR)::GlobalLock((HGLOBAL) pDoc->GetHDIB());
if(lpDIB==NULL)
return;
lpDIBBits=::FindDIBBits(lpDIB);
iColorNum=::DIBNumColors(lpDIB);
//判断是否是8-bpp位图
if(iColorNum!=256)
{ MessageBox("目前只支持256级灰度位图哈夫曼编码!","系统提示",
MB_ICONINFORMATION | MB_OK);
::GlobalUnlock((HGLOBAL)pDoc->GetHDIB());
return;
}
BeginWaitCursor( );
fFreq=new float[2*iColorNum];
lWidth=::DIBWidth(lpDIB);
lHeight=::DIBHeight(lpDIB);
lLineBytes=WIDTHBYTES(lWidth*8);
for(i=0;i<iColorNum;i++)
fFreq[i]=0.0;
for(i=0;i<lHeight;i++) //计算各个灰度值的计数
for(j=0;j<lWidth;j++)
{ lpSrc=(BYTE *)lpDIBBits+lLineBytes*i+j;
fFreq[*(lpSrc)]++;
}
for(i=0;i<iColorNum;i++)
if(fFreq[i]>0)
ActualColorNum++;
lCountSum=lHeight*lWidth;
for(i=0;i<iColorNum;i++) //计算各个灰度值出现的概率
fFreq[i]/=(float)lCountSum;
//计算各个灰度值出现的概率结束
//**************************************************
//创建对话框
CDlgHuffman dlgPara;
dlgPara.m_fFreq =new HuffmanTree [2*ActualColorNum];
int temp=1;
for(i=1;i<=iColorNum;i++)
if(fFreq[i-1]>0)
{ dlgPara.m_fFreq[temp].freq=fFreq[i-1];
dlgPara.m_fFreq[temp].GrayValue=i-1;
temp++;
}
for(i=0;i<=2*ActualColorNum;i++)
{ dlgPara.m_fFreq[i].lchild =0;
dlgPara.m_fFreq[i].rchild =0;
dlgPara.m_fFreq[i].parent =0;
}
for(i=ActualColorNum+1;i<2*ActualColorNum;i++)
dlgPara.m_fFreq[i].freq =0.0;
dlgPara.m_iColorNum=ActualColorNum;
dlgPara.m_height=(unsigned int)lHeight;
dlgPara.m_width=(unsigned int)lWidth;
dlgPara.m_lpDIB=lpDIB;
dlgPara.m_lpDIBBits=lpDIBBits;
dlgPara.m_lLineBytes=lLineBytes;
dlgPara.DoModal();
//以下对图象进行编码并存入文件
char szFilters[]="*.huf";//选择需要写入的文件
CString PathName; //选择文件的路径
CFile ImageFile; //文件对象
unsigned int p,q,k;
HUFHEADER hufHdr; //以下为准备写入的*.huf文件头
hufHdr.wManufacturer =HUF_HEADER_MARKER;
hufHdr.bVersion =0x0001;
hufHdr.wHeight =dlgPara.m_height;
hufHdr.wWidth =dlgPara.m_width;
hufHdr.wItemNum =2*dlgPara.m_iColorNum;
hufHdr.wReserved =0x0000;
HUFCODEBOOK *hufCodeBk;
hufCodeBk=new HUFCODEBOOK [2*dlgPara.m_iColorNum];//以下为编码本的准备
for(p=0;p<2*dlgPara.m_iColorNum;p++)
{ hufCodeBk[p].GrayValue =dlgPara.m_fFreq[p].GrayValue ;
hufCodeBk[p].lchild=dlgPara.m_fFreq[p].lchild ;
hufCodeBk[p].rchild=dlgPara.m_fFreq[p].rchild ;
hufCodeBk[p].parent=dlgPara.m_fFreq[p].parent ;
}
hufHdr.wSize=hufHdr.wItemNum *sizeof(HUFCODEBOOK);
int LeftBits=0; //记载没有编码的位数
int bits=0;
unsigned int m;
BYTE wCode=0x00;
WORD tempCode=0x0000;
CFileDialog dlgFileSave(FALSE,"huf","*.huf",
OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT,szFilters,this);
if(dlgFileSave.DoModal ()==IDOK)
PathName=dlgFileSave.GetPathName();
else
return;
TRY
{ CFile ImageFile;
CFileException fe;
ImageFile.Open(PathName,CFile::modeCreate | CFile::modeReadWrite | CFile::shareExclusive,&fe);
ImageFile.Write(&hufHdr,sizeof(HUFHEADER));//写入文件头
ImageFile.Write(hufCodeBk,hufHdr.wSize); //写入编码本
for(q=0;q<dlgPara.m_height;q++)
for(k=0;k<dlgPara.m_width;k++)
{ for(p=1;p<=dlgPara.m_iColorNum;p++)
{ lpSrc=(BYTE *)dlgPara.m_lpDIBBits+dlgPara.m_lLineBytes*q+k;
if(dlgPara.m_fFreq[p].GrayValue==(*lpSrc))
break;
}
for(m=0;m<(unsigned int)(dlgPara.m_strCode[p-1].GetLength());m++)
{
wCode<<=1;
wCode|=(dlgPara.m_strCode[p-1].GetAt(m)-'0');
LeftBits++;
if(LeftBits>=8)
{ ImageFile.Write(&wCode,1);
LeftBits-=8;
wCode=0x00;
}
}
}
for(;LeftBits<8;LeftBits++)
wCode<<=1;
ImageFile.Write(&wCode,1);
ImageFile.Close();
}
CATCH(CFileException,fe)
{
MessageBox("Open file error!");
fe->Delete( );
return;
}
END_CATCH
delete hufCodeBk;
::GlobalUnlock((HGLOBAL)pDoc->GetHDIB());
EndWaitCursor();
}
void CImageProcessView::OnCodeDehuffman()
{
CFile hufFile,bmpSourceFile;
CFileException fe;
char Filters[]="*.huf";
CString PathName;
//打开欲解码的文件
CFileDialog dlgFileDeCode(TRUE,"huf","*.huf",OFN_READONLY,Filters,this);
if(dlgFileDeCode.DoModal ()==IDOK)
PathName=dlgFileDeCode.GetPathName();
else
return;
hufFile.Open((LPCTSTR)PathName,CFile::modeRead,&fe);
//打开与解码文件对应的源位图文件
char FiltersSource[]="*.bmp";
CFileDialog dlgFileSource(TRUE,"bmp","*.bmp",OFN_READONLY,FiltersSource,this);
if(dlgFileSource.DoModal ()==IDOK)
PathName=dlgFileSource.GetPathName();
else
return;
bmpSourceFile.Open((LPCTSTR)PathName,CFile::modeRead,&fe);
HUFHEADER hufHdr;
HUFCODEBOOK *hufCodeBk;
DWORD dwDIBSize;
DWORD dwLineBytes;
//读出文件头
if(hufFile.Read(&hufHdr,sizeof(HUFHEADER))!=sizeof(HUFHEADER))
{ MessageBox("读文件发生错误,操作不能继续","提示信息",MB_OK);
return;
}
//判断是否是*.huf文件
if(hufHdr.wManufacturer!=HUF_HEADER_MARKER)
{ MessageBox("不支持此种文件格式!","提示信息",MB_OK);
return;
}
//读入编码本
hufCodeBk=new HUFCODEBOOK [hufHdr.wItemNum];
if(hufFile.Read((LPSTR)hufCodeBk,hufHdr.wSize)!=hufHdr.wSize )
{ MessageBox("读文件发生错误,解码无法继续!","提示信息",MB_OK);
return;
}
//读入像素值的编码
BYTE *lpSrc;
lpSrc=new BYTE [hufFile.GetLength()-sizeof(HUFHEADER)-hufHdr.wSize];
if(hufFile.ReadHuge(lpSrc,hufFile.GetLength()
-sizeof(HUFHEADER)-hufHdr.wSize)!=hufFile.GetLength()
-sizeof(HUFHEADER)-hufHdr.wSize)
{ MessageBox("读取像素时发生错误,解码不能继续!","提示信息",MB_OK);
return;
}
HDIB hDIB,hDIBSource;
LPSTR lpDIB,lpDIBSource;
LPBITMAPINFOHEADER lpBI;
dwLineBytes=WIDTHBYTES(hufHdr.wWidth*8);
dwDIBSize=sizeof(BITMAPINFOHEADER)+1024+hufHdr.wHeight*dwLineBytes;
hDIB=(HDIB)::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwDIBSize);
if(hDIB==0)
{ MessageBox("内存分配失败,解码无法继续!","提示信息",MB_OK);
return;
}
lpDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
lpBI=(LPBITMAPINFOHEADER)lpDIB;
lpBI->biSize =40;
lpBI->biWidth =hufHdr.wWidth ;
lpBI->biHeight =hufHdr.wHeight ;
lpBI->biPlanes =1;
lpBI->biBitCount =8;
lpBI->biCompression =BI_RGB;
lpBI->biSizeImage =hufHdr.wHeight * dwLineBytes;
lpBI->biXPelsPerMeter =hufHdr.wWidth ;
lpBI->biYPelsPerMeter =hufHdr.wHeight ;
lpBI->biClrImportant =0;
lpBI->biClrUsed =256 ;
BYTE *lpDst,*lpSource;
BYTE tempCode=*lpSrc;
BYTE *lptemp;
BYTE test=0x80;
unsigned int i,j,LeftBits=8; //计数变量
lpDst=(BYTE *)lpDIB+sizeof(BITMAPINFOHEADER);
for(i=0;i<256;i++)
{ for(j=0;j<3;j++,lpDst++)
*lpDst=(BYTE)i;
*lpDst=0x00;
lpDst++;
}
lpDst=(BYTE *)FindDIBBits(lpDIB);
//以下开始解码
for(i=0;i<hufHdr.wHeight;i++)
for(j=0;j<hufHdr.wWidth;j++)
{ lptemp=lpDst+i*dwLineBytes+j;
HUFCODEBOOK tempCodeBk;
tempCodeBk=hufCodeBk[hufHdr.wItemNum-1];
while(tempCodeBk.lchild!=0 && tempCodeBk.rchild!=0)
{ if((tempCode & test)==128)
tempCodeBk=hufCodeBk[tempCodeBk.rchild];
else
tempCodeBk=hufCodeBk[tempCodeBk.lchild];
LeftBits--;
tempCode<<=1;
if(LeftBits==0)
{ LeftBits=8;
lpSrc++;
tempCode=*lpSrc;
}
}
*lptemp=(BYTE)tempCodeBk.GrayValue ;
}
hDIBSource=::ReadDIBFile(bmpSourceFile);
lpDIBSource=(LPSTR)::GlobalLock((HGLOBAL)hDIBSource);
lpSource=(BYTE *)FindDIBBits(lpDIBSource);
double difference=0.0;
lptemp=lpDst;
BYTE *lpSourcetemp=lpSource;
for(i=0;i<hufHdr.wHeight;i++)
for(j=0;j<hufHdr.wWidth;j++)
{ lptemp=lpDst+i*dwLineBytes+j;
lpSourcetemp=lpSource+i*dwLineBytes+j;
difference+=pow((double)((*lptemp)-(*lpSourcetemp)),double(2));
if(difference!=0)
{ i++;
i--;
}
}
//在文档中显示位图
CImageProcessDoc *pDoc=GetDocument();
//ASSERT_VALID(pDoc);
pDoc->ReplaceHDIB(hDIB);
pDoc->InitDIBData();
//pDoc->SetModifiedFlag(TRUE);
SetScrollSizes(MM_TEXT,pDoc->GetDocSize());
OnDoRealize((WPARAM)m_hWnd,0);
pDoc->UpdateAllViews(NULL);
//计算峰值信噪比
char *diffstr,*position='\0',*bitnum="000000";
double ratio;
int decimal,sign;
int precision = 10;
if(difference==0.0)
{ diffstr = _ecvt( difference, precision, &decimal, &sign );
MessageBox(diffstr,"所有对应像素值差平方之和D",MB_OK);
}
else
{ double temp=255*255*(double)hufHdr.wHeight*(double)hufHdr.wWidth;
ratio=10 * log10((double)(temp/difference));
DlgRatio dlgra;
dlgra.m_dRatio =ratio;
dlgra.DoModal ();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -