using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.Structure;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
using System.Threading;

namespace Foto_Scanner_New
{
    /// <summary>
    /// Class for image processing of the detected photos.
    /// Basic pocessing functions: scale, rotate, graylevel, brightness, cropping.
    /// </summary>
    public partial class FotoDetail : Form
    {
        private System.ComponentModel.BackgroundWorker backgroundWorker1;

        // Image objects
        public List<Image<Bgr, Byte>> img = null;
        public Image<Bgr, Byte> imgTmp = null;
        public Image<Bgr, Byte> imgOrig = null;
        public Image<Bgr, Byte> imgTmp1 = null;
        public Image<Bgr, Byte> imgOld = null;
        Image<Gray, byte> grayImage = null;

        // HSV color space
        Image<Hsv, Byte> hsvimg = null;
        Image<Gray, Byte>[] channels = null;     //split into components
        Image<Gray, Byte> imghue = null;         //hsv, so channels[0] is hue.
        Image<Gray, Byte> imgsat = null;
        Image<Gray, Byte> imgval = null;         //hsv, so channels[2] is value.

        // Cropping - image coordinates
        int _left = -1;
        int _right = -1;
        int _w = 0;
        int _h = 0;
        int pixelG = 1;

        // Cropping - rectangle
        Rectangle r;
        bool breitformat = false;

        // Meta data
        double height = 0;
        double width = 0;

        // Save edited image
        string format = "";
        string workingDirPath = "";
        string path = "";

        //helper
        bool first = true;
        int VALUE = 0;
        Warten w = null;
        bool handlerReady = true;

        /// <summary>
        /// Shows detected photos.
        /// </summary>
        /// <param name="_imgs">List with detected images</param>
        /// <param name="workingDir">Current working directory</param>
        /// <param name="folder">Current folder (image name)</param>
        public FotoDetail(List<Image<Bgr, Byte>> _imgs, string workingDir, string folder)
        {
            InitializeComponent();
            
            this.img = _imgs;

            initComboBox();
            workingDirPath = workingDir;

            path = workingDir + folder;
            this.toolStripStatusLabel1.Text = "Arbeitsverzeichnis: " + workingDir + folder + "/";

            if (!Directory.Exists(path)) {
                Directory.CreateDirectory(path);
            }

            first = true;
        }

        /// <summary>
        /// Initialize CheckBox with photos.
        /// </summary>
        private void initComboBox()
        {
            int index = 0;
            foreach (Image<Bgr, Byte> imgs in img) {
                int indexNew = index + 1; 
                this.comboBoxPhotos.Items.Insert(index, "Foto " + indexNew);
                index++;
            }

            this.comboBoxPhotos.SelectedIndex = 0;
            this.updateValues(img[0],0);
            this.imgTmp = img[0].Copy();
            this.imgOrig = img[0].Copy(); ;

            _w = imgTmp.Width + 1;
            _h = imgTmp.Height + 1;

            this.updateValues(img[0], 0);
          
            // Format
            this.comboBox1.SelectedIndex = 0;
            this.format = comboBox1.Text;

            this.comboBoxPixel.SelectedIndex = 2;
            this.pixelG = Convert.ToInt32(this.comboBoxPixel.Items[comboBoxPixel.SelectedIndex].ToString());

        }

        /// <summary>
        /// Eventhanlder for selecting items in the combo box.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxPhotos_SelectedIndexChanged(object sender, EventArgs e)
        {
            _left = -1;
            _right = -1;
            _w = 0;
            _h = 0;

            // Edit image
            int itemIndex = comboBoxPhotos.SelectedIndex;
            this.pictureBoxDetail.Image = img[itemIndex].ToBitmap();
           
            this.imgTmp = img[itemIndex];
            this.imgOrig = img[itemIndex];

            this.updateValues(imgTmp, itemIndex);

            //checkBoxBW.Checked = false;
            this.trackBar1.Value = 0;

            first = true;
        }

