// test4Dlg.cpp : implementation file
//


#include "stdafx.h"
#include "test4.h"
#include "test4Dlg.h"
#include "stdio.h"

#include "..\Cximage\ximage.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTest4Dlg dialog

CTest4Dlg::CTest4Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CTest4Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTest4Dlg)
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_byBeginFlag=1;
	m_byInfOpenedFlag=0;
}

void CTest4Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTest4Dlg)
	DDX_Control(pDX, IDC_BUTTON_stop, m_ButtonStop);
	DDX_Control(pDX, IDC_BUTTON_play, m_ButtonPlay);
	DDX_Control(pDX, IDC_BUTTON_pause, m_ButtonPause);
	DDX_Control(pDX, IDC_BUTTON_open, m_ButtonOpen);
	DDX_Control(pDX, IDC_LIST1, m_ListForDebug);
	DDX_Control(pDX, IDC_SLIDER1, m_Slider);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTest4Dlg, CDialog)
	//{{AFX_MSG_MAP(CTest4Dlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON_open, OnBUTTONopen)
	ON_BN_CLICKED(IDC_BUTTON_play, OnBUTTONplay)
	ON_BN_CLICKED(IDC_BUTTON_pause, OnBUTTONpause)
	ON_BN_CLICKED(IDC_BUTTON_stop, OnBUTTONstop)
	ON_WM_SIZE()
	ON_COMMAND(ID_origin, OnOriginSize)
	ON_COMMAND(ID_open, OnOpen)
	ON_COMMAND(ID_pause, OnPause)
	ON_COMMAND(ID_play, OnPlay)
	ON_WM_TIMER()
	ON_COMMAND(ID_stop, OnStop)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTest4Dlg message handlers

BOOL CTest4Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	this->SetWindowText("easy player - searching time test");

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CTest4Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTest4Dlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CTest4Dlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

/*
void CTest4Dlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
	CxImage  image;
	image.Load("data0.bmp", CXIMAGE_FORMAT_BMP);
	if (image.IsValid())
	{
		CWnd* pWnd = GetDlgItem(IDC_STATIC);
		CDC* pDC = pWnd->GetDC();

		CRect rect;
		pWnd->GetClientRect(&rect);
		image.Draw(pDC->m_hDC, rect, NULL);

	}
}
*/
void CTest4Dlg::OnBUTTONopen() 
{
	// TODO: Add your control notification handler code here
	CString strInfFileName;

	m_byPauseFlag=1;
	m_byRedrawingFlag=0;

//	CWnd* pWnd = GetDlgItem(IDC_STATIC);
//	CDC* pDC = pWnd->GetDC();

	CFileDialog *dlgOpenFile = new CFileDialog(TRUE,NULL,NULL,
		OFN_HIDEREADONLY,
		"inf Files (*.inf)|*.inf|All Files (*.*)|*.*||",NULL);

	if(dlgOpenFile->DoModal()==TRUE)
	{

		strInfFileName.Format("%s",dlgOpenFile->GetPathName());
		if(m_byInfOpenedFlag)			//we should close the old info file firstly.
		{
			m_Slider.SetPos(0);
			m_fileInf.Close();
		}
	


		if(m_fileInf.Open(strInfFileName, CFile::modeRead, NULL))
		{
			m_fileInf.Read(&m_AviFileInfo,sizeof(AVIFILEINFO));
			m_fileInf.Read(&m_strIFrameType,4);
			m_fileInf.Read(&m_strPFrameType,4);

			int iInstallResult;
			int iRate=m_AviFileInfo.dwScale/1000;

			iInstallResult=SetTimer(1,iRate,NULL);
			if(iInstallResult==0)
			{
				MessageBox("Can not install timer!");
			}

			m_Slider.SetRange(0,m_AviFileInfo.dwLength);

			m_byInfOpenedFlag=1;
			m_dwFrameNum=0;

		}
	}

	m_byPauseFlag=0;
}

void CTest4Dlg::OnTimer(UINT nIDEvent)
{
	int iSliderPos;
	if(!m_byPauseFlag)
	{
		if(m_dwFrameNum < m_AviFileInfo.dwLength)  //the video is not finished.
		{
			byte byFrameType;
			iSliderPos=m_Slider.GetPos();
 			if(m_dwFrameNum != (DWORD)iSliderPos)
			{
				//following code is for the test of search time: 
				CString strTemp;
				clock_t StartTime, FinishTime;
				double  Duration;
				StartTime = clock();

				SliderChange();

				//following code is for the test of search time:
				FinishTime = clock();
				Duration = (double)(FinishTime - StartTime)/ CLOCKS_PER_SEC;
				strTemp.Format("searching time=%lf",Duration);
				m_ListForDebug.InsertString(0,strTemp);

			}

			m_fileInf.Read(&byFrameType,sizeof(byte));

			//for the debugging of the m_byRedrawingFlag process.
//			CString aa;
//			aa.Format("type=%d, Num=%d, pos=%d, %p",type, Num, pos, info.GetPosition());
//			m_ListForDebug.InsertString(0,aa);
		

			if(byFrameType==IFRAME)
				ReadIFrame();
			if(byFrameType==PFRAME)
				ReadPFrame();
			if(byFrameType==OFRAME)
				Read0Frame();		
		
			m_dwFrameNum++;
			m_Slider.SetPos(m_dwFrameNum);
		}
		else
		{
			OnBUTTONstop();
		}
	}
}

