//подсчет величины корреляции
        public static double[] GetAlpha(Bitmap rankBlock, Bitmap domainBlock, double[] meanRankBlock, double[] meanDomainBlock)
        {
            BufferedBitmap bbRankBlock   = new BufferedBitmap(rankBlock);
            BufferedBitmap bbDomainBlock = new BufferedBitmap(domainBlock);

            double[] alpha = new double[Data.ColorFlag];
            double   temp  = 0;

            for (int k = 0; k < Data.ColorFlag; k++)
            {
                alpha[k] = 0;
                for (int i = 0; i < rankBlock.Height; i++)
                {
                    for (int j = 0; j < rankBlock.Width; j++)
                    {
                        temp = (bbDomainBlock.GetColorOfPixel(i, j, k) - meanDomainBlock[k]) *
                               (bbRankBlock.GetColorOfPixel(i, j, k) - meanRankBlock[k]);
                        alpha[k] += temp;
                    }
                }
            }
            bbRankBlock.Unlock();
            bbDomainBlock.Unlock();
            return(alpha);
        }
        //подсчет дисперсии значений пикселов
        public static double[] GetBeta(Bitmap domainBlock, double[] mean)
        {
            BufferedBitmap bbDomainBlock = new BufferedBitmap(domainBlock);

            double[] beta = new double[Data.ColorFlag];

            for (int k = 0; k < Data.ColorFlag; k++)
            {
                beta[k] = 0;
                for (int i = 0; i < domainBlock.Height; i++)
                {
                    for (int j = 0; j < domainBlock.Width; j++)
                    {
                        beta[k] += Math.Pow(bbDomainBlock.GetColorOfPixel(i, j, k) - mean[k], 2);
                    }
                }
            }
            bbDomainBlock.Unlock();
            return(beta);
        }
        //подсчет среднего значения пикселов в блоке
        public static double[] Mean(Bitmap block)
        {
            BufferedBitmap bbBlock = new BufferedBitmap(block);

            double[] mean = new double[Data.ColorFlag];

            for (int k = 0; k < Data.ColorFlag; k++)
            {
                mean[k] = 0;
                for (int i = 0; i < bbBlock.Height; i++)
                {
                    for (int j = 0; j < bbBlock.Width; j++)
                    {
                        mean[k] += bbBlock.GetColorOfPixel(i, j, k);
                    }
                }
                mean[k] = mean[k] / (Data.RankBlockSize * Data.RankBlockSize);
            }
            bbBlock.Unlock();
            return(mean);
        }
        //подсчет значения метрики
        public static double[] GetMetric(Bitmap rankBlock, Bitmap domainBlock, double[] contrast, double[] brightness)
        {
            BufferedBitmap bbRankBlock   = new BufferedBitmap(rankBlock);
            BufferedBitmap bbDomainBlock = new BufferedBitmap(domainBlock);

            double[] metric = new double[Data.ColorFlag];

            for (int k = 0; k < Data.ColorFlag; k++)
            {
                metric[k] = 0;
                for (int i = 0; i < rankBlock.Height; i++)
                {
                    for (int j = 0; j < rankBlock.Width; j++)
                    {
                        metric[k] += Math.Pow(contrast[k] * bbDomainBlock.GetColorOfPixel(i, j, k)
                                              + brightness[k] - bbRankBlock.GetColorOfPixel(i, j, k), 2);
                    }
                }
            }
            bbRankBlock.Unlock();
            bbDomainBlock.Unlock();
            return(metric);
        }
        //декодирование изображения
        public Bitmap[] Decompress(string path, int numberOfIterations, bool imageFlag)
        {
            Stopwatch sw = new Stopwatch();

            sw.Restart();
            int width, height;
            var compressedData = ReadData(path, out width, out height);

            Bitmap[] images = new Bitmap[numberOfIterations];

            if (!imageFlag)
            {
                try
                {
                    OpenFileDialog opf = new OpenFileDialog();
                    if (opf.ShowDialog() == DialogResult.OK)
                    {
                        images[0] = ResizeImage(new Bitmap(opf.FileName), width, height);
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception("Файл не является картинкой");
                }
            }
            else
            {
                images[0] = CreateRandomImage(width, height);
            }

            Bitmap image      = new Bitmap(images[0]);
            Bitmap reduced    = new Bitmap(ResizeImage(image, width / 2, height / 2));
            Bitmap restored   = new Bitmap(image);
            Bitmap temp       = new Bitmap(image);
            var    bbOriginal = new BufferedBitmap(image);
            var    bbReduced  = new BufferedBitmap(reduced);

            for (int nb = 1; nb < numberOfIterations; nb++)
            {
                for (int i = 0; i < compressedData.GetLength(0); i++)
                {
                    for (int x = 0; x < compressedData.GetLength(1); x++)
                    {
                        for (int y = 0; y < compressedData.GetLength(2); y++)
                        {
                            var offsetX       = (int)compressedData[i, x, y, 0];
                            var offsetY       = (int)compressedData[i, x, y, 1];
                            var indexRotation = (int)compressedData[i, x, y, 2];
                            var contrast      = compressedData[i, x, y, 3];
                            var brightness    = compressedData[i, x, y, 4];

                            var domainBlock = SelectBlockFromImage(bbReduced, offsetX, offsetY, Data.RankBlockSize);
                            domainBlock.RotateFlip(rotate[indexRotation]);
                            var bbDomainBlock = new BufferedBitmap(domainBlock);

                            for (int domainX = 0; domainX < Data.RankBlockSize; domainX++)
                            {
                                for (int domainY = 0; domainY < Data.RankBlockSize; domainY++)
                                {
                                    double pixel = bbDomainBlock.GetColorOfPixel(domainX, domainY, i);
                                    pixel = contrast * pixel + brightness;
                                    pixel = Math.Round(pixel);
                                    if (pixel < byte.MinValue)
                                    {
                                        pixel = 0;
                                    }
                                    if (pixel > byte.MaxValue)
                                    {
                                        pixel = 255;
                                    }

                                    if (i == 0)
                                    {
                                        bbOriginal.SetPixel(x * Data.RankBlockSize + domainX, y * Data.RankBlockSize + domainY,
                                                            Color.FromArgb((int)pixel, (int)pixel, (int)pixel));
                                        continue;
                                    }
                                    var color = temp.GetPixel(x * Data.RankBlockSize + domainX, y * Data.RankBlockSize + domainY);
                                    if (i == 1)
                                    {
                                        bbOriginal.SetPixel(x * Data.RankBlockSize + domainX, y * Data.RankBlockSize + domainY,
                                                            Color.FromArgb((int)pixel, (int)pixel, color.B));
                                        continue;
                                    }
                                    if (i == 2)
                                    {
                                        bbOriginal.SetPixel(x * Data.RankBlockSize + domainX, y * Data.RankBlockSize + domainY,
                                                            Color.FromArgb((int)pixel, color.G, color.B));
                                        continue;
                                    }
                                }
                            }
                        }
                    }
                    bbOriginal.Unlock();

                    image      = bbOriginal.Bitmap;
                    temp       = new Bitmap(image);
                    bbOriginal = new BufferedBitmap(image);
                }
                bbOriginal.Unlock();
                bbReduced.Unlock();

                image      = bbOriginal.Bitmap;
                reduced    = new Bitmap(ResizeImage(image, width / 2, height / 2));
                images[nb] = new Bitmap(image);

                var a = new Bitmap(image);
                a.Save(nb + ".jpg");

                bbOriginal = new BufferedBitmap(image);
                bbReduced  = new BufferedBitmap(reduced);
            }
            image.Save(Path.GetDirectoryName(Data.Path) + "//" + Path.GetFileNameWithoutExtension(Data.Path) + "-restored.png");
            sw.Stop();
            MessageBox.Show("Восстановление завершено\r\nВремя: " + (sw.ElapsedMilliseconds / 1000.0).ToString());
            return(images);
        }