첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드
sample.zip
다운로드

▶ MainForm.cs

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// YUV 디코더
        /// </summary>
        private YUVDecoder yuvDecoder;

        /// <summary>
        /// 프레임 정보
        /// </summary>
        private FrameInformation frameInformation = new FrameInformation();

        /// <summary>
        /// 재생 여부
        /// </summary>
        private bool isPlaying = false;

        /// <summary>
        /// 위치
        /// </summary>
        private int position;

        /// <summary>
        /// 타이머
        /// </summary>
        private Timer timer = new Timer();

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            AllowDrop = true;

            DragOver += Form_DragOver;
            DragDrop += Form_DragDrop;

            KeyDown += Form_KeyDown;

            this.timer = new Timer();

            this.timer.Interval = 30;

            this.timer.Tick += new EventHandler(this.timer_Tick);

            this.openMenuItem.Click  += openMenuItem_Click;
            this.closeMenuItem.Click += closeMenuItem_Click;
            this.exitMenuItem.Click  += exitMenuItem_Click;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 폼 키 다운시 처리하기 - Form_KeyDown(sender, e)

        /// <summary>
        /// 폼 키 다운시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_KeyDown(object sender, KeyEventArgs e)
        {
            switch(e.KeyCode)
            {
                case Keys.Space :

                    Play();

                    break;                
            }
        }

        #endregion

        #region 열기 메뉴 클릭시 처리하기 - openMenuItem_Click(sender, e)

        /// <summary>
        /// 열기 메뉴 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void openMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            if(openFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.frameInformation.FilePath = openFileDialog.FileName;

                ReadFile();
            }
        }

        #endregion
        #region 닫기 메뉴 클릭시 처리하기 - closeMenuItem_Click(sender, e)

        /// <summary>
        /// 닫기 메뉴 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void closeMenuItem_Click(object sender, EventArgs e)
        {
            CloseFile();
        }

        #endregion
        #region 종료 메뉴 클릭시 처리하기 - exitMenuItem_Click(sender, e)

        /// <summary>
        /// 종료 메뉴 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void exitMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion

        #region 폼 드래그 오버시 처리하기 - Form_DragOver(sender, e)

        /// <summary>
        /// 폼 드래그 오버시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_DragOver(object sender, DragEventArgs e)
        {
            if(e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;                
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }

        #endregion
        #region 폼 드래그 드롭시 처리하기 - Form_DragDrop(sender, e)

        /// <summary>
        /// 폼 드래그 드롭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_DragDrop(object sender, DragEventArgs e)
        {
            string[] fileNameArray = e.Data.GetData(DataFormats.FileDrop) as string[];

            if(fileNameArray != null)
            {
                this.frameInformation.FilePath = fileNameArray[0];

                ReadFile();
            }
        }

        #endregion

        #region 백그라운드 작업자 작업 처리하기 - backgroundWorker_DoWork(sender, e)

        /// <summary>
        /// 백그라운드 작업자 작업 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker backgroundWorker = sender as BackgroundWorker;

            backgroundWorker.DoWork -= backgroundWorker_DoWork;

            int totalFrameCount = this.yuvDecoder.FileBufferArray.Length / (this.yuvDecoder.FrameInformation.PixelCountPerFrame +
                this.yuvDecoder.FrameInformation.PixelCountPerFrame / 2);
            int frame           = (int)e.Argument;

            this.yuvDecoder.GetBitmap(frame);

            int percentage = frame / (totalFrameCount / 100);

            this.statusProgressBar.Value = percentage;

            this.messageLabel.Text = "파일 로딩...";

            if(percentage > 98)
            {
                this.statusProgressBar.Value = 100;

                this.messageLabel.Text = "스페이스 키를 누르면 재생됩니다.";

                this.statusProgressBar.Value = 0;

                this.statusProgressBar.Visible = false;
            }

            if(this.yuvDecoder == null)
            {
                this.messageLabel.Text = "대기";

                this.statusProgressBar.Value = 0;

                this.statusProgressBar.Visible = false;

                return;
            }

            ((BackgroundWorker)sender).Dispose();
        }

        #endregion
        #region 타이머 틱 처리하기 - timer_Tick(sender, e)

        /// <summary>
        /// 타이머 틱 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void timer_Tick(object sender, EventArgs e)
        {
            if(this.yuvDecoder == null)
            {
                return;
            }

            if(this.position == this.yuvDecoder.BitmapArray.Length - 1)
            {
                this.timer.Stop();                

                this.position = 0;

                this.isPlaying = false;

                this.messageLabel.Text = string.Format("프레임 : {0} (재생 완료)", this.position);

                return;
            }

            if(this.yuvDecoder.BitmapArray[++this.position] == null)
            {                
                this.position--;
            }

            this.messageLabel.Text = string.Format("프레임 : {0}", this.position);

            this.screenPictureBox.Image = this.yuvDecoder.BitmapArray[this.position];
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Function

        #region 프레임 준비하기 - PrepareFrames()

        /// <summary>
        /// 프레임 준비하기
        /// </summary>
        private void PrepareFrames()
        {
            int totalFrameCount = this.yuvDecoder.FileBufferArray.Length / (this.yuvDecoder.FrameInformation.PixelCountPerFrame +
                this.yuvDecoder.FrameInformation.PixelCountPerFrame / 2);
            
            for(int i = 1; i < totalFrameCount; i++)
            {
                if(this.yuvDecoder == null)
                {
                    return;
                }

                BackgroundWorker backgroundWorker = new BackgroundWorker();

                backgroundWorker.DoWork += backgroundWorker_DoWork;

                backgroundWorker.RunWorkerAsync(i);
            }
        }

        #endregion
        #region 파일 읽기 - ReadFile()

        /// <summary>
        /// 파일 읽기
        /// </summary>
        private void ReadFile()
        {
            this.statusProgressBar.Visible = true;

            this.yuvDecoder = new YUVDecoder(this.frameInformation);

            this.screenPictureBox.Image = this.yuvDecoder.GetBitmap(0);

            PrepareFrames();
        }

        #endregion
        #region 재생하기 - Play()

        /// <summary>
        /// 재생하기
        /// </summary>
        private void Play()
        {
            if(this.isPlaying)
            {
                this.timer.Stop();                
            }
            else
            {
                this.timer.Start();
            }

            this.isPlaying = !this.isPlaying;
        }

        #endregion
        #region 파일 닫기 - CloseFile()

        /// <summary>
        /// 파일 닫기
        /// </summary>
        private void CloseFile()
        {
            if(this.yuvDecoder != null)
            {
                this.yuvDecoder = null;

                this.screenPictureBox.Image = null;

                this.messageLabel.Text = "대기";

                this.isPlaying = false;
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형
Posted by 사용자 icodebroker

댓글을 달아 주세요