void CTest4Dlg::ReadPFrame()
{
	CFile filePFrame;
	my_pixel TempPix;
	RGBQUAD Color;
	int i;

	char PFrameFileName[30];

	::sprintf(PFrameFileName, "data%d.%s", m_dwFrameNum, m_strPFrameType);
	if(::strcmp(m_strPFrameType,"bin")==0)
	{
		if(filePFrame.Open(PFrameFileName, CFile::modeRead, NULL))
		{
			for(i=0;i<=1024*768;i++)
			{
				filePFrame.Read(&TempPix,sizeof(my_pixel)-1);
				if(TempPix.x==-1)
					break;
				Color.rgbRed=TempPix.r; Color.rgbGreen=TempPix.g; Color.rgbBlue=TempPix.b;

				m_Ximage.SetPixelColor(TempPix.x, TempPix.y, Color, NULL);
			}

			ShowImage();
		}
	}
	else if(::strcmp(m_strPFrameType,"png")==0)
	{
		CxImage tempImage;
		tempImage.Load(PFrameFileName,CXIMAGE_FORMAT_PNG);
		Mix2Pic(&m_Ximage, tempImage);
		ShowImage();
	}
	else if(::strcmp(m_strPFrameType,"jpg")==0)
	{
		CxImage tempImage;
		tempImage.Load(PFrameFileName,CXIMAGE_FORMAT_JPG);
		Mix2Pic(&m_Ximage, tempImage);
		ShowImage();
	}

}



void CTest4Dlg::Read0Frame()
{
	ShowImage();
}

void CTest4Dlg::ReadIFrame()
{
	char pIFrameFilename[30];
	::sprintf(pIFrameFilename,"data%d.%s", m_dwFrameNum, m_strIFrameType);
	if(::strcmp(m_strIFrameType,"bmp")==0)
		m_Ximage.Load(pIFrameFilename, CXIMAGE_FORMAT_BMP);

	else if(::strcmp(m_strIFrameType,"png")==0)
		m_Ximage.Load(pIFrameFilename, CXIMAGE_FORMAT_PNG);

	else if(::strcmp(m_strIFrameType,"jpg")==0)
		m_Ximage.Load(pIFrameFilename, CXIMAGE_FORMAT_JPG);

	else
		MessageBox("error in mainframetype");

	ShowImage();
}

void CTest4Dlg::ShowImage()
{
	if(!m_byRedrawingFlag)
	{
		if (m_Ximage.IsValid())
		{
			CWnd* pWnd = GetDlgItem(IDC_STATIC);
			CDC* pDC = pWnd->GetDC();

			CRect rect;
			pWnd->GetClientRect(&rect);
			m_Ximage.Draw(pDC->m_hDC, rect, NULL);

		}
	}
}


void CTest4Dlg::OnBUTTONplay() 
{
	// TODO: Add your control notification handler code here
	m_byPauseFlag=0;
}

void CTest4Dlg::OnBUTTONpause() 
{
	// TODO: Add your control notification handler code here
	m_byPauseFlag=1;
}

void CTest4Dlg::OnBUTTONstop() 
{
	// TODO: Add your control notification handler code here
	m_byPauseFlag=1;
	m_dwFrameNum=0;
	m_fileInf.Seek(sizeof(AVIFILEINFO)+8,CFile::begin);
	m_Slider.SetPos(0);

}


void CTest4Dlg::SliderChange()
{	
	m_byPauseFlag=1;
	byte byFrameType;
	int	newNum=m_Slider.GetPos();
	m_dwFrameNum=newNum;
	m_fileInf.Seek(sizeof(AVIFILEINFO) + 8 + m_dwFrameNum, CFile::begin);

	for(;;)
	{
		//seek for the previous I-frame.
		m_fileInf.Read(&byFrameType,sizeof(byte));
		m_fileInf.Seek(-1,CFile::current);
		if(byFrameType!=2)
		{
			m_fileInf.Seek(-1,CFile::current);
			newNum--;
		
//		CString aa;
//		int pos=m_Slider.GetPos();
//		aa.Format("searching   newNum=%d,Num=%d, pos=%d, %p",newNum,Num, pos, info.GetPosition());
//		m_ListForDebug.InsertString(0,aa);

		}

		else
			break;
	}

	m_byRedrawingFlag=1;
    int oldNum=m_dwFrameNum;

	//redraw the image till the current frame.
	for(m_dwFrameNum=newNum; (int)m_dwFrameNum<=oldNum; m_dwFrameNum++)
	{		
		m_fileInf.Read(&byFrameType,sizeof(byte));

//		CString aa;
//		int pos=m_Slider.GetPos();
//		aa.Format("m_byRedrawingFlag   type=%d,newNum=%d,Num=%d, pos=%d, %p",type,newNum,Num, pos, info.GetPosition());
//		m_ListForDebug.InsertString(0,aa);

		if(byFrameType==IFRAME)
			ReadIFrame();
		if(byFrameType==PFRAME)
			ReadPFrame();
		if(byFrameType==OFRAME)
			Read0Frame();	
		
	}
	m_byRedrawingFlag=0;
	m_byPauseFlag=0;
}

