www.pudn.com > Videodisplay.rar > VideoView.cpp, change:2005-10-06,size:37851b


// VideoView.cpp : implementation of the CVideoView class 
// 
 
#include "stdafx.h" 
#include "Video.h" 
 
#include "VideoDoc.h" 
#include "VideoView.h" 
#include "math.h" 
#include "convert.h" 
#include "wtdlg.h" 
#include "yuvdlg.h" 
#include "time.h" 
#include "fstream.h" 
#include "dwt.h" 
#include "stdio.h" 
#include "stdlib.h" 
#include "intwt.h" 
#include "mcvqdlg.h" 
#include "RelationDlg.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CVideoView 
 
IMPLEMENT_DYNCREATE(CVideoView, CScrollView) 
 
BEGIN_MESSAGE_MAP(CVideoView, CScrollView) 
	//{{AFX_MSG_MAP(CVideoView) 
	ON_COMMAND(ID_PLAY_YUV, OnPlayYuv) 
	ON_COMMAND(ID_WT_SPIHT_ENCODE, OnWtSpihtEncode) 
	ON_COMMAND(ID_WT_SPIHT_DECODE, OnWtSpihtDecode) 
	ON_COMMAND(ID_PLAY_WT, OnPlayWt) 
	ON_COMMAND(ID_MC_INT_ENCODE, OnMcIntEncode) 
	ON_COMMAND(ID_INT_MC_DECODE, OnIntMcDecode) 
	ON_COMMAND(ID_MCVQ_ENCODE, OnMcvqEncode) 
	ON_COMMAND(ID_MCVQ_DECODE, OnMcvqDecode) 
	ON_COMMAND(ID_INTRO_FRAME, OnIntroFrame) 
//	ON_COMMAND(ID_INTER_FRAME, OnInterFrame) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CVideoView construction/destruction 
 
CVideoView::CVideoView() 
{ 
	pels=352; 
	lines=288;          //默认CIF 
	bFlag=0; 
	str_FileName="0"; 
	nFrameNum=0; 
	frequency=30; 
 
	hloc = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, 
   		sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * 256)); 
	BmpInfo = (LPBITMAPINFO) GlobalLock(hloc); 
	// TODO: add construction code here 
} 
 
CVideoView::~CVideoView() 
{ 
} 
 
BOOL CVideoView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
 
	return CScrollView::PreCreateWindow(cs); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CVideoView drawing 
 
void CVideoView::OnDraw(CDC* pDC) 
{ 
	CVideoDoc* pDoc = GetDocument(); 
	ASSERT_VALID(pDoc); 
	// TODO: add draw code for native data here 
	if(bFlag==1)  //表示播放原始视频序列 
	{ 
	    BmpInfo->bmiHeader.biBitCount = 24; 
		create(); 
		showVideo(pDC); 
		bFlag=0; 
		//str_FileName="0"; 
	} 
	if(bFlag==2) //表示小波变换+RLC+Huffman编码 
	{ 
		CString str; 
		str.Format("Encoding,please wait for a moment!"); 
		pDC->SetBkColor(255);	 
		pDC->TextOut(5000,-5000,str); 
		bFlag=0; 
	} 
	if(bFlag==3)   //表示小波+RLC+Huffman解码 
	{ 
		BmpInfo->bmiHeader.biBitCount=24; 
		create(); 
		RlcHuffDe(pDC); 
		bFlag=0; 
	} 
	if(bFlag==4)  //IDWT+反量化 
	{ 
		BmpInfo->bmiHeader.biBitCount=24; 
		create(); 
		iwt(pDC); 
		bFlag=0; 
	} 
	if(bFlag==2) //表示提升小波变换+运动补偿 
	{ 
		CString str; 
		str.Format("Encoding,please wait for a moment!"); 
		pDC->SetBkColor(255);	 
		pDC->TextOut(5000,-5000,str); 
		bFlag=0; 
	} 
} 
 
