using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SelectScaledImageRectangle
{
    public partial class frm40SelectScaledImageRectangle : Form
    {
        public frm40SelectScaledImageRectangle()
        {
            InitializeComponent();
        }

        // The original image.
        private Bitmap OriginalImage;

        // True when we're selecting a rectangle.
        private bool IsSelecting = false;

        // The drags starting point.
        private Point StartPoint;

        private void frm40SelectScaledImageRectangle_Load(object sender, EventArgs e)
        {
            sizeModeComboBox.Text = "AutoSize";
        }

        // Start selecting the rectangle.
        private void originalPictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            IsSelecting = true;

            // Copy the original image.
            OriginalImage = new Bitmap(originalPictureBox.Image);

            // Save the start point.
            StartPoint = ConvertPoint(originalPictureBox, e.Location);
        }

        // Continue selecting.
        private void originalPictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            // Do nothing it we're not selecting an area.
            if (!IsSelecting) return;

            // Make a Bitmap to display the selection rectangle.
            Bitmap bm = new Bitmap(OriginalImage);
            using (Graphics gr = Graphics.FromImage(bm))
            {
                // Draw the rectangle.
                Point currentPoint = ConvertPoint(originalPictureBox, e.Location);
                Rectangle rect = GetRectangle(StartPoint, currentPoint);
                using (Pen pen = new Pen(Color.Yellow, 3))
                {
                    gr.DrawRectangle(pen, rect);
                }
            }

            // Display the temporary bitmap.
            originalPictureBox.Image = bm;
        }

        // Finish selecting the area.
        private void originalPictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            // Do nothing it we're not selecting an area.
            if (!IsSelecting) return;
            IsSelecting = false;

            // Display the original image.
            originalPictureBox.Image = OriginalImage;

            // Copy the selected part of the image.
            Point currentPoint = ConvertPoint(originalPictureBox, e.Location);
            Rectangle rect = GetRectangle(StartPoint, currentPoint);
            Bitmap area = ImagePiece(OriginalImage, rect);

            // Display the result.
            resultPictureBox.Image = area;
            resultPictureBox.Show();
        }

        // Return a Rectangle with the two points as opposite corners.
        private Rectangle GetRectangle(Point point1, Point point2)
        {
            int x = Math.Min(point1.X, point2.X);
            int y = Math.Min(point1.Y, point2.Y);
            int width = Math.Abs(point2.X - point1.X);
            int height = Math.Abs(point2.Y - point1.Y);
            return new Rectangle(x, y, width, height);
        }

        // Return a piece of an image.
        private Bitmap ImagePiece(Bitmap bm, Rectangle sourceRect)
        {
            // Intersect the rectangle with the Bitmap's bounds.
            Rectangle bmRect = new Rectangle(0, 0, bm.Width, bm.Height);
            sourceRect.Intersect(bmRect);

            // Make sure the result has a positive size.
            if ((sourceRect.Width < 1) || (sourceRect.Height < 1)) return null;

            Bitmap piece = new Bitmap(sourceRect.Width, sourceRect.Height);
            using (Graphics gr = Graphics.FromImage(piece))
            {
                Rectangle destRect = new Rectangle(0, 0,
                    sourceRect.Width, sourceRect.Height);
                gr.DrawImage(OriginalImage, destRect,
                    sourceRect, GraphicsUnit.Pixel);
            }
            return piece;
        }

        // Change the PictureBox's SizeMode.
        private void sizeModeComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (sizeModeComboBox.SelectedItem.ToString())
            {
                case "AutoSize":
                    originalPictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
                    break;
                case "Normal":
                    originalPictureBox.SizeMode = PictureBoxSizeMode.Normal;
                    break;
                case "CenterImage":
                    originalPictureBox.SizeMode = PictureBoxSizeMode.CenterImage;
                    break;
                case "StretchImage":
                    originalPictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
                    break;
                case "Zoom":
                    originalPictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                    break;
            }

            // Set the PictureBox's size.
            if (originalPictureBox.SizeMode != PictureBoxSizeMode.AutoSize)
            {
                int width = int.Parse(sizeTextBox.Text.Split(',')[0]);
                int height = int.Parse(sizeTextBox.Text.Split(',')[1]);
                originalPictureBox.Size = new Size(width, height);
            }
            resultPictureBox.Left = originalPictureBox.Right + 6;
            resultPictureBox.Image = null;
        }

        // Convert the coordinates for the image's SizeMode.
        private Point ConvertPoint(PictureBox pic, Point point)
        {
            int picHgt = pic.ClientSize.Height;
            int picWid = pic.ClientSize.Width;
            int imgHgt = pic.Image.Height;
            int imgWid = pic.Image.Width;

            int x = point.X;
            int y = point.Y;
            switch (pic.SizeMode)
            {
                case PictureBoxSizeMode.AutoSize:
                case PictureBoxSizeMode.Normal:
                    // These are okay. Leave them alone.
                    break;
                case PictureBoxSizeMode.CenterImage:
                    x = point.X - (picWid - imgWid) / 2;
                    y = point.Y - (picHgt - imgHgt) / 2;
                    break;
                case PictureBoxSizeMode.StretchImage:
                    x = (int)(imgWid * point.X / (float)picWid);
                    y = (int)(imgHgt * point.Y / (float)picHgt);
                    break;
                case PictureBoxSizeMode.Zoom:
                    float picAspect = picWid / (float)picHgt;
                    float imgAspect = imgWid / (float)imgHgt;
                    if (picAspect > imgAspect)
                    {
                        // The PictureBox is wider/shorter than the image.
                        y = (int)(imgHgt * point.Y / (float)picHgt);

                        // The image fills the height of the PictureBox.
                        // Get its width.
                        float scaledWidth = imgWid * picHgt / imgHgt;
                        float dx = (picWid - scaledWidth) / 2;
                        x = (int)((point.X - dx) * imgHgt / (float)picHgt);
                    }
                    else
                    {
                        // The PictureBox is taller/thinner than the image.
                        x = (int)(imgWid * point.X / (float)picWid);

                        // The image fills the height of the PictureBox.
                        // Get its height.
                        float scaledHeight = imgHgt * picWid / imgWid;
                        float dy = (picHgt - scaledHeight) / 2;
                        y = (int)((point.Y - dy) * imgWid / picWid);
                    }
                    break;
            }

            return new Point(x, y);
        }


        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.resultPictureBox = new System.Windows.Forms.PictureBox();
            this.originalPictureBox = new System.Windows.Forms.PictureBox();
            this.label1 = new System.Windows.Forms.Label();
            this.sizeModeComboBox = new System.Windows.Forms.ComboBox();
            this.label2 = new System.Windows.Forms.Label();
            this.sizeTextBox = new System.Windows.Forms.TextBox();
            ((System.ComponentModel.ISupportInitialize)(this.resultPictureBox)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.originalPictureBox)).BeginInit();
            this.SuspendLayout();
            // 
            // resultPictureBox
            // 
            this.resultPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.resultPictureBox.Location = new System.Drawing.Point(318, 41);
            this.resultPictureBox.Name = "resultPictureBox";
            this.resultPictureBox.Size = new System.Drawing.Size(0, 0);
            this.resultPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.resultPictureBox.TabIndex = 5;
            this.resultPictureBox.TabStop = false;
            this.resultPictureBox.Visible = false;
            // 
            // originalPictureBox
            // 
            this.originalPictureBox.BackColor = System.Drawing.Color.LightBlue;
            this.originalPictureBox.Cursor = System.Windows.Forms.Cursors.Cross;
            this.originalPictureBox.Image = global::SelectScaledImageRectangle.Properties.Resources.EssentialAlgorithms;
            this.originalPictureBox.Location = new System.Drawing.Point(12, 41);
            this.originalPictureBox.Name = "originalPictureBox";
            this.originalPictureBox.Size = new System.Drawing.Size(300, 377);
            this.originalPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
            this.originalPictureBox.TabIndex = 4;
            this.originalPictureBox.TabStop = false;
            this.originalPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.originalPictureBox_MouseDown);
            this.originalPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.originalPictureBox_MouseMove);
            this.originalPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.originalPictureBox_MouseUp);
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(150, 15);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(57, 13);
            this.label1.TabIndex = 6;
            this.label1.Text = "SizeMode:";
            // 
            // sizeModeComboBox
            // 
            this.sizeModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.sizeModeComboBox.FormattingEnabled = true;
            this.sizeModeComboBox.Items.AddRange(new object[] {
            "AutoSize",
            "Normal",
            "CenterImage",
            "StretchImage",
            "Zoom"});
            this.sizeModeComboBox.Location = new System.Drawing.Point(213, 12);
            this.sizeModeComboBox.Name = "sizeModeComboBox";
            this.sizeModeComboBox.Size = new System.Drawing.Size(99, 21);
            this.sizeModeComboBox.TabIndex = 1;
            this.sizeModeComboBox.SelectedIndexChanged += new System.EventHandler(this.sizeModeComboBox_SelectedIndexChanged);
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(12, 15);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(30, 13);
            this.label2.TabIndex = 8;
            this.label2.Text = "Size:";
            // 
            // sizeTextBox
            // 
            this.sizeTextBox.Location = new System.Drawing.Point(48, 12);
            this.sizeTextBox.Name = "sizeTextBox";
            this.sizeTextBox.Size = new System.Drawing.Size(80, 20);
            this.sizeTextBox.TabIndex = 0;
            this.sizeTextBox.Text = "300, 250";
            this.sizeTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
            // 
            // frm40SelectScaledImageRectangle
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(406, 430);
            this.Controls.Add(this.sizeTextBox);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.sizeModeComboBox);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.resultPictureBox);
            this.Controls.Add(this.originalPictureBox);
            this.Name = "frm40SelectScaledImageRectangle";
            this.Text = "SelectScaledImageRectangle";
            this.Load += new System.EventHandler(this.frm40SelectScaledImageRectangle_Load);
            ((System.ComponentModel.ISupportInitialize)(this.resultPictureBox)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.originalPictureBox)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.PictureBox resultPictureBox;
        private System.Windows.Forms.PictureBox originalPictureBox;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.ComboBox sizeModeComboBox;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox sizeTextBox;
    }
}