void CTest4Dlg::OnSize(UINT nType, int x, int y) 
{
	CDialog::OnSize(nType, x, y);
	
	// TODO: Add your message handler code here
	if(!m_byBeginFlag)
	{
		CRect rect;
		GetClientRect(&rect);
		rect.InflateRect(-20,-20);

		m_ButtonOpen.MoveWindow(rect.left+0, rect.bottom-10, 50, 22);
		m_ButtonPlay.MoveWindow(rect.left+52, rect.bottom-10, 50, 22);
		m_ButtonPause.MoveWindow(rect.left+104, rect.bottom-10, 50, 22);
		m_ButtonStop.MoveWindow(rect.left+156, rect.bottom-10, 50, 22);
		m_Slider.MoveWindow(rect.left+210, rect.bottom-10, rect.Width()-195, 22);

		CWnd* pWnd = GetDlgItem(IDC_STATIC);
		pWnd->MoveWindow(rect.left, rect.top, rect.Width(), rect.Height()-40);

	}
	m_byBeginFlag=0;
	
}

void CTest4Dlg::OnOriginSize() 
{
	// TODO: Add your command handler code here
	if(m_byInfOpenedFlag)
	{
		int SceneX,SceneY;
		CRect MaxWindowRect;

		ShowWindow(SW_MAXIMIZE);    //make the window largest.
		GetClientRect(&MaxWindowRect);  //get its window's rectangle 

		SceneX = MaxWindowRect.Width();		//assume the scene should be the largest scene
		SceneY = MaxWindowRect.Height()-40;	//that mean's the vedio's original size is larger than the current scene

		if((int) m_AviFileInfo.dwWidth < SceneX)   //whether the vedio's width is smaller than Scene
			SceneX=m_AviFileInfo.dwWidth;		//the Scene should equal to vedio's original size.	

		if((int)m_AviFileInfo.dwHeight < SceneY)
			SceneY=m_AviFileInfo.dwHeight;

		if(SceneX!=MaxWindowRect.Width() || SceneY!=MaxWindowRect.Height()-40)
		{//use vedio's original size, since it is smaller than the maximal window.
			
			MoveWindow(			//move the Window into the center, resize it.
				MaxWindowRect.left+(MaxWindowRect.Width()-SceneX)/2-10,
				MaxWindowRect.top-10+(MaxWindowRect.Height()-40-SceneY)/2,
				SceneX+30,
				SceneY+100
				);

			CWnd* pWnd = GetDlgItem(IDC_STATIC);  //resize the scene part.
			pWnd->MoveWindow(10,10,SceneX,SceneY);	
		}
		else		//use max windows size as the original video scene size.
		{
			CWnd* pWnd = GetDlgItem(IDC_STATIC);
			pWnd->MoveWindow(
				MaxWindowRect.left+(MaxWindowRect.Width()-SceneX)/2,
				MaxWindowRect.top+(MaxWindowRect.Height()-40-SceneY)/2,
				SceneX,
				SceneY
				);
		}
	}
}

void CTest4Dlg::OnOpen() 
{
	// TODO: Add your command handler code here
	OnBUTTONopen();
}

void CTest4Dlg::OnPause() 
{
	// TODO: Add your command handler code here
	OnBUTTONpause();
}

void CTest4Dlg::OnPlay() 
{
	// TODO: Add your command handler code here
	OnBUTTONplay();
}

void CTest4Dlg::OnStop() 
{
	// TODO: Add your command handler code here
	OnBUTTONstop();
}

//and the 
void CTest4Dlg::Mix2Pic(CxImage *pXimage1, CxImage Ximage2)
{  
	long x,y;
	long width = Ximage2.GetWidth();
    long height = Ximage2.GetHeight();

//	RGBQUAD rgbBackgrnd = image2.GetTransColor();
	RGBQUAD rgb1;
	RGBQUAD Backgroud;
	Backgroud.rgbBlue=205;
	Backgroud.rgbGreen=205;
	Backgroud.rgbRed=205;
    
	for(x = 0; x < width; x++)
    {
        for(y = 0; y < height; y++)
        {
            rgb1 = Ximage2.GetPixelColor(x, y);
		  	if(memcmp(&Backgroud,&rgb1,sizeof(RGBQUAD)-1)!=0)
                pXimage1->SetPixelColor(x, y, rgb1);
        }
    }
}