void CVideoView::OnInitialUpdate() 
{ 
	CScrollView::OnInitialUpdate(); 
 
    CSize sizeTotal(30000, 40000); // 30-by-40 cm 
    CSize sizeLine = CSize(sizeTotal.cx / 100, sizeTotal.cy / 100); 
    SetScrollSizes(MM_HIMETRIC, sizeTotal, sizeTotal, sizeLine); 
	CClientDC dc(this); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CVideoView diagnostics 
 
#ifdef _DEBUG 
void CVideoView::AssertValid() const 
{ 
	CScrollView::AssertValid(); 
} 
 
void CVideoView::Dump(CDumpContext& dc) const 
{ 
	CScrollView::Dump(dc); 
} 
 
CVideoDoc* CVideoView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVideoDoc))); 
	return (CVideoDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CVideoView message handlers 
 
void CVideoView::OnPlayYuv() //播放原始YUV序列 
{ 
	CYUVdlg dlgyuv; 
	dlgyuv.DoModal(); 
	pels=dlgyuv.pels; 
	lines=dlgyuv.lines; 
	frequency=dlgyuv.m_nFrequency; 
	CFileDialog dlg(TRUE,"yuv","*.yuv");  //打开文件的对话狂 
	if(dlg.DoModal()==IDOK) 
	{ 
		str_FileName=dlg.GetPathName(); 
		bFlag=1;       //改变程序运行的状态    
	} 
	Invalidate(); 
} 
 
void CVideoView::create()        //生成图象的头文件 
{ 
    int i; 
	HANDLE hloc1; 
	RGBQUAD *argbq; 
	hloc1 = LocalAlloc(LMEM_ZEROINIT | LMEM_MOVEABLE,(sizeof(RGBQUAD) * 256)); 
	argbq = (RGBQUAD *) LocalLock(hloc1); 
	for(i=0;i<256;i++) { 
		argbq[i].rgbBlue=i; 
		argbq[i].rgbGreen=i; 
		argbq[i].rgbRed=i; 
		argbq[i].rgbReserved=0; 
	}     //生成调色板 
	BmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	BmpInfo->bmiHeader.biPlanes = 1; 
	BmpInfo->bmiHeader.biBitCount = 24; 
	BmpInfo->bmiHeader.biCompression = BI_RGB; 
	BmpInfo->bmiHeader.biWidth = pels; 
	BmpInfo->bmiHeader.biHeight =lines; 
	memcpy(BmpInfo->bmiColors, argbq, sizeof(RGBQUAD) * 256); 
	LocalUnlock(hloc1); 
	LocalFree(hloc1); 
} 
 
 
void CVideoView::showVideo(CDC* pDC)   //播放原始视频序列 
{ 
	 
    ColorSpaceConversions conv; 
	CFile fileVideo; //视频文件 
	fileVideo.Open(str_FileName,CFile::modeRead); 
	unsigned char* lum=new unsigned char[pels*lines]; 
	unsigned char* Cb=new unsigned char[pels*lines/4]; 
	unsigned char* Cr=new unsigned char[pels*lines/4]; 
	UINT PicSize=pels*lines*3/2; 
	unsigned char* m_pImageData=new unsigned char[pels*lines*3/2]; 
	m_pDataRGB=new unsigned char[pels*lines*3]; 
	 
	CString str; 
 
	for(nFrameNum=0;nFrameNum<1500;nFrameNum++) 
	{ 
		fileVideo.Seek(nFrameNum*pels*lines*3/2,SEEK_SET); 
		if(PicSize!=fileVideo.Read(m_pImageData,sizeof(BYTE)*pels*lines*3/2))//在文件中读取一幅图象 
		{ 
			AfxMessageBox("播放结束!"); 
			break; 
		}		  
        memcpy(lum, m_pImageData, pels*lines);             //Y 
        memcpy(Cb, m_pImageData + pels*lines, pels*lines/4);	//u	 
        memcpy(Cr, m_pImageData + pels*lines + pels*lines/4, pels*lines/4);   //V 
		conv.YV12_to_RGB24(lum,Cb,Cr,m_pDataRGB,pels,lines);	 
	    SetDIBitsToDevice(pDC->GetSafeHdc(),600,-660,pels, 
  	                   lines, 
		               0,0,0,lines, 
    		           m_pDataRGB,BmpInfo,DIB_PAL_COLORS); 
		str.Format("The number of frame is %d",nFrameNum+1); 
	    pDC->TextOut(13000,-600,str); 
		delay(frequency); //延时 
	} 
	fileVideo.Close(); 
 
} 
 
void CVideoView::delay(int n)        //延时函数,其中n为每秒的祯数 
{ 
	long int i; 
    clock_t t1,t2; 
	t1=clock(); 
	float tmp=(float)0.95;  //tmp为比例因子,消除其他运算对时间的影响 
	for(i=0;i<3500000;i++) 
	{ 
		t2=clock(); 
		if(((float)(t2-t1)/((float)CLOCKS_PER_SEC))>=(tmp/(float)n)) 
			return; 
		sin(i); 
				t2=clock(); 
		if(((float)(t2-t1)/((float)CLOCKS_PER_SEC))>=(tmp/(float)n)) 
			return; 
		sin(2*i); 
				t2=clock(); 
		if(((float)(t2-t1)/((float)CLOCKS_PER_SEC))>=(tmp/(float)n)) 
			return; 
		sin(3*i); 
				t2=clock(); 
		if(((float)(t2-t1)/((float)CLOCKS_PER_SEC))>=(tmp/(float)n)) 
			return; 
		sin(4*i); 
				t2=clock(); 
		if(((float)(t2-t1)/((float)CLOCKS_PER_SEC))>=(tmp/(float)n)) 
			return; 
		sin(5*i); 
				t2=clock(); 
		if(((float)(t2-t1)/((float)CLOCKS_PER_SEC))>=(tmp/(float)n)) 
			return; 
	} 
 
} 
 
void CVideoView::OnWtSpihtEncode()    //小波变换+行程+huffman编码 
{ 
	BeginWaitCursor(); 
	CFileDialog dlgsource(TRUE,"yuv","*.yuv");  //打开文件的对话狂 
	if(dlgsource.DoModal()==IDOK) 
	{ 
		str_FileName=dlgsource.GetPathName(); 
	} 
	else 
	{ 
		bFlag=0; 
		return; 
	} 
	CWTDlg dlgwt; 
	dlgwt.DoModal(); 
     
	int SpaceLevel,TimeLevel;  //空间分解层数和时间分解层数 
    int nNum;          //时间多少祯做一次小拨分解 
	int stepY,stepU,stepV;    //Y, U, V的量化步长 
	SpaceLevel=dlgwt.m_nSpaceLevel; 
	TimeLevel=dlgwt.m_nTimeLevel; 
	nNum=dlgwt.m_nFrame; 
	stepY=dlgwt.m_nStepY; 
    stepU=dlgwt.m_nStepU; 
    stepV=dlgwt.m_nStepV; 
	pels=dlgwt.pels; 
	lines=dlgwt.lines; 
	AfxMessageBox("请选择编码以后的文件保存:"); 
	CString str_Save;          //编码后的文件保存路径 
    CFileDialog dlgsave(FALSE,"ws","*.ws"); 
	if(dlgsave.DoModal()==IDOK) 
	{ 
		str_Save=dlgsave.GetPathName(); 
		bFlag=2;     //改变程序运行状态 
		Invalidate(); 
	} 
	else 
	{    
	    bFlag=0;  //恢复程序运行状态 
		return; 
	} 
	AfxMessageBox("编码时间可能较长,请耐心等待"); 
	double* tmpBlockY=new double[pels*lines*nNum]; 
	double* tmpBlockU=new double[pels*lines*nNum/4]; 
    double* tmpBlockV=new double[pels*lines*nNum/4]; 
    unsigned char* blockY=new unsigned char[pels*lines*nNum]; 
	unsigned char* blockU=new unsigned char[pels*lines*nNum/4]; 
	unsigned char* blockV=new unsigned char[pels*lines*nNum/4]; 
	unsigned char* m_pData=new unsigned char[pels*lines*3/2]; 
    CFile fileSource; 
	if(!fileSource.Open(str_FileName,CFile::modeRead)) 
	{ 
		bFlag=0; 
		AfxMessageBox("读入文件发生错误!"); 
		return; 
	} 
 
	ofstream tmpout; 
	tmpout.open("D:\\tmp.yuv",ios::trunc|ios::binary); 
	tmpout<<(unsigned char)SpaceLevel<<(unsigned char)TimeLevel<<(unsigned char)nNum<<(unsigned char)stepY<<(unsigned char)stepU<<(unsigned char)stepV; 
	int i,j,k,m; 
	int flag=0;    //临时标记 
	CDwt dwt; 
	unsigned char* spaceDataY=new unsigned char[pels*lines]; 
	unsigned char* spaceDataU=new unsigned char[pels*lines/4]; 
	unsigned char* spaceDataV=new unsigned char[pels*lines/4]; 
	double* timeData=new double[nNum]; 
 
    double *tmpSpaceDataY=new double[pels*lines]; 
	double *tmpSpaceDataU=new double[pels*lines/4]; 
	double *tmpSpaceDataV=new double[pels*lines/4]; 
	double *tmpTimeData=new double[nNum]; 
	double minC,maxC;   //小波变换以后的最小系数和最大系数 
	minC=10000; 
	maxC=0; 
	for(nFrameNum=0;nFrameNum<15000;) 
	{ 
		for(k=0;k=pels*lines) 
				    	goto loo; 
				} 
				else if(dataNew!=dataOld) 
				{ 
					i++; 
					goto loo; 
				} 
			} 
loo:        out<=pels*lines/4) 
				    	goto loou; 
				} 
				else if(dataNew!=dataOld) 
				{ 
					i++; 
					goto loou; 
				} 
			} 
