private Task <StandardRgbBitmap> CreateSampledBitmap(StandardRgbBitmap source, float volumeAspectRatio, int totalVolumeCount) { return(Task.Run(() => { // Determine the ideal width and height of each volume // x * y = totalvolumeCount // x * volumeAspectRatio / y = source.w / source.h // => y = totalVolumeCount / x // => x * x * volumeAspectRatio / totalVolumeCount = source.w / source.h // => x ^ 2 = source.w / source.h * totalVolumeCount / volumeAspectRatio // => y = sqrt(source.w / source.h * totalVolumeCount / volumeAspectRatio) double targetWidth = Math.Sqrt((double)source.Width / source.Height * totalVolumeCount / volumeAspectRatio); double targetHeight = totalVolumeCount / targetWidth; int width = (int)targetWidth; int height = (int)targetHeight; int areaWidth = source.Width / width; int areaHeight = source.Height / height; int startX = (source.Width - width * areaWidth) / 2; int startY = (source.Height - height * areaHeight) / 2; StandardRgbColor[] pixels = new StandardRgbColor[width * height]; Parallel.For(0, width, targetX => { for (int targetY = 0; targetY < height; targetY++) { ColorAverageAccumulator accumulator = new ColorAverageAccumulator(); for (int sourceX = startX + targetX * areaWidth; sourceX < startX + (targetX + 1) * areaWidth; sourceX++) { for (int sourceY = startY + targetY * areaHeight; sourceY < startY + (targetY + 1) * areaHeight; sourceY++) { accumulator.AddSample((Vector3)source.Pixels[sourceY * source.Width + sourceX].ToCieLab()); } } pixels[targetY * width + targetX] = ((CieLabColor)accumulator.GetAverage()).ToStandardRgb(); } }); return new StandardRgbBitmap(pixels, width, height, source.DpiX, source.DpiY); })); }
private async void OpenMosaicImage(object sender, RoutedEventArgs e) { OpenFileDialog mosaicOpenFileDialog = new OpenFileDialog { Title = "Mosaic Image", Filter = "Images|*.jpg;*.png", InitialDirectory = Settings.Default.MosaicImagePath }; if (mosaicOpenFileDialog.ShowDialog() == true) { Settings.Default.MosaicImagePath = Path.GetDirectoryName(mosaicOpenFileDialog.FileName); Settings.Default.Save(); var originalImage = BitmapFrame.Create(new Uri(mosaicOpenFileDialog.FileName), BitmapCreateOptions.None, BitmapCacheOption.Default); sampledBitmap = await CreateSampledBitmap(originalImage.ToStandardRgbBitmap(), averageAspectRatio, sources.Count); var targetImage = sampledBitmap.ToBitmapSource(); SimplifiedBitmap.Source = targetImage; SimplifiedBitmap.Width = targetImage.PixelWidth * 1.5; SimplifiedBitmap.Height = targetImage.PixelHeight; } }