        /// <summary>
        /// Gets the most important properties of tn image and sets the values.
        /// </summary>
        /// <param name="img">Image</param>
        public void updateValues(Image<Bgr, Byte> img, int itemIndex)
        {
            double width = img.Width;
            double height = img.Height;
            this.width = width;
            this.height = height;
            this.textBoxWidth.Text = width.ToString();
            this.textBoxHeight.Text = height.ToString();

            int name = itemIndex + 1;
            string nameTxt = Convert.ToString(name);
            this.textBoxName.Text = nameTxt;

            _left = -1;
            _right = -1;
            _w = imgTmp.Width + 1;
            _h = imgTmp.Height + 1;
        }

        /// <summary>
        /// Changes the size of the bounding rectangle.
        /// </summary>
        /// <param name="img">Image</param>
        public void editBox(Image<Bgr, Byte> tmp1, int left, int right, int w, int h, Bgr c)
        {
            int itemIndex = comboBoxPhotos.SelectedIndex;
            //this.imgTmp = img[itemIndex];

            if (Convert.ToInt16(textBoxHeight.Text) > Convert.ToInt16(textBoxWidth.Text)) 
                r = new Rectangle(left, right, h, w);
            else
                r = new Rectangle(left, right, w, h);
            //Console.Out.WriteLine("Rechteck " + r.ToString());
            tmp1.Draw(r, c, 3);
            this.pictureBoxDetail.Image = imgTmp1.ToBitmap(); this.pictureBoxDetail.Update();
        }

        /// <summary>
        /// Eventhandler - Rotate image.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            Image<Bgr, Byte> imgRot = this.imgOrig.Copy();

            double v = Convert.ToDouble(this.trackBar1.Value) / 2.0;
            imgRot = imgRot.Rotate(v, new Bgr(Color.Transparent));

            imgTmp = imgRot;

            this.pictureBoxDetail.Image = imgRot.ToBitmap();
            this.pictureBoxDetail.Update();

            _left = -1;
            _right = -1;

            _w = imgTmp.Width + 1;
            _h = imgTmp.Height + 1;
        }

        /// <summary>
        /// Eventhandler - Show original image (undo).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonBack_Click(object sender, EventArgs e)
        {
            //checkBoxBW.Checked = false;

            int itemIndex = comboBoxPhotos.SelectedIndex;
           
            this.updateValues(img[itemIndex],itemIndex);
            this.imgTmp = imgOrig.Copy(); ;
            
            this.trackBar1.Value = 0;
            this.comboBox1.SelectedIndex = 0;

            this.imgTmp = this.imgOrig;
            this.pictureBoxDetail.Image = this.imgTmp.ToBitmap();
            _left = -1;
            _right = -1;
     
            _w = imgTmp.Width + 1;
            _h = imgTmp.Height + 1;

            this.checkBoxBW.Checked = false;
            this.trackBar2.Value = 0;

            this.comboBoxPixel.SelectedIndex = 2;
            this.pixelG = Convert.ToInt32(this.comboBoxPixel.Items[comboBoxPixel.SelectedIndex].ToString());

            first = true;
        }

        /// <summary>
        /// Eventhandler - Rotate image right
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            first = false;

            double h = Convert.ToDouble(this.textBoxHeight.Text);
            double w = Convert.ToDouble(this.textBoxWidth.Text);

            this.textBoxWidth.Text = h.ToString();
            this.textBoxHeight.Text = w.ToString();
            
            string img = saveImage(this.textBoxName.Text, Convert.ToDouble(this.textBoxWidth.Text), Convert.ToDouble(this.textBoxHeight.Text), this.format, r, false);
            
            bool ok = CVUtils.runIV(img, "R", Convert.ToInt32(h), Convert.ToInt32(w));
            Image<Bgr, Byte> imgRotation = new Image<Bgr,byte>(img);
            
            this.pictureBoxDetail.Image = imgRotation.ToBitmap(); 
            this.pictureBoxDetail.Update();

            this.imgTmp = imgRotation;

            _left = -1;
            _right = -1;

