/// <summary>
        ///     Function that initializes the program.
        ///     loads the image into data manager as a byte array.
        /// </summary>
        public MediaCompression() {
            InitializeComponent();
            //init Data wrapper class
            MPEGData = new List<DataManager>();
            Manager = new DataManager();
            DataManager mpegManager1 = new DataManager();
            DataManager mpegManager2 = new DataManager();
            MPEGData.Add(mpegManager1);
            MPEGData.Add(mpegManager2);

            //init the split container
            splitContainer.SplitterWidth = 1;
            splitContainer.SplitterDistance = splitContainer.Width/2;

            contextMenuStrip1.Items.Add(new ToolStripButton("Compress Image"));
            contextMenuStrip2.Items.Add(new ToolStripButton("Set Image"));
            contextMenuStrip1.Items.Add(new ToolStripButton("Set Image"));
            contextMenuStrip1.Items.Add(new ToolStripButton("Clear"));
            contextMenuStrip2.Items.Add(new ToolStripButton("Clear"));
            contextMenuStrip2.Items.Add(new ToolStripButton("Open Compressed"));

            contextMenuStrip1.ItemClicked += HandleLeftContext;
            contextMenuStrip2.ItemClicked += HandleRightContext;

            // Tests
            //Tester.TestZigZag();
            //Tester.TestDCT_Quantize();
            Tester.TestWhole();
        }
        /// <summary>
        ///     Performs the search on two lists using two managers which contain data
        ///     about two images.
        /// </summary>
        /// <param name="manager">data on prev frame</param>
        /// <param name="manager2">data on new frame</param>
        /// <returns></returns>
        public static List<Tuple<Point, Point>> Search(DataManager manager, DataManager manager2) {
            List<Tuple<Point, Point>> mvs = new List<Tuple<Point, Point>>();

            for (int oi = 0; oi < manager.LumList.Count; oi += 16) {
                for (int oj = 0; oj < manager.LumList.Count; oj += 16) {
                    List<List<float>> C = manager.LumList.GetSquare(oi, oj, 16);
                    List<List<float>> R = manager2.LumList.GetSquare(oi, oj, 16);
                    List<List<float>> checkBlock = C.GetSquare(4, 4, 8);
                    float mad = MeanDifference(checkBlock, R, 8, 4, 4);
                    Point sp = new Point(oi + 4, oj + 4);
                    Point ep = new Point(oi + 4, oj + 4);

                    for (int i = 0; i < oi + 8; i++) {
                        for (int j = 0; j < oj + 8; j++) {
                            float nmad = MeanDifference(checkBlock, R, 8, i, j);
                            if (nmad < mad) {
                                mad = nmad;
                                ep = new Point(i + oi, j + oj);
                            }
                        }
                    }
                    mvs.Add(new Tuple<Point, Point>(sp, ep));
                }
            }

            Bitmap map1 = new Bitmap(manager.LumList.Count, manager.LumList.Count);
            Bitmap map2 = new Bitmap(manager2.LumList.Count, manager2.LumList.Count);

            for (int i = 0; i < map1.Height; i++) {
                for (int j = 0; j < map1.Width; j++) {
                    map1.SetPixel(i, j, Color.FromArgb((int) manager.LumList[i][j], 0, 0, 0));
                    map2.SetPixel(i, j, Color.FromArgb((int) manager2.LumList[i][j], 0, 0, 0));
                }
            }
            using (Graphics g = Graphics.FromImage(map1)) {
                Pen p = Pens.AliceBlue;
                foreach (Tuple<Point, Point> mv in mvs) {
                    g.DrawLine(p, mv.Item1, mv.Item2);
                }
            }

            manager.box.Image = map1;
            manager2.rbox.Image = map2;

            return mvs;
        }
 /// <summary>
 ///     Constructor for DCT image Processor
 /// </summary>
 /// <param name="manager">The data manager that contains the program's data</param>
 public DctImageProcessor(DataManager manager) {
     Manager = manager;
 }
        /// <summary>
        ///     Loads output.dct
        ///     initializes data
        ///     uses DctImageProcessor::UncoProcess
        ///     in a thread to display a JPEG image
        /// </summary>
        /// <param name="sender">c# params</param>
        /// <param name="e">c# params</param>
        private void openCompressedToolStripMenuItem_Click(object sender, EventArgs e) {
            if (FOpen.ShowDialog() != DialogResult.OK)
                return;
            try {
                Stream raw = FOpen.OpenFile();
                using (MemoryStream ms = new MemoryStream()) {
                    raw.CopyTo(ms);
                    Manager = new DataManager();

                    leftPicture.Image = null;
                    rightPicture.Image = null;
                    Manager.LoadedData = ms.ToArray().Select(s=>(sbyte)s).ToArray();
                    SetSizeToolStrip(Manager.LoadedData.Length);
                    Manager.box = leftPicture;
                    Manager.rbox = rightPicture;
                }
            }
            catch (Exception ex) {
                MessageBox.Show(@"Error: Could not read file from disk. Original error: " + ex.Message);
            }

            DctImageProcessor processor = new DctImageProcessor(Manager);
            Task.Run(()=>processor.UndoProcess());
        }
        private void HandleRightContext(object sender, ToolStripItemClickedEventArgs e) {
            if(e.ClickedItem.Text == @"Set Image") {
                contextMenuStrip2.Hide();
                SetRightImage();
            }else if (e.ClickedItem.Text == @"Open Compressed") {
                contextMenuStrip2.Hide();
                if(FOpen.ShowDialog() != DialogResult.OK)
                    return;
                try {
                    Stream raw = FOpen.OpenFile();
                    using(MemoryStream ms = new MemoryStream()) {
                        raw.CopyTo(ms);
                        Manager = new DataManager();

                        leftPicture.Image = null;
                        rightPicture.Image = null;
                        Manager.LoadedData = ms.ToArray().Select(s => (sbyte)s).ToArray();
                        SetSizeToolStrip(Manager.LoadedData.Length);
                        Manager.box = leftPicture;
                        Manager.rbox = rightPicture;
                    }
                } catch(Exception ex) {
                    MessageBox.Show(@"Error: Could not read file from disk. Original error: " + ex.Message);
                }

                DctImageProcessor processor = new DctImageProcessor(Manager);
                Task.Run(() => processor.UndoProcess());
            } else {
                contextMenuStrip2.Hide();
                RightImageClear();
            }
        }
        /// <summary>
        ///     Method to decompress MPEG
        ///     opens a file selector
        ///     reads data
        ///     initializes its data
        ///     sends it off to DctImageProcessor::UntoRippeg function
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void decompressToolStripMenuItem2_Click(object sender, EventArgs e) {
            if (FOpen.ShowDialog() != DialogResult.OK)
                return;
            try {
                Stream raw = FOpen.OpenFile();
                using (MemoryStream ms = new MemoryStream()) {
                    raw.CopyTo(ms);
                    MPEGData[0] = new DataManager();

                    leftPicture.Image = null;
                    rightPicture.Image = null;
                    MPEGData[0].LoadedData = ms.ToArray().Select(s => (sbyte)s).ToArray();
                    SetSizeToolStrip(MPEGData[0].LoadedData.Length);
                    MPEGData[0].box = leftPicture;
                }
            }
            catch (Exception ex) {
                MessageBox.Show(@"Error: Could not read file from disk. Original error: " + ex.Message);
            }

            DctImageProcessor processor = new DctImageProcessor(MPEGData[0]);

            await Task.Run(() => processor.UndoRippeg());

            //now we just have to use the vector info to move blocks around.
            Bitmap newmap = new Bitmap(MPEGData[0].ImageSize, MPEGData[0].ImageSize);

            for (int i = 0; i < MPEGData[0].ImageSize; i++) {
                for (int j = 0; j < MPEGData[0].ImageSize; j++) {
                    newmap.SetPixel(i, j, MPEGData[0].UncutBitmap.GetPixel(i, j));
                }
            }

            using (Graphics g = Graphics.FromImage(newmap)) {
                Pen p2 = new Pen(Color.White, 1);
                Pen p = new Pen(Color.Black, 2);
                foreach (Tuple<Point, Point> mV in MPEGData[0].MVs) {
                    for (int i = 0; i < 16; i++) {
                        for (int j = 0; j < 16; j++) {
                            newmap.SetPixel(
                                i + mV.Item2.X, j + mV.Item2.Y,
                                MPEGData[0].UncutBitmap.GetPixel(i + mV.Item1.X, j + mV.Item1.Y)
                                );
                        }
                    }
                    g.DrawLine(p, mV.Item1, mV.Item2);
                    g.DrawLine(p2, mV.Item1, mV.Item2);
                }
            }

            rightPicture.Image = Padder.CropImage(newmap,
                new Rectangle(0, 0, MPEGData[0].RealWidth, MPEGData[0].RealHeight));
        }
        private void loadFirstFileToolStripMenuItem_Click(object sender, EventArgs e) {
            if (FOpen.ShowDialog() != DialogResult.OK)
                return;
            try {
                MPEGData[0] = new DataManager();
                Image image = Image.FromStream(FOpen.OpenFile());
                MPEGData[0].SetLeftPicture(image);
                MPEGData[0].box = leftPicture;
                MPEGData[0].rbox = rightPicture;
                leftPicture.Image = MPEGData[0].LeftImageBitmap;
                MemoryStream ms = new MemoryStream();
                image.Save(ms, ImageFormat.Bmp);
                int bytes = (int) ms.Length;
                SetSizeToolStrip(bytes);
                ms.Close();
            }
            catch (Exception ex) {
                MessageBox.Show(@"Error: Could not read file from disk. Original error: " + ex.Message);
            }

            MPEGData[0].SplitBytesIntoColorSpaces();
            MPEGData[0].DrawYcbcrOnRightBitmap(1);
        }