loou:        out<=pels*lines/4) 
				    	goto loov; 
				} 
				else 
				{ 
					i++; 
					goto loov; 
				} 
			} 
loov:        out<>tmp[i]; 
	for(nFrameNum=0;nFrameNum<305;) 
	{ 
		//下面开始解码 
        for(k=0;k>num>>data; 
			    for(j=0;j=pels*lines) 
						break; 
				} 
			} 
			//U 
			for(i=0;i>num>>data; 
				for(j=0;j=pels*lines/4) 
						break; 
				} 
			} 
			//V 
			for(i=0;i>num>>data; 
				for(j=0;j=pels*lines/4) 
						break; 
				} 
			}			 
              //上面已经读入 
           for(i=0;iGetSafeHdc(),600,-660,pels, 
  	                   lines, 
		               0,0,0,lines, 
    		           m_pDataRGB,BmpInfo,DIB_PAL_COLORS); 
	       str.Format("The number of frame is %d",nFrameNum+1); 
	       pDC->TextOut(13000,-600,str); 
		   nFrameNum++; 
			     
        } 
		//上面已经读入块中 
		//下面、是播放 
 /*     for(k=0;kGetSafeHdc(),600,-660,pels, 
  	                   lines, 
		               0,0,0,lines, 
    		           m_pDataRGB,BmpInfo,DIB_PAL_COLORS); 
		}*/ 
	} 
     delete []blockY; 
	 delete []blockU; 
	 delete []blockV; 
	 delete []tmp; 
} 
 