            if (imgTmp.Width >= imgTmp.Height)
            {
                _w = imgTmp.Width + 1;
                _h = imgTmp.Height + 1;
            }
            else
            {
                _w = imgTmp.Height + 1;
                _h = imgTmp.Width + 1;
            }
        }

        /// <summary>
        /// Eventhandler - Rotate image left.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            first = false;

            double h = Convert.ToDouble(this.textBoxHeight.Text);
            double w = Convert.ToDouble(this.textBoxWidth.Text);

            this.textBoxWidth.Text = h.ToString();
            this.textBoxHeight.Text = w.ToString();

            string img = saveImage(this.textBoxName.Text, Convert.ToDouble(this.textBoxWidth.Text), Convert.ToDouble(this.textBoxHeight.Text), this.format, r, false);
            
            bool ok = CVUtils.runIV(img, "L", Convert.ToInt32(h), Convert.ToInt32(w));
            Image<Bgr, Byte> imgRotation = new Image<Bgr, byte>(img);

            //imgRotation.Draw(rr, new Bgr(Color.Red), 3);
            this.pictureBoxDetail.Image = imgRotation.ToBitmap();
            this.pictureBoxDetail.Update();

            this.imgTmp = imgRotation;

            // refreh rect

            _left = -1;
            _right = -1;

            if (imgTmp.Width >= imgTmp.Height)
            {
                _w = imgTmp.Width + 1;
                _h = imgTmp.Height + 1;
            }
            else {
                _w = imgTmp.Height + 1;
                _h = imgTmp.Width + 1;
            }

        }

        /// <summary>
        /// Eventhandler - Crop image (smaller).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
           
            //checkBoxBW.Checked = false;

            if (pixelG == 1)
            {
                _left = _left + 1;
                _right = _right + 1;

                _w = _w - 2;
                _h = _h - 2;
            }
            else {
                _left = _left + pixelG;
                _right = _right + pixelG;

                _w = _w - (pixelG*2);
                _h = _h - (pixelG*2);
            }


            Bgr color = new Bgr(Color.Red);
            imgTmp1 = new Image<Bgr, byte>(imgTmp.Width, imgTmp.Height);
            imgTmp.CopyTo(imgTmp1);

            if (imgTmp.Height >= imgTmp.Width && first)
            {
                editBox(this.imgTmp1, _left, _right, _h, _w, color);
            }
            else {
                //orig
                editBox(this.imgTmp1, _left, _right, _w, _h, color);
            }
        }

        /// <summary>
        /// Eventhandler - Crop image (bigger).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonMinus_Click(object sender, EventArgs e)
        {
            //checkBoxBW.Checked = false;

            double H = Convert.ToDouble(this.textBoxHeight.Text);
            double W = Convert.ToDouble(this.textBoxWidth.Text);

            int Y = 0;
            if (imgTmp.Width >= imgTmp.Height) { Y = imgTmp.Width; }
            else { Y = imgTmp.Height; }

            //if ( (_left + _w) <= (Y - pixelG))

            if (_left >= pixelG && _right >= pixelG && ((_left + _w) <= (Y - pixelG)) )
            {
                Bgr colorTrans = new Bgr(Color.Red);

                imgTmp1 = new Image<Bgr, byte>(imgTmp.Width, imgTmp.Height);
                imgTmp.CopyTo(imgTmp1);

                if (imgTmp.Height >= imgTmp.Width && first)
                {
                    editBox(this.imgTmp1, _left, _right, _h, _w, colorTrans);
                }
                else
                {
                    //orig
                    editBox(this.imgTmp1, _left, _right, _w, _h, colorTrans);
                }

                //editBox(imgTmp1, _left, _right, _w, _h, colorTrans);

                if (pixelG == 1)
                {
                    _left = _left - 1;
                    _right = _right - 1;
                    _w = _w + 2;
                    _h = _h + 2;
                }
                else {
                    _left = _left - pixelG;
                    _right = _right - pixelG;
                    _w = _w + (2*pixelG);
                    _h = _h + (2*pixelG);
                }
            }
        }

        /// <summary>
        /// Change output format.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.format = comboBox1.Text;   
        }

        /// <summary>
        /// Eventhandler - Save image and translations to disk.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSave_Click(object sender, EventArgs e)
        {
            //Console.Out.WriteLine("-- Save Image --");
            string name = saveImage(this.textBoxName.Text, Convert.ToDouble(this.textBoxWidth.Text), Convert.ToDouble(this.textBoxHeight.Text), this.format, r, true);

            // Change text
            int indexNow = this.comboBoxPhotos.SelectedIndex;
            try
            {
                if (!comboBoxPhotos.Items[indexNow].ToString().Contains("savd"))
                comboBoxPhotos.Items[indexNow] = comboBoxPhotos.Items[indexNow].ToString() + " - (saved)";
            }
            catch (Exception e1)
            { }
            
            // New image
            if (this.comboBoxPhotos.Items.Count >= 2) 
            {
                int newIndex = comboBoxPhotos.SelectedIndex + 1;

                if (newIndex < comboBoxPhotos.Items.Count)
                {
                    this.comboBoxPhotos.SelectedIndex = newIndex;

                }
            }

            r = new Rectangle(0,0,0,0);
        }

        /// <summary>
        /// Eventhandler - Convert to black white image.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void checkBoxBW_CheckedChanged(object sender, EventArgs e)
        {
            imgOld = imgTmp.Copy();

            if (checkBoxBW.Checked) { 
                grayImage = imgTmp.Convert<Gray, byte>();
                this.pictureBoxDetail.Image = grayImage.ToBitmap();
                this.pictureBoxDetail.Update();
            }

            else if (!checkBoxBW.Checked)
            {
                this.imgTmp = imgOld;
                this.pictureBoxDetail.Image = imgOld.ToBitmap() ;
                this.pictureBoxDetail.Update();
            }
          
        }

        /// <summary>
        /// Saves image to files syste,
        /// </summary>
        /// <param name="_name">Name of image</param>
        /// <param name="_width">Width of image</param>
        /// <param name="_height">Height of image</param>
        /// <param name="_format">Format og image</param>
        /// <param name="_boundingBox">RIO of image</param>
        /// <param name="_msg">Show message</param>
        private string saveImage(string _name, double _width, double _height, string _format, Rectangle boundingBox, bool msg)
        {
            int boxLeft = boundingBox.X;
            int boxRight = boundingBox.Y;
            string newpath = path + "/" + _name;
            string formatName = "";

            // Convert to output format
            if (format.Equals(".jpg")){
                //Console.Out.WriteLine("JPG");
                newpath = newpath + ".jpg";
                formatName = ".jpg";
            }
            else if (format.Equals(".png")){
                //Console.Out.WriteLine("PNG");
                newpath = newpath + ".png";
                formatName = ".png";
            }
            else if (format.Equals(".bmp")){
                //Console.Out.WriteLine("PNG");
                newpath = newpath + ".bmp";
                formatName = ".bmp";
            }

            Console.Out.WriteLine("  -> IMG: " + imgTmp.Size);
            Console.Out.WriteLine("  -> REC: " + r.Size);

            // Gray image
            if (this.checkBoxBW.Checked) {
                // Ret == null
                if (boundingBox.X == 0 && boundingBox.Y == 0 && boundingBox.Width == 0 && boundingBox.Height == 0)
                {
                    // Save
                    grayImage = grayImage.Resize(Convert.ToInt32(textBoxWidth.Text), Convert.ToInt32(textBoxHeight.Text), Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
                    grayImage.Save(newpath);
                }
                // Ret != null
                else
                {
                    //Rectangle r = new Rectangle(boundingBox.X + 1, boundingBox.Y + 1, boundingBox.Width - 1, boundingBox.Height - 1);
                    try
                    {
                        grayImage = grayImage.GetSubRect(r);
                    }
                    catch (Exception e2) {
                        MessageBox.Show("Gewählter Bereich (Rechteck) ungültig\nOriginalgröße wurde gespeichert!", "Warnung", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }

                    grayImage.Resize(Convert.ToInt32(textBoxWidth.Text), Convert.ToInt32(textBoxHeight.Text), Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
                    grayImage.Save(newpath);
                        
                }
            } 
            else 
            {
                // Ret == null
                if (boundingBox.X == 0 && boundingBox.Y == 0 && boundingBox.Width == 0 && boundingBox.Height == 0)
                {
                    // Save
                    imgTmp = imgTmp.Resize(Convert.ToInt32(textBoxWidth.Text), Convert.ToInt32(textBoxHeight.Text), Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
                    imgTmp.Save(newpath);
                }
                // Ret != null
                else 
                {
                    Rectangle rSave = new Rectangle();

                    if (this.imgTmp.Width >= this.imgTmp.Height) breitformat = true;
                    else breitformat = false;
                    if (breitformat) {
                        rSave = new Rectangle();
                        rSave.X = r.X;
                        rSave.Y = r.Y;

                        int _wi = Math.Max(r.Width, r.Height);
                        int _he = Math.Min(r.Width, r.Height);
                        rSave.Width = _wi;
                        rSave.Height = _he;
                    }
                    else if (!breitformat) {
                        rSave = new Rectangle();
                        rSave.X = r.X;
                        rSave.Y = r.Y;

                        int _wi = Math.Min(r.Width, r.Height);
                        int _he = Math.Max(r.Width, r.Height);
                        rSave.Width = _wi;
                        rSave.Height = _he;
                    }
                   
                    //Image<Bgr, Byte> tmpShow = this.imgTmp.Copy();
                    //mpShow.Draw(r, new Bgr(Color.Red), 3);
                    //this.pictureBoxDetail.Image = tmpShow.ToBitmap();
                    //this.pictureBoxDetail.Update();

                    // Save
                    try
                    {
                        imgTmp = imgTmp.GetSubRect(rSave);
                    }
                    catch 
                    {
                        MessageBox.Show("Gewählter Bereich (Rechteck) ungültig\nOriginalgröße wurde gespeichert!", "Warnung", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    }
                    imgTmp.Resize(Convert.ToInt32(textBoxWidth.Text), Convert.ToInt32(textBoxHeight.Text), Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR);
                    imgTmp.Save(newpath);
                }
            }
            
            //Console.Out.WriteLine("Paht  :" + path);
            //Console.Out.WriteLine("Width :" + _width);
            //Console.Out.WriteLine("Height:" + _height);
            //Console.Out.WriteLine("Format:" + _format);
            //Console.Out.WriteLine("Rect :" + boundingBox.ToString());
            //Console.Out.WriteLine("Rect :" + boundingBox.X);
            //Console.Out.WriteLine("Rect :" + boundingBox.Y);
            //Console.Out.WriteLine("Rect :" + boundingBox.Width);
            
            string text = "Bild wurde gespeichert unter: " + _name + formatName + "\n" + workingDirPath; 
            if (msg)
                MessageBox.Show(text,"Bild speichern", MessageBoxButtons.OK, MessageBoxIcon.Information);
            
            // Use next image
            int items = comboBox1.Items.Count;
            int now = comboBox1.SelectedIndex;

            return newpath;
        }

        /// <summary>
        /// Validate entered value for height.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxHeight_Validating(object sender, CancelEventArgs e)
        {
            string errorMsg;
            if (!validDoble(textBoxHeight.Text, out errorMsg))
            {
                // Cancel the event and select the text to be corrected by the user.
                e.Cancel = true;
                textBoxHeight.Select(0, textBoxHeight.Text.Length);

                // Set the ErrorProvider error with the text to display. 
                this.errorProvider1.SetError(textBoxHeight, errorMsg);
            }
            else
            {
                this.errorProvider1.SetError(textBoxHeight, "");

                //Calculate Value
            }
        }

        /// <summary>
        /// Checks if value is integer.
        /// </summary>
        /// <param name="wert">Value</param>
        /// <param name="errorMessage">Erros message</param>
        /// <returns>True if bool, else otherwise</returns>
        public bool validDoble(string wert, out string errorMessage)
        {
            if (wert.Length == 0)
            {
                errorMessage = "Bitte Betrag eingeben.";
                return false;
            }

            if (wert.Equals("0"))
            {
                errorMessage = "Bitte positiven Wert eingeben.";
                return false;
            }

            if (!checkInt(wert))
            {
                errorMessage = "Eingegebener Betrag ist ungültig.";
                return false;
            }
            else
            {
                errorMessage = "";
                return true;
            }
        }

        /// <summary>
        /// Checks if value in integer
        /// </summary>
        /// <param name="val">Value</param>
        /// <returns>True if integer</returns>
        public static bool checkInt(string val)
        {
            Regex isnumber = new Regex("[^0-9]");

            bool ok = false;
            ok = (!isnumber.IsMatch(val));

            return ok;
        }

        /// <summary>
        /// Validate entered value for widrh.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxWidth_Validating(object sender, CancelEventArgs e)
        {
            string errorMsg;
            if (!validDoble(textBoxWidth.Text, out errorMsg))
            {
                // Cancel the event and select the text to be corrected by the user.
                e.Cancel = true;
                textBoxHeight.Select(0, textBoxWidth.Text.Length);

                // Set the ErrorProvider error with the text to display. 
                this.errorProvider1.SetError(textBoxWidth, errorMsg);
            }
            else
            {
                this.errorProvider1.SetError(textBoxWidth, "");
            }
        }

        /// <summary>
        /// Calidate textBoc file name.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxName_Validating(object sender, CancelEventArgs e)
        {
            string errorMsg;
            if (!validFileName(textBoxName.Text, out errorMsg))
            {
                // Cancel the event and select the text to be corrected by the user.
                e.Cancel = true;
                textBoxName.Select(0, textBoxName.Text.Length);

                // Set the ErrorProvider error with the text to display. 
                this.errorProvider3.SetError(textBoxName, errorMsg);
            }
            else
            {
                this.errorProvider3.SetError(textBoxName, "");
            }
        }

        /// <summary>
        /// Checks if file name is correct.
        /// </summary>
        /// <param name="wert">Value</param>
        /// <param name="errorMessage">Erros message</param>
        /// <returns>True if bool, else otherwise</returns>
        public bool validFileName(string wert, out string errorMessage)
        {
            if (wert.Length == 0)
            {
                errorMessage = "Bitte Namen eingeben.";
                return false;
            }

            if (!checkName(wert))
            {
                errorMessage = "Eingegebener Name ist nicht gültig (keine Sonderzeichen).";
                return false;
            }
            else
            {
                errorMessage = "";
                return true;
            }
        }

        /// <summary>
        /// Checks if file name is ok (regex)
        /// </summary>
        /// <param name="val">Value</param>
        /// <returns>True if integer</returns>
        public static bool checkName(string val)
        {
            Regex isname = new Regex("^[a-zA-Z0-9._ -]+$");

            bool ok = false;
            ok = (isname.IsMatch(val));

            return ok;
        }

        /// <summary>
        /// Change value of height textbox.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxHeight_Leave(object sender, EventArgs e)
        {
            double widthNew = 0;
            try
            {
                int change = Convert.ToInt32(this.textBoxHeight.Text);

                if (this.checkBoxVerh.Checked)
                {
                    double faktor = this.height / change;
                    widthNew = (this.width / faktor);
                    int withNewInt = Convert.ToInt32(widthNew);
                    this.textBoxWidth.Text = withNewInt.ToString();

                }
            }
            catch (Exception r) { }
        }

        /// <summary>
        /// Change value of width textbox.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBoxWidth_Leave(object sender, EventArgs e)
        {
            double heihgtNew = 0;
            try
            {
                int change = Convert.ToInt32(this.textBoxWidth.Text);

                if (this.checkBoxVerh.Checked)
                {
                    double faktor = this.width / change;
                    heihgtNew = (this.height / faktor);
                    int heightNewInt = Convert.ToInt32(heihgtNew);
                    this.textBoxHeight.Text = heightNewInt.ToString();

                }
            }
            catch (Exception r) { }
        }

        /// <summary>
        /// Send image to IrvanView and open it.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click_1(object sender, EventArgs e)
        {
            string img = saveImage(this.textBoxName.Text, Convert.ToDouble(this.textBoxWidth.Text), Convert.ToDouble(this.textBoxHeight.Text), this.format, r, true);
             
            bool ok = CVUtils.runIV(img, "", 0, 0);

            if (ok == false) {
                MessageBox.Show("IrvanView konnte nicht geöffnet werden!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Handler - Copy image
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void groupBox3_Enter(object sender, EventArgs e)
        {
            Image<Bgr, Byte> imgNow = this.imgTmp.Copy();
        }

        /// <summary>
        /// Eventhandler - Convert image to HSV color space.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trackBar2_Enter(object sender, EventArgs e)
        {
            hsvimg = imgTmp.Convert<Hsv, Byte>();

            channels = hsvimg.Split();    //split into components
            imghue = channels[0];         //hsv, so channels[0] is hue.
            imgsat = channels[1];
            imgval = channels[2];         //hsv, so channels[2] is value.
        }

        /// <summary>
        /// Change brightness of image in hsv.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trackBar2_MouseUp(object sender, MouseEventArgs e)
        {
            if (handlerReady)
            {
                VALUE = this.trackBar2.Value;
                Image<Hsv, Byte> hsvIMG = new Image<Hsv, byte>(imgTmp.Width, imgTmp.Height);
                backgroundWorker2.RunWorkerAsync(hsvIMG);

                // Progressbar
                this.toolStripProgressBar1.Maximum = imgTmp.Width;

                /*
                double min = -1;
                for (int i = 0; i < hsvimg.Width; i++)
                {
                    for (int j = 0; j < hsvimg.Height; j++)
                    {
                    
                        double _hue = imghue[j, i].Intensity;
                        double _sat = imgsat[j,i].Intensity;
                    
                        double newval = imgval[j, i].Intensity + this.trackBar2.Value;
                        if (newval >= 255) newval = 254.0;
                        if (newval <= 0) newval = 0.0;

                        double _val = newval;

                        if (_val > min) min = _val;

                        Hsv hsv = new Hsv(_hue, _sat, _val);

                        hsvIMG[j, i] = hsv;

                    }
                }

                Console.Out.WriteLine("weiter");
                this.imgTmp = hsvIMG.Convert<Bgr, Byte>();
                Image<Bgr, Byte> imgTmp1 = this.imgTmp.Copy();
                imgTmp1.Draw(r, new Bgr(Color.Red), 3);

                this.pictureBoxDetail.Image = imgTmp1.ToBitmap();
                 * 
                 * */
            }
        }

        /// <summary>
        /// Handler - Open explorer
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            //tring path = workingDir + folder + "/";
            if (Directory.Exists(path))
            {
                try
                {
                    Console.Out.WriteLine(path);
                    string pathN = path.Replace("/", "\\");
                    Process.Start("explorer.exe", pathN);
                }
                catch (Exception e1)
                { 
                    MessageBox.Show("Explorer konnte nicht geöffnet werden!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            
                }
            }
        }

        /// <summary>
        /// Eventhandler - Set pixel size
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBoxPixel_SelectedIndexChanged(object sender, EventArgs e)
        {
            pixelG = Convert.ToInt32(comboBoxPixel.Items[comboBoxPixel.SelectedIndex].ToString());
            Console.Out.WriteLine(pixelG);
        }

        /// <summary>
        /// Eventhandler - Crop Left
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonL_Click(object sender, EventArgs e)
        {
            if (_left >= pixelG)
            {
                _left = _left - pixelG;

                Bgr colorTrans = new Bgr(Color.Red);
                imgTmp1 = new Image<Bgr, byte>(imgTmp.Width, imgTmp.Height);
                imgTmp.CopyTo(imgTmp1);

                editBox(imgTmp1, _left, _right, _w, _h, colorTrans);
            }
        }

        /// <summary>
        /// Eventhandler - Crop Right
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonR_Click(object sender, EventArgs e)
        {
            int Y = 0;
            if (imgTmp.Width >= imgTmp.Height) { Y = imgTmp.Width; }
            else { Y = imgTmp.Height; }

            if ( (_left + _w) <= (Y - pixelG))
            {
                _left = _left + pixelG;

                Bgr colorTrans = new Bgr(Color.Red);
                imgTmp1 = new Image<Bgr, byte>(imgTmp.Width, imgTmp.Height);
                imgTmp.CopyTo(imgTmp1);

                editBox(imgTmp1, _left, _right, _w, _h, colorTrans);
            }

        }

        /// <summary>
        /// Eventhandler - Crop Oben
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonO_Click(object sender, EventArgs e)
        {
            if (_right >= pixelG)
            {
                _right = _right - pixelG;

                Bgr colorTrans = new Bgr(Color.Red);
                imgTmp1 = new Image<Bgr, byte>(imgTmp.Width, imgTmp.Height);
                imgTmp.CopyTo(imgTmp1);

                editBox(imgTmp1, _left, _right, _w, _h, colorTrans);
            }
        }

        /// <summary>
        /// Eventhandler - Crop Unten
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonU_Click(object sender, EventArgs e)
        {
            int X = 0;
            if (imgTmp.Width >= imgTmp.Height) { X = imgTmp.Width; }
            else { X = imgTmp.Height; }

            if (((_right + _h) <= (imgTmp.Height - this.pixelG)) && ( ((_right + _w)) <= ( X - pixelG) ))
            {
                _right = _right + pixelG;

                Bgr colorTrans = new Bgr(Color.Red);
                imgTmp1 = new Image<Bgr, byte>(imgTmp.Width, imgTmp.Height);
                imgTmp.CopyTo(imgTmp1);

                editBox(imgTmp1, _left, _right, _w, _h, colorTrans);

            }
        }

        /// <summary>
        /// Eventhanderl - BackgrounWorker
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            handlerReady = false;

            backgroundWorker2.WorkerReportsProgress = true;
        
            Thread.Sleep(100);

            int time = hsvimg.Width * hsvimg.Height;
            int fac = Convert.ToInt32(time / 100);

            //Warten w = new Warten(time);
            //w.Show();
            
            Image<Hsv, Byte> hsvIMG = (Image<Hsv, Byte>)e.Argument;
            
            double min = -1;
            for (int i = 0; i < hsvimg.Width; i++)
            {
                backgroundWorker2.ReportProgress(i);

                if (i % 300 == 0) { Thread.Sleep(10); Console.Out.WriteLine("sleep"); }

                for (int j = 0; j < hsvimg.Height; j++)
                {
                   
                    double _hue = imghue[j, i].Intensity;
                    double _sat = imgsat[j,i].Intensity;

                    double newval = imgval[j, i].Intensity + VALUE;
                    if (newval >= 255) newval = 254.0;
                    if (newval <= 0) newval = 0.0;

                    double _val = newval;

                    if (_val > min) min = _val;

                    Hsv hsv = new Hsv(_hue, _sat, _val);
                    hsvIMG[j, i] = hsv;
                }
                
            }
            
            Thread.Sleep(300);
  
            this.imgTmp = hsvIMG.Convert<Bgr, Byte>();
            Image<Bgr, Byte> imgTmp1 = this.imgTmp.Copy();
            imgTmp1.Draw(r, new Bgr(Color.Red), 3);

            this.pictureBoxDetail.Image = imgTmp1.ToBitmap();

            e.Result = hsvIMG;
            handlerReady = true;
            //w.Close();
        }

        private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            //Console.Out.WriteLine(e.ProgressPercentage);
            //Console.Out.WriteLine(toolStripProgressBar1.Maximum);

            if (e.ProgressPercentage+1 == (toolStripProgressBar1.Maximum))
                toolStripProgressBar1.Value = 0;
            else
                toolStripProgressBar1.Value = e.ProgressPercentage;
           
        }

    }
}
