■ GIF 에디터 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MainForm.cs

 

 

using System;

using System.Drawing;

using System.IO;

using System.Windows.Forms;

 

using TestProject.Properties;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// GIF 래퍼

        /// </summary>

        private GIFWrapper wrapper = null;

 

        /// <summary>

        /// 파일 경로

        /// </summary>

        private string filePath = null;

 

        /// <summary>

        /// 현재 컨트롤

        /// </summary>

        private Control currentControl = null;

 

        /// <summary>

        /// GIF 파트 헤더 컨트롤

        /// </summary>

        private GIFPartHeaderControl headerControl;

 

        /// <summary>

        /// GIF 파트 16진수 문자열 뷰 컨트롤

        /// </summary>

        private GIFPartHexadecimalControl hexadecimalControl;

 

        /// <summary>

        /// GIF 파트 LWZ 이미지 컨트롤

        /// </summary>

        private GIFPartLWZImageControl lwzImageControl;

 

        /// <summary>

        /// GIF 파트 메타 어플리케이션 컨트롤

        /// </summary>

        private GIFPartMetaApplicationControl metaApplicationControl;

 

        /// <summary>

        /// GIF 파트 메타 그래픽스 컨트롤

        /// </summary>

        private GIFPartMetaGraphicsControl metaGraphicsControl;

 

        /// <summary>

        /// GIF 파트 메타 루프 컨트롤

        /// </summary>

        private GIFPartMetaLoopControl metaLoopControl;

 

        /// <summary>

        /// GIF 파트 메타 텍스트 컨트롤

        /// </summary>

        private GIFPartMetaTextControl metaTextControl;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 래퍼 - Wrapper

 

        /// <summary>

        /// 래퍼

        /// </summary>

        public GIFWrapper Wrapper

        {

            get

            {

                return this.wrapper;

            }

            set

            {

                this.wrapper = value;

 

                UpdatePartList();

 

                UpdatePreviewPanel();

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region GIF 컨트롤을 설정한다.

 

            this.headerControl          = new GIFPartHeaderControl();

            this.hexadecimalControl     = new GIFPartHexadecimalControl();

            this.lwzImageControl        = new GIFPartLWZImageControl();

            this.metaApplicationControl = new GIFPartMetaApplicationControl();

            this.metaGraphicsControl    = new GIFPartMetaGraphicsControl();

            this.metaLoopControl        = new GIFPartMetaLoopControl();

            this.metaTextControl        = new GIFPartMetaTextControl();

 

            #endregion

            #region 파트 리스트 뷰를 설정한다.

 

            ImageList imageList = new ImageList();

 

            imageList.Images.Add(Resources.header );

            imageList.Images.Add(Resources.lwzimg );

            imageList.Images.Add(Resources.app    );

            imageList.Images.Add(Resources.comment);

            imageList.Images.Add(Resources.ctrl   );

            imageList.Images.Add(Resources.text   );

            imageList.Images.Add(Resources.unknown);

            imageList.Images.Add(Resources.eof    );

            imageList.Images.Add(Resources.garbage);

 

            this.partListView.SmallImageList = imageList;

 

            #endregion

            #region 이벤트를 설정한다.

 

            DragEnter                                += Form_DragEnter;

            DragDrop                                 += Form_DragDrop;

            this.openMenuItem.Click                  += openMenuItem_Click;

            this.saveMenuItem.Click                  += saveMenuItem_Click;

            this.saveAsMenuItem.Click                += saveAsMenuItem_Click;

            this.partListView.SelectedIndexChanged   += partListView_SelectedIndexChanged;

            this.headerControl.ValueChanged          += gifControl_ValueChanged;

            this.hexadecimalControl.ValueChanged     += gifControl_ValueChanged;

            this.lwzImageControl.ValueChanged        += gifControl_ValueChanged;

            this.metaApplicationControl.ValueChanged += gifControl_ValueChanged;

            this.metaGraphicsControl.ValueChanged    += gifControl_ValueChanged;

            this.metaLoopControl.ValueChanged        += gifControl_ValueChanged;

            this.metaTextControl.ValueChanged        += gifControl_ValueChanged;

 

            #endregion

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 폼 드래그 ENTER 처리하기 - Form_DragEnter(sender, e)

 

        /// <summary>

        /// 폼 드래그 ENTER 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_DragEnter(object sender, DragEventArgs e)

        {

            if(e.Data.GetDataPresent(DataFormats.FileDrop))

            {

                e.Effect = DragDropEffects.Move;

            }

            else

            {

                e.Effect = DragDropEffects.None;

            }

        }

 

        #endregion

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

 

        /// <summary>

        /// 폼 드래그 DROP 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void Form_DragDrop(object sender, DragEventArgs e)

        {

            if(e.Data.GetDataPresent(DataFormats.FileDrop))

            {

                try

                {

                    string[] fileArray = (string[])e.Data.GetData(DataFormats.FileDrop);

 

                    if(fileArray != null && fileArray.Length > 0)

                    {

                        GIFWrapper wrapper = new GIFWrapper(fileArray[0]);

 

                        Wrapper = wrapper;

 

                        this.filePath = fileArray[0];

                    }

                }

                catch(Exception exception)

                {

                    MessageBox.Show

                    (

                        "GIF 이미지 로딩시 에러가 발생했습니다.\r\n\r\n" + exception.Message,

                        "ERROR",

                        MessageBoxButtons.OK,

                        MessageBoxIcon.Error

                    );

                }

            }

        }

 

        #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();

 

            openFileDialog.AutoUpgradeEnabled = true;

            openFileDialog.Filter             = "GIF 이미지|*.gif|모든 파일|*.*";

            openFileDialog.FilterIndex        = 0;

            openFileDialog.Multiselect        = false;

            openFileDialog.RestoreDirectory   = true;

 

            if(openFileDialog.ShowDialog() == DialogResult.OK)

            {

                try

                {

                    GIFWrapper wrapper = new GIFWrapper(openFileDialog.FileName);

 

                    Wrapper = wrapper;

 

                    this.filePath = openFileDialog.FileName;

                }

                catch(Exception exception)

                {

                    MessageBox.Show

                    (

                        "GIF 이미지 로딩시 에러가 발생했습니다.\r\n\r\n" + exception.Message,

                        "ERROR",

                        MessageBoxButtons.OK,

                        MessageBoxIcon.Error

                    );

                }

            }

        }

 

        #endregion

        #region 저장하기 메뉴 항목 클릭시 처리하기 - saveMenuItem_Click(sender, e)

 

        /// <summary>

        /// 저장하기 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void saveMenuItem_Click(object sender, EventArgs e)

        {

            if(this.wrapper == null)

            {

                return;

            }

 

            if(string.IsNullOrEmpty(this.filePath))

            {

                return;

            }

 

            try

            {

                byte[] dataByteArray = this.wrapper.GetDataByteArray();

 

                File.WriteAllBytes(this.filePath, dataByteArray);

            }

            catch(Exception exception)

            {

                MessageBox.Show

                (

                    "GIF 이미지 저장시 에러가 발생했습니다.\r\n\r\n" + exception.Message,

                    "ERROR",

                    MessageBoxButtons.OK,

                    MessageBoxIcon.Error

                );

            }

        }

 

        #endregion

        #region 다른 이름으로 저정하기 메뉴 항목 클릭시 처리하기 - saveAsMenuItem_Click(sender, e)

 

        /// <summary>

        /// 다른 이름으로 저정하기 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void saveAsMenuItem_Click(object sender, EventArgs e)

        {

            if(this.wrapper == null)

            {

                return;

            }

 

            try

            {

                byte[] dataByteArray = this.wrapper.GetDataByteArray();

 

                SaveFileDialog saveFileDialog = new SaveFileDialog();

 

                saveFileDialog.AutoUpgradeEnabled = true;

                saveFileDialog.CheckFileExists    = false;

                saveFileDialog.CheckPathExists    = true;

                saveFileDialog.DefaultExt         = ".gif";

                saveFileDialog.FileName           = string.IsNullOrEmpty(this.filePath) ? "image.gif" : Path.GetFileName(this.filePath);

                saveFileDialog.Filter             = "GIF 이미지|*.gif|모든 파일|*.*";

                saveFileDialog.FilterIndex        = 0;

                saveFileDialog.RestoreDirectory   = true;

 

                if(saveFileDialog.ShowDialog() == DialogResult.OK)

                {

                    File.WriteAllBytes(saveFileDialog.FileName, dataByteArray);

                }

            }

            catch(Exception exception)

            {

                MessageBox.Show

                (

                    "GIF 이미지 저장시 에러가 발생했습니다.\r\n\r\n" + exception.Message,

                    "ERROR",

                    MessageBoxButtons.OK,

                    MessageBoxIcon.Error

                );

            }

        }

 

        #endregion

        #region 모든 지연 시간 설정하기 메뉴 항목 클릭시 처리하기 - setAllDelayTimeMenuItem_Click(sender, e)

 

        /// <summary>

        /// 모든 지연 시간 설정하기 메뉴 항목 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void setAllDelayTimeMenuItem_Click(object sender, EventArgs e)

        {

            if(this.wrapper == null)

            {

                return;

            }

 

            decimal initial = 0m;

            decimal count   = 0m;

 

            foreach(GIFPart part in this.wrapper)

            {

                if(part is GIFPartMetaData.GraphicsControl)

                {

                    initial += (part as GIFPartMetaData.GraphicsControl).DelayTime;

 

                    count++;

                }

            }

 

            if(count > 0)

            {

                initial = Math.Floor(initial / count);

            }

 

            SelectNumberForm form = new SelectNumberForm("지연 시간 선택하기", "지연 시간", 65535, initial);

 

            if(form.ShowDialog() == DialogResult.OK)

            {

                ushort value = Convert.ToUInt16(form.Value);

 

                foreach(GIFPart part in this.wrapper)

                {

                    if(part is GIFPartMetaData.GraphicsControl)

                    {

                        (part as GIFPartMetaData.GraphicsControl).DelayTime = value;

                    }

                }

 

                UpdateExistingList();

 

                UpdatePreviewPanel();

            }

        }

 

        #endregion

        #region 파트 리스트 뷰 선택 인덱스 변경시 처리하기 - partListView_SelectedIndexChanged(sender, e)

 

        /// <summary>

        /// 파트 리스트 뷰 선택 인덱스 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void partListView_SelectedIndexChanged(object sender, EventArgs e)

        {

            this.partPanel.Controls.Clear();

 

            Control nextControl = null;

 

            object partObject = this.partListView.SelectedItems.Count == 0 ? null : this.partListView.SelectedItems[0].Tag;

 

            if(partObject is GIFPartHeader)

            {

                GIFPartHeader header = partObject as GIFPartHeader;

 

                this.headerControl.Part = header;

 

                nextControl = this.headerControl;

            }

            else if(partObject is GIFPartLWZImage)

            {

                GIFPartLWZImage lwzImage = partObject as GIFPartLWZImage;

 

                this.lwzImageControl.Part = lwzImage;

 

                nextControl = this.lwzImageControl;

            }

            else if(partObject is GIFPartMetaData.ApplicationData)

            {

                GIFPartMetaData.ApplicationData applicationData = partObject as GIFPartMetaData.ApplicationData;

 

                this.metaApplicationControl.Part = applicationData;

 

                nextControl = this.metaApplicationControl;

            }

            else if(partObject is GIFPartMetaData.Comment)

            {

                GIFPartMetaData.Comment comment = partObject as GIFPartMetaData.Comment;

 

                this.hexadecimalControl.Part = comment;

 

                nextControl = this.hexadecimalControl;

            }

            else if(partObject is GIFPartMetaData.GraphicsControl)

            {

                GIFPartMetaData.GraphicsControl graphicsControl = partObject as GIFPartMetaData.GraphicsControl;

 

                this.metaGraphicsControl.Part = graphicsControl;

 

                nextControl = this.metaGraphicsControl;

            }

            else if(partObject is GIFPartMetaData.Loop)

            {

                GIFPartMetaData.Loop metaLoop = partObject as GIFPartMetaData.Loop;

 

                this.metaLoopControl.Part = metaLoop;

 

                nextControl = this.metaLoopControl;

            }

            else if(partObject is GIFPartMetaData.TextDraw)

            {

                GIFPartMetaData.TextDraw metaText = partObject as GIFPartMetaData.TextDraw;

 

                this.metaTextControl.Part = metaText;

 

                nextControl = this.metaTextControl;

            }

            else if(partObject is GIFPartMetaData)

            {

                GIFPartMetaData metaData = partObject as GIFPartMetaData;

 

                this.hexadecimalControl.Part = metaData;

 

                nextControl = this.hexadecimalControl;

            }

            else if(partObject is GIFPartGarbageData)

            {

                GIFPartGarbageData grabaseData = partObject as GIFPartGarbageData;

 

                this.hexadecimalControl.Part = grabaseData;

 

                nextControl = this.hexadecimalControl;

            }

 

            if(this.currentControl != nextControl)

            {

                SuspendLayout();

 

                this.partPanel.Controls.Clear();

 

                if(nextControl != null)

                {

                    this.partPanel.Controls.Add(nextControl);

 

                    nextControl.Dock = DockStyle.Fill;

                }

 

                ResumeLayout();

 

                this.currentControl = nextControl;

            }

        }

 

        #endregion

        #region GIF 컨트롤 값 변경시 처리하기 - gifControl_ValueChanged(sender, e)

 

        /// <summary>

        /// GIF 컨트롤 값 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void gifControl_ValueChanged(object sender, EventArgs e)

        {

            UpdatePreviewPanel();

 

            GIFPart part = (sender as IGIFControl).GIFPart;

 

            ListViewItem updateItem = null;

 

            foreach(ListViewItem item in this.partListView.Items)

            {

                if(item.Tag == part)

                {

                    updateItem = item;

 

                    break;

                }

            }

 

            if(updateItem != null)

            {

                UpdateListViewItem(updateItem, part);

            }

        }

 

        #endregion

 

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

 

        #region 리스트 뷰 항목 업데이트하기 - UpdateListViewItem(item, part)

 

        /// <summary>

        /// 리스트 뷰 항목 업데이트하기

        /// </summary>

        /// <param name="item">리스트 뷰 항목</param>

        /// <param name="part">GIF 파트</param>

        private void UpdateListViewItem(ListViewItem item, GIFPart part)

        {

            if(part is GIFPartHeader)

            {

                item.Text       = "헤더";

                item.ImageIndex = 0;

            }

            else if(part is GIFPartLWZImage)

            {

                GIFPartLWZImage lwzImage = part as GIFPartLWZImage;

 

                item.Text = string.Format

                (

                    "이미지 [{0}x{1} @{2}x{3}]",

                    lwzImage.Width,

                    lwzImage.Height,

                    lwzImage.Left,

                    lwzImage.Top

                );

 

                item.ImageIndex = 1;

            }

            else if(part is GIFPartMetaData.ApplicationData)

            {

                GIFPartMetaData.ApplicationData applicationData = part as GIFPartMetaData.ApplicationData;

 

                item.Text = string.Format("앱 데이터 [{0}]", applicationData.AppIdentifier);

 

                item.ImageIndex = 2;

            }

            else if (part is GIFPartMetaData.Loop)

            {

                GIFPartMetaData.Loop loop = part as GIFPartMetaData.Loop;

 

                item.Text = string.Format("앱 데이터 [반복 : {0}]", loop.IterationCount);

 

                item.ImageIndex = 2;

            }

            else if(part is GIFPartMetaData.Comment)

            {

                GIFPartMetaData.Comment comment = part as GIFPartMetaData.Comment;

 

                item.Text = string.Format("주석 [{0} 바이트]", comment.ContentByteArray.Length);

 

                item.ImageIndex = 3;

            }

            else if(part is GIFPartMetaData.GraphicsControl)

            {

                GIFPartMetaData.GraphicsControl control = part as GIFPartMetaData.GraphicsControl;

 

                item.Text = string.Format

                (

                    "제어 [변환 : {0}, 지연 : {1}]",

                    control.UseTransparency ? "1" : "0",

                    control.UseUserInput ? "사용자" : ((control.DelayTime).ToString() + "밀리초")

                );

 

                item.ImageIndex = 4;

            }

            else if(part is GIFPartMetaData.TextDraw)

            {

                GIFPartMetaData.TextDraw textDraw = part as GIFPartMetaData.TextDraw;

 

                string text = textDraw.Text;

 

                item.Text = string.Format

                (

                    "텍스트 [{2}, @{0}x{1}]",

                    textDraw.Left,

                    textDraw.Width,

                    text.Length > 10 ? (text.Substring(0, 8) + "...") : text

                );

 

                item.ImageIndex = 5;

            }

            else if(part is GIFPartMetaData)

            {

                GIFPartMetaData metaData = part as GIFPartMetaData;

 

                item.Text = string.Format("미정 [{0}]", metaData.MetaType);

 

                item.ImageIndex = 6;

            }

            else if(part is GIFPartTerminator)

            {

                item.Text = "파일 끝";

 

                item.ImageIndex = 7;

            }

            else if(part is GIFPartGarbageData)

            {

                GIFPartGarbageData garbageData = part as GIFPartGarbageData;

 

                item.Text = "가비지 데이터";

 

                item.ImageIndex = 8;

            }

        }

 

        #endregion

        #region 파트 리스트 업데이트하기 - UpdatePartList()

 

        /// <summary>

        /// 파트 리스트 업데이트하기

        /// </summary>

        private void UpdatePartList()

        {

            if(InvokeRequired)

            {

                Invoke(new Action(UpdatePartList));

 

                return;

            }

 

            SuspendLayout();

 

            this.partListView.Items.Clear();

 

            if(this.wrapper != null)

            {

                foreach(GIFPart part in this.wrapper)

                {

                    ListViewItem item = new ListViewItem();

 

                    UpdateListViewItem(item, part);

 

                    item.SubItems.Add(part.Length.ToString());

 

                    item.Tag = part;

 

                    this.partListView.Items.Add(item);

                }

            }

 

            ResumeLayout();

        }

 

        #endregion

        #region 기존 리스트 업데이트하기 - UpdateExistingList()

 

        /// <summary>

        /// 기존 리스트 업데이트하기

        /// </summary>

        private void UpdateExistingList()

        {

            if(InvokeRequired)

            {

                Invoke(new Action(UpdatePartList));

 

                return;

            }

 

            SuspendLayout();

 

            ListViewItem item;

 

            for(int i = 0; i < this.wrapper.Count; i++)

            {

                GIFPart part = this.wrapper[i];

 

                if(this.partListView.Items.Count <= i)

                {

                    item = new ListViewItem();

 

                    UpdateListViewItem(item, this.wrapper[i]);

 

                    item.SubItems.Add(this.wrapper[i].Length.ToString());

 

                    item.Tag = this.wrapper[i];

 

                    this.partListView.Items.Add(item);

                }

                else if(this.partListView.Items[i].Tag != this.wrapper[i])

                {

                    int index = -1;

 

                    for(int j = 0; j < this.partListView.Items.Count; j++)

                    {

                        if(this.partListView.Items[j].Tag == part)

                        {

                            index = j;

 

                            break;

                        }

                    }

 

                    if(index == -1)

                    {

                        item = new ListViewItem();

 

                        UpdateListViewItem(item, this.wrapper[i]);

 

                        item.SubItems.Add(this.wrapper[i].Length.ToString());

 

                        item.Tag = this.wrapper[i];

 

                        this.partListView.Items.Insert(i, item);

                    }

                    else

                    {

                        item = this.partListView.Items[index];

 

                        UpdateListViewItem(item, part);

 

                        this.partListView.Items.RemoveAt(index);

 

                        this.partListView.Items.Insert(i, item);

                    }

                }

                else

                {

                    item = partListView.Items[i];

 

                    UpdateListViewItem(item, part);

                }

            }

 

            ResumeLayout();

        }

 

        #endregion

        #region 미리보기 패널 업데이트하기 - UpdatePreviewPanel()

 

        /// <summary>

        /// 미리보기 패널 업데이트하기

        /// </summary>

        private void UpdatePreviewPanel()

        {

            if(InvokeRequired)

            {

                Invoke(new Action(UpdatePreviewPanel));

 

                return;

            }

 

            Image image = null;

 

            if(this.wrapper != null)

            {

                try

                {

                    image = this.wrapper.ToImage();

                }

                catch(Exception exception)

                {

                    image = new Bitmap(256, 256);

 

                    using(Graphics graphics = Graphics.FromImage(image))

                    {

                        using(Pen pen = new Pen(Color.Red, 4f))

                        {

                            using(Font font = new Font(FontFamily.GenericSansSerif, 8f, FontStyle.Regular))

                            {

                                graphics.Clear(Color.Transparent);

 

                                graphics.DrawRectangle(pen, 0, 0, 256, 256);

 

                                graphics.DrawLine(pen, 0, 0, 256, 256);

                                graphics.DrawLine(pen, 256, 0, 0, 256);

 

                                graphics.DrawString(exception.Message, font, Brushes.Black, new RectangleF(8, 8, 248, 248));

                            }

                        }

                    }

                }

            }

 

            if(this.previewPictureBox.Image != null)

            {

                this.previewPictureBox.Image.Dispose();

            }

 

            this.previewPictureBox.Image = image;

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker

댓글을 달아 주세요