void CVideoView::OnPlayWt()   //播放小波变换量化后的 
{ 
	bFlag=4; 
    Invalidate(); 
} 
	 
 
 
void CVideoView::iwt(CDC* pDC)//反量化+IDWT 
{ 
    
	m_pDataRGB=new unsigned char[pels*lines*3]; 
    ColorSpaceConversions conv; 
	CString str; 
	CFile tmpfile; 
    tmpfile.Open("d:\\tmp.yuv",CFile::modeRead); 
    ///////// 
    unsigned char *tmp=new unsigned char[6]; 
	tmpfile.Read(tmp,6); 
	int nNum,SpaceLevel,TimeLevel,stepY,stepU,stepV; 
	SpaceLevel=tmp[0]; 
	TimeLevel=tmp[1]; 
	nNum=tmp[2]; 
	stepY=tmp[3]; 
	stepU=tmp[4]; 
	stepV=tmp[5]; 
    char*m_pData=new char[pels*lines*3/2]; 
	unsigned char *Lum=new unsigned char[pels*lines]; 
	unsigned char *Cb=new unsigned char[pels*lines/4]; 
	unsigned char *Cr=new unsigned char[pels*lines/4]; 
	double *spaceY=new double[pels*lines]; 
	double *spaceU=new double[pels*lines/4]; 
	double *spaceV=new double[pels*lines/4]; 
	double *blockY=new double[nNum*pels*lines]; 
	double *blockU=new double[nNum*pels*lines/4]; 
	double *blockV=new double[nNum*pels*lines/4]; 
    double *timeData=new double[nNum]; 
	double *tmpTimeData=new double[nNum]; 
	int i,j,k; 
    CDwt dwt; 
	int pixelnum=pels*lines; 
	for(nFrameNum=0;nFrameNum<1500;) 
	{ 
		for(k=0;kGetSafeHdc(),600,-660,pels, 
  	                   lines, 
		               0,0,0,lines, 
    		           m_pDataRGB,BmpInfo,DIB_PAL_COLORS); 
	       str.Format("The number of frame is %d",nFrameNum+1); 
	       pDC->TextOut(13000,-600,str); 
		   nFrameNum++; 
		} 
	} 
