//кодирование изображения public void Compress(Bitmap image, IProgress <int> progress = null, CancellationToken?token = null) { if (progress == null) { progress = new Progress <int>(); } if (token == null) { token = new CancellationToken(); } Stopwatch sw = new Stopwatch(); sw.Start(); Bitmap[,] parts = SplitImage(image, out numberOfParts); Bitmap[,,] domainBlocks; int partOffsetX = image.Width / Data.RankBlockSize / numberOfParts; int partOffsetY = image.Height / Data.RankBlockSize / numberOfParts; var bbOriginal = new BufferedBitmap(image); if (bbOriginal.IsGrey()) { Data.ColorFlag = 1; } else { Data.ColorFlag = 3; } bbOriginal.Unlock(); double[] contrast = new double[Data.ColorFlag]; double[] brightness = new double[Data.ColorFlag]; double[] metric = new double[Data.ColorFlag]; double[] min = new double[Data.ColorFlag]; double[,,,] compressedData = new double[Data.ColorFlag, bbOriginal.Width / Data.RankBlockSize, bbOriginal.Height / Data.RankBlockSize, numberOfParameters]; double controlValue = (bbOriginal.Width / Data.RankBlockSize) * (bbOriginal.Height / Data.RankBlockSize) / 100.0; double count = 0; int value = 1; double mse = 0; for (int partX = 0; partX < numberOfParts; partX++) { for (int partY = 0; partY < numberOfParts; partY++) { domainBlocks = CreateAllDomainBlocks(parts[partX, partY]); bbOriginal = new BufferedBitmap(parts[partX, partY]); for (int i = 0; i *Data.RankBlockSize != bbOriginal.Width; i++) { for (int j = 0; j *Data.RankBlockSize != bbOriginal.Height; j++) { if ((bool)token?.IsCancellationRequested) { progress.Report(0); MessageBox.Show("Операция прервана"); return; } int indexX = i + partX * partOffsetX; int indexY = j + partY * partOffsetY; Bitmap rankBlock = SelectBlockFromImage(bbOriginal, i, j, Data.RankBlockSize); if (min[0] != 0) { for (int k = 0; k < Data.ColorFlag; k++) { mse += min[k]; } } for (int k = 0; k < Data.ColorFlag; k++) { min[k] = double.PositiveInfinity; } var meanRankBlock = Metric.Mean(rankBlock); for (int p = 0; p < parts[partX, partY].Width / Data.DomainBlockSize; p++) { for (int q = 0; q < parts[partX, partY].Height / Data.DomainBlockSize; q++) { var meanDomainBlock = Metric.Mean(domainBlocks[p, q, 0]); for (int rotation = 0; rotation < numberOfRotations; rotation++) { contrast = Metric.GetContrast(rankBlock, domainBlocks[p, q, rotation], meanRankBlock, meanDomainBlock); brightness = Metric.GetBrightness(contrast, meanRankBlock, meanDomainBlock); metric = Metric.GetMetric(rankBlock, domainBlocks[p, q, rotation], contrast, brightness); for (int m = 0; m < Data.ColorFlag; m++) { if (metric[m] < min[m]) { min[m] = metric[m]; double[] mas = new double[] { p + partX * partOffsetX / Data.Factor, q + partY * partOffsetY / Data.Factor, rotation, contrast[m], brightness[m] }; for (int k = 0; k < mas.Length; k++) { compressedData[m, indexX, indexY, k] = mas[k]; } } } //if (Data.FastCompression && min[0] <= 100) //break; } //if (Data.FastCompression && min[0] <= 100) //break; } count += 1.0 / domainBlocks.GetLength(1); if (count >= controlValue) { if (value > 100) { value = 100; } progress.Report(value); value++; count -= controlValue; count = Math.Round(count, 2); } //if (Data.FastCompression && min[0] <= 100) //break; } } } } } mse = mse / ((image.Width / Data.RankBlockSize) * (image.Height / Data.RankBlockSize)); bbOriginal.Unlock(); double psnr = 10 * Math.Log10(image.Width * image.Height * Math.Pow(byte.MaxValue, 2) * Data.ColorFlag / mse); WriteData(compressedData, image.Width, image.Height); sw.Stop(); MessageBox.Show("Сжатие завершено\r\nВремя: " + (sw.ElapsedMilliseconds / 1000.0).ToString()); progress.Report(0); }