■ PictureEdit 클래스 : 마우스를 사용해 올가미 밧줄(lasso) 사각형 그리기

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


TestProject.zip


MainForm.cs

 

 

using System;

using System.Drawing;

using System.IO;

using System.Windows.Forms;

 

using DevExpress.XtraEditors;

using DevExpress.XtraEditors.Controls;

using DevExpress.XtraEditors.ViewInfo;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : Form

    {

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

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

 

        #region Field

 

        /// <summary>

        /// 소스 이미지 디렉토리 경로

        /// </summary>

        private string sourceImageDirectoryPath = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;

 

        /// <summary>

        /// 소스 이미지

        /// </summary>

        private Image sourceImage;

 

        /// <summary>

        /// 마우스 DOWN 포인트

        /// </summary>

        private Point mouseDownPoint = Point.Empty;

 

        /// <summary>

        /// 올가미 밧줄 사각형

        /// </summary>

        private Rectangle lassoRectangle = Rectangle.Empty;

 

        /// <summary>

        /// 확대/축소 퍼센트 변경 여부

        /// </summary>

        private bool zoomPercentChanged;

 

        /// <summary>

        /// 올가미 밧줄 펜

        /// </summary>

        private Pen lassoPen = new Pen(Color.Red);

 

        #endregion

 

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

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

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            #region 소스 이미지를 설정한다.

 

            this.sourceImage = Image.FromFile(this.sourceImageDirectoryPath + @"\sample.jpg");

 

            #endregion

            #region 소스 픽처 에디터를 설정한다.

 

            this.sourcePictureEdit.Properties.ShowZoomSubMenu         = DevExpress.Utils.DefaultBoolean.True;

            this.sourcePictureEdit.Properties.ShowScrollBars          = true;

            this.sourcePictureEdit.Properties.AllowScrollViaMouseDrag = false;

            this.sourcePictureEdit.EditValue                          = sourceImage;

 

            #endregion

            #region 그림 크기 모드 콤보 에디터를 설정한다.

 

            this.pictureSizeModeComboBoxEdit.Properties.Items.AddRange

            (

                new PictureSizeMode[]

                {

                    PictureSizeMode.Clip,

                    PictureSizeMode.Squeeze,

                    PictureSizeMode.Stretch,

                    PictureSizeMode.StretchHorizontal,

                    PictureSizeMode.StretchVertical,

                    PictureSizeMode.Zoom

                }

            );

 

            this.pictureSizeModeComboBoxEdit.SelectedIndex = 0;

 

            #endregion

            #region 이벤트를 설정한다.

 

            this.pictureSizeModeComboBoxEdit.EditValueChanged += pictureSizeModeComboBoxEdit_EditValueChanged;

 

            this.sourcePictureEdit.HScrollBar.ValueChanged += sourcePictureEdit_ScrollBar_ValueChanged;

            this.sourcePictureEdit.VScrollBar.ValueChanged += sourcePictureEdit_ScrollBar_ValueChanged;

            this.sourcePictureEdit.MouseDown               += sourcePictureEdit_MouseDown;

            this.sourcePictureEdit.MouseMove               += sourcePictureEdit_MouseMove;

            this.sourcePictureEdit.MouseUp                 += sourcePictureEdit_MouseUp;

            this.sourcePictureEdit.ZoomPercentChanged      += sourcePictureEdit_ZoomPercentChanged;

            this.sourcePictureEdit.Paint                   += sourcePictureEdit_Paint;

 

            #endregion

        }

 

        #endregion

 

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

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

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

 

        #region 그림 크기 모드 콤보 에디터 편집 값 변경시 처리하기 - pictureSizeModeComboBoxEdit_EditValueChanged(sender, e)

 

        /// <summary>

        /// 그림 크기 모드 콤보 에디터 편집 값 변경시 처리하기

        /// </summary>

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

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

        private void pictureSizeModeComboBoxEdit_EditValueChanged(object sender, EventArgs e)

        {

            ComboBoxEdit comboBoxEdit = sender as ComboBoxEdit;

 

            this.sourcePictureEdit.Properties.SizeMode = (PictureSizeMode)comboBoxEdit.EditValue;

 

            this.zoomPercentChanged = false;

        }

 

        #endregion

 

        #region 소스 픽처 에디터 스크롤바 값 변경시 처리하기 - sourcePictureEdit_ScrollBar_ValueChanged(sender, e)

 

        /// <summary>

        /// 소스 픽처 에디터 스크롤바 값 변경시 처리하기

        /// </summary>

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

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

        private void sourcePictureEdit_ScrollBar_ValueChanged(object sender, EventArgs e)

        {

            ResetLassoRectangle();

        }

 

        #endregion

        #region 소스 픽처 에디터 확대/축소 퍼센트 변경시 처리하기 - sourcePictureEdit_ZoomPercentChanged(sender, e)

 

        /// <summary>

        /// 소스 픽처 에디터 확대/축소 퍼센트 변경시 처리하기

        /// </summary>

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

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

        private void sourcePictureEdit_ZoomPercentChanged(object sender, EventArgs e)

        {

            this.zoomPercentChanged = true;

 

            ResetLassoRectangle();

        }

 

        #endregion

        #region 소스 픽처 에디터 마우스 DOWN 처리하기 - sourcePictureEdit_MouseDown(sender, e)

 

        /// <summary>

        /// 소스 픽처 에디터 마우스 DOWN 처리하기

        /// </summary>

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

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

        private void sourcePictureEdit_MouseDown(object sender, MouseEventArgs e)

        {

            if(e.Button != MouseButtons.Left)

            {

                return;

            }

 

            this.mouseDownPoint = e.Location;

 

            ResetLassoRectangle();

 

            PictureEdit pictureEdit = sender as PictureEdit;

 

            pictureEdit.Refresh();

        }

 

        #endregion

        #region 소스 픽처 에디터 마우스 이동시 처리하기 - sourcePictureEdit_MouseMove(object sender, MouseEventArgs e)

 

        /// <summary>

        /// 소스 픽처 에디터 마우스 이동시 처리하기

        /// </summary>

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

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

        private void sourcePictureEdit_MouseMove(object sender, MouseEventArgs e)

        {

            if(this.mouseDownPoint.IsEmpty)

            {

                return;

            }

 

            if(e.Button != MouseButtons.Left)

            {

                return;

            }

 

            Point mouseMovePoint = e.Location;

 

            if(CheckBoundRectangle(mouseMovePoint.X, mouseMovePoint.Y))

            {

                this.lassoRectangle = new Rectangle

                (

                    mouseDownPoint.X,

                    mouseDownPoint.Y,

                    mouseMovePoint.X - mouseDownPoint.X,

                    mouseMovePoint.Y - mouseDownPoint.Y

                );

 

                PictureEdit pictureEdit = sender as PictureEdit;

 

                pictureEdit.Refresh();

            }

        }

 

        #endregion

        #region 소스 픽처 에디터 마우스 UP 처리하기 - sourcePictureEdit_MouseUp(sender, e)

 

        /// <summary>

        /// 소스 픽처 에디터 마우스 UP 처리하기

        /// </summary>

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

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

        private void sourcePictureEdit_MouseUp(object sender, MouseEventArgs e)

        {

            PictureEdit pictureEdit = sender as PictureEdit;

 

            Point startPoint = ConvertPoint(pictureEdit, lassoRectangle.Location);

            Point endPoint   = ConvertPoint(pictureEdit , new Point(lassoRectangle.Right, lassoRectangle.Bottom));

 

            Rectangle selectedImageRectangle = new Rectangle

            (

                startPoint.X,

                startPoint.Y,

                endPoint.X - startPoint.X,

                endPoint.Y - startPoint.Y

            );

 

            if(selectedImageRectangle.Size.Width <= 0 || selectedImageRectangle.Size.Height <= 0)

            {

                return;

            }

 

            Bitmap selectedImage = new Bitmap(sourceImage);

 

            this.targetPictureEdit.EditValue = selectedImage.Clone(selectedImageRectangle, selectedImage.PixelFormat);

        }

 

        #endregion

        #region 소스 픽처 에디터 페인트시 처리하기 - sourcePictureEdit_Paint(sender, e)

 

        /// <summary>

        /// 소스 픽처 에디터 페인트시 처리하기

        /// </summary>

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

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

        private void sourcePictureEdit_Paint(object sender, PaintEventArgs e)

        {

            e.Graphics.DrawRectangle(this.lassoPen, this.lassoRectangle);

        }

 

        #endregion

 

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

 

        #region 올가미 밧줄 사각형 리셋하기 - ResetLassoRectangle()

 

        /// <summary>

        /// 올가미 밧줄 사각형 리셋하기

        /// </summary>

        private void ResetLassoRectangle()

        {

            this.lassoRectangle = Rectangle.Empty;

        }

 

        #endregion

        #region 테두리 사각형 체크하기 - CheckBoundRectangle(x, y)

 

        /// <summary>

        /// 테두리 사각형 체크하기

        /// </summary>

        /// <param name="x">X 좌표</param>

        /// <param name="y">Y 좌표</param>

        /// <returns>체크 결과</returns>

        private bool CheckBoundRectangle(int x, int y)

        {

            return x >= 0 && x < this.sourcePictureEdit.Image.Width && y >= 0 && y < this.sourcePictureEdit.Image.Height;

        }

 

        #endregion

        #region 포인트 변환하기 - ConvertPoint(pictureEdit, sourcePoint)

 

        /// <summary>

        /// 포인트 변환하기

        /// </summary>

        /// <param name="pictureEdit">픽처 에디터</param>

        /// <param name="sourcePoint">소스 포인트</param>

        /// <returns>변환 포인트</returns>

        private Point ConvertPoint(PictureEdit pictureEdit, Point sourcePoint)

        {

            Point targetPoint = Point.Empty;

 

            if(pictureEdit.Image != null)

            {

                PictureEditViewInfo viewInfo = pictureEdit.GetViewInfo() as PictureEditViewInfo;

 

                double zoomX = 1.0;

                double zoomY = 1.0;

 

                if(this.zoomPercentChanged && pictureEdit.Properties.SizeMode != PictureSizeMode.Squeeze)

                {

                    zoomX = zoomY = Convert.ToDouble(pictureEdit.Properties.ZoomPercent) / 100;

                }

                else

                {

                    switch(pictureEdit.Properties.SizeMode)

                    {

                        case PictureSizeMode.Zoom    :

                        case PictureSizeMode.Squeeze :

 

                            zoomX = zoomY = Convert.ToDouble(viewInfo.PictureScreenBounds.Width / pictureEdit.Image.Size.Width);

 

                            break;

 

                        case PictureSizeMode.Stretch :

 

                            zoomX = Convert.ToDouble(viewInfo.PictureScreenBounds.Width  / pictureEdit.Image.Size.Width );

                            zoomY = Convert.ToDouble(viewInfo.PictureScreenBounds.Height / pictureEdit.Image.Size.Height);

 

                            break;

 

                        case PictureSizeMode.StretchHorizontal :

 

                            zoomX = Convert.ToDouble(viewInfo.PictureScreenBounds.Width / pictureEdit.Image.Size.Width);

 

                            break;

 

                        case PictureSizeMode.StretchVertical :

 

                            zoomY = zoomY = Convert.ToDouble(viewInfo.PictureScreenBounds.Height / pictureEdit.Image.Size.Height);

 

                            break;

                    }

                }

 

                int scrollX = (pictureEdit.Controls[1] as DevExpress.XtraEditors.HScrollBar).Value;

                int scrollY = (pictureEdit.Controls[0] as DevExpress.XtraEditors.VScrollBar).Value;

 

                int x, y;

 

                if(pictureEdit.Controls[1].Visible == true)

                {

                    x = (int)((sourcePoint.X + scrollX - viewInfo.PictureScreenBounds.X) / zoomX);

                }

                else

                {

                    x = (int)((sourcePoint.X - viewInfo.PictureScreenBounds.X) / zoomX);

                }

 

                if(pictureEdit.Controls[0].Visible == true)

                {

                    y = (int)((sourcePoint.Y + scrollY - viewInfo.PictureScreenBounds.Y) / zoomY);

                }

                else

                {

                    y = (int)((sourcePoint.Y - viewInfo.PictureScreenBounds.Y) / zoomY);

                }

 

                targetPoint = new Point(x, y);

            }

 

            return targetPoint;

        }

 

        #endregion

    }

}

 

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

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요