endp:tmpfile.Close(); 
 
} 
 
void CVideoView::OnMcIntEncode() //提升格式小波变换与运动补偿编码 
{ 
	// TODO: Add your command handler code here 
	BeginWaitCursor(); 
	CFileDialog dlgsource(TRUE,"yuv","*.yuv");  //打开文件的对话狂 
	if(dlgsource.DoModal()==IDOK) 
	{ 
		str_FileName=dlgsource.GetPathName(); 
	} 
	else 
	{ 
		bFlag=0; 
		return; 
	} 
	CWTDlg dlgwt; 
	dlgwt.DoModal(); 
     
	int SpaceLevel,TimeLevel;  //空间分解层数和时间分解层数 
    int nNum;          //时间多少祯做一次小拨分解 
	int stepY,stepU,stepV;    //Y, U, V的量化步长 
	SpaceLevel=dlgwt.m_nSpaceLevel; 
	TimeLevel=dlgwt.m_nTimeLevel; 
	nNum=dlgwt.m_nFrame; 
	stepY=dlgwt.m_nStepY; 
    stepU=dlgwt.m_nStepU; 
    stepV=dlgwt.m_nStepV; 
	pels=dlgwt.pels; 
	lines=dlgwt.lines; 
	AfxMessageBox("请选择编码以后的文件保存:"); 
	CString str_Save;          //编码后的文件保存路径 
    CFileDialog dlgsave(FALSE,"lwr","*.lwr"); 
	if(dlgsave.DoModal()==IDOK) 
	{ 
		str_Save=dlgsave.GetPathName(); 
		bFlag=5;     //改变程序运行状态 
		Invalidate(); 
	} 
	else 
	{    
	    bFlag=0;  //恢复程序运行状态 
		return; 
	} 
	AfxMessageBox("编码时间可能较长,请耐心等待"); 
	//下面是定义 
	int pixelnum=pels*lines; 
	double* baseBlockY=new double[pixelnum*nNum/2];   //原始块 
	double* baseBlockU=new double[pixelnum/4*nNum/2]; 
	double* baseBlockV=new double[pixelnum/4*nNum/2]; 
	//下面是预测块 
	double* preBlockY=new double[pixelnum*nNum/2]; 
	double* preBlockU=new double[pixelnum/4*nNum/2]; 
	double* preBlockV=new double[pixelnum/4*nNum/2]; 
	unsigned char* spaceData=new unsigned char[pels*lines*3/2];   //总的每祯图象 
	unsigned char* spaceY=new unsigned char[pels*lines]; 
	unsigned char* spaceU=new unsigned char[pels*lines/4]; 
	unsigned char* spaceV=new unsigned char[pels*lines/4]; 
	double* tmpSpaceY=new double[pels*lines];      //经过小波变换以后的 
	double* tmpSpaceU=new double[pels*lines/4]; 
	double* tmpSpaceV=new double[pels*lines/4]; 
	double* timeData=new double[nNum/2]; 
	double* tmpTimeData=new double[nNum/2]; 
	//上面已经定义完全了所需要的变量 
	int i,j,k; //循环变量 
    CFile fileSource; 
	if(!fileSource.Open(str_FileName,CFile::modeRead)) 
	{ 
		bFlag=0; 
		AfxMessageBox("读入文件发生错误!"); 
		return; 
	} 
	//从下面开始小波变换 
	CIntWT intwt; 
	CDwt dwt; 
	int flag=0;   //flag表示读了多少祯,是一个判断程序该何时结束的参数 
	for(nFrameNum=0;nFrameNum<1500;) 
	{ 
		//下面先让原始祯成块,并对每祯进行整数小波变换 
		for(i=0;i