From 5fb11e7fddcec99bf848fe3a21779ebb18d78d69 Mon Sep 17 00:00:00 2001 From: Richard Moss Date: Sat, 11 Feb 2017 10:10:17 +0000 Subject: [PATCH] Tinkering --- src/DitheringTest.csproj | 1 + src/MainForm.cs | 158 ++++++++++-------- .../SimpleIndexedPalettePixelTransform16.cs | 2 +- src/WorkerData.cs | 22 +++ 4 files changed, 115 insertions(+), 68 deletions(-) create mode 100644 src/WorkerData.cs diff --git a/src/DitheringTest.csproj b/src/DitheringTest.csproj index 2a73380..e3b534f 100644 --- a/src/DitheringTest.csproj +++ b/src/DitheringTest.csproj @@ -98,6 +98,7 @@ + AboutDialog.cs diff --git a/src/MainForm.cs b/src/MainForm.cs index 5baf286..badb77f 100644 --- a/src/MainForm.cs +++ b/src/MainForm.cs @@ -105,11 +105,11 @@ private void actualSizeToolStripButton_Click(object sender, EventArgs e) private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { - Tuple data; + WorkerData data; - data = (Tuple)e.Argument; + data = (WorkerData)e.Argument; - e.Result = this.GetTransformedImage(data.Item1, data.Item2, data.Item3); + e.Result = this.GetTransformedImage(data); } private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) @@ -322,6 +322,35 @@ private IErrorDiffusion GetDitheringInstance() return result; } + private int GetMaximumColorCount() + { + int result; + + result = 256; + + if (monochromeRadioButton.Checked) + { + result = 2; + } + else if (colorRadioButton.Checked) + { + switch (paletteSizeComboBox.SelectedIndex) + { + case 0: + result = 8; + break; + case 1: + result = 16; + break; + case 2: + result = 256; + break; + } + } + + return result; + } + private IPixelTransform GetPixelTransform() { IPixelTransform result; @@ -351,80 +380,34 @@ private IPixelTransform GetPixelTransform() return result; } - private Bitmap GetTransformedImage(Bitmap image, IPixelTransform transform, IErrorDiffusion dither) + private Bitmap GetTransformedImage(WorkerData workerData) { + Bitmap image; Bitmap result; ArgbColor[] pixelData; Size size; - bool inline; + IPixelTransform transform; + IErrorDiffusion dither; + transform = workerData.Transform; + dither = workerData.Dither; + image = workerData.Image; size = image.Size; pixelData = image.GetPixelsFrom32BitArgbImage(); - if (dither != null) + if (dither != null && dither.Prescan) { - if (dither.Prescan) - { - inline = false; - - for (int row = 0; row < size.Height; row++) - { - for (int col = 0; col < size.Width; col++) - { - int index; - ArgbColor current; - - index = row * size.Width + col; - - current = pixelData[index]; - - dither.Diffuse(pixelData, current, current, col, row, size.Width, size.Height); - } - } - } - else - { - inline = true; - } - } - else - { - inline = false; + // perform the dithering on the source data before + // it is transformed + this.ProcessPixels(pixelData, size, null, dither); + dither = null; } - for (int row = 0; row < size.Height; row++) - { - for (int col = 0; col < size.Width; col++) - { - int index; - ArgbColor current; - ArgbColor transformed; - - index = row * size.Width + col; - - current = pixelData[index]; - - // transform the pixel - normally this would be some form of color - // reduction. For this sample it's simple threshold based - // monochrome conversion - if (transform != null) - { - transformed = transform.Transform(pixelData, current, col, row, size.Width, size.Height); - pixelData[index] = transformed; - } - else - { - transformed = current; - } - - // apply a dither algorithm to this pixel - if (inline) - { - dither.Diffuse(pixelData, current, transformed, col, row, size.Width, size.Height); - } - } - } + // scan each pixel, apply a transform the pixel + // and then dither it + this.ProcessPixels(pixelData, size, transform, dither); + // create the final bitmap result = pixelData.ToBitmap(size); return result; @@ -569,10 +552,43 @@ private void pasteToolStripMenuItem_Click(object sender, EventArgs e) } } + private void ProcessPixels(ArgbColor[] pixelData, Size size, IPixelTransform pixelTransform, IErrorDiffusion dither) + { + for (int row = 0; row < size.Height; row++) + { + for (int col = 0; col < size.Width; col++) + { + int index; + ArgbColor current; + ArgbColor transformed; + + index = row * size.Width + col; + + current = pixelData[index]; + + // transform the pixel + if (pixelTransform != null) + { + transformed = pixelTransform.Transform(pixelData, current, col, row, size.Width, size.Height); + pixelData[index] = transformed; + } + else + { + transformed = current; + } + + // apply a dither algorithm to this pixel + // assuming it wasn't done before + dither?.Diffuse(pixelData, current, transformed, col, row, size.Width, size.Height); + } + } + } + private void RequestImageTransform() { if (_image != null && !backgroundWorker.IsBusy) { + WorkerData workerData; IPixelTransform transform; IErrorDiffusion ditherer; Bitmap image; @@ -585,10 +601,18 @@ private void RequestImageTransform() ditherer = this.GetDitheringInstance(); image = _image.Copy(); + workerData = new WorkerData + { + Image = image, + Transform = transform, + Dither = ditherer, + ColorCount = this.GetMaximumColorCount() + }; + #if USEWORKER - backgroundWorker.RunWorkerAsync(Tuple.Create(image, transform, ditherer)); + backgroundWorker.RunWorkerAsync(workerData); #else - backgroundWorker_RunWorkerCompleted(backgroundWorker, new RunWorkerCompletedEventArgs(this.GetTransformedImage(image, transform, ditherer), null, false)); + backgroundWorker_RunWorkerCompleted(backgroundWorker, new RunWorkerCompletedEventArgs(this.GetTransformedImage(workerData), null, false)); #endif } } diff --git a/src/Transforms/SimpleIndexedPalettePixelTransform16.cs b/src/Transforms/SimpleIndexedPalettePixelTransform16.cs index 91422bd..5a2f779 100644 --- a/src/Transforms/SimpleIndexedPalettePixelTransform16.cs +++ b/src/Transforms/SimpleIndexedPalettePixelTransform16.cs @@ -22,8 +22,8 @@ public SimpleIndexedPalettePixelTransform16() ArgbColor.FromArgb(0, 0, 128), ArgbColor.FromArgb(128, 0, 128), ArgbColor.FromArgb(0, 128, 128), - ArgbColor.FromArgb(192, 192, 192), ArgbColor.FromArgb(128, 128, 128), + ArgbColor.FromArgb(192, 192, 192), ArgbColor.FromArgb(255, 0, 0), ArgbColor.FromArgb(0, 255, 0), ArgbColor.FromArgb(255, 255, 0), diff --git a/src/WorkerData.cs b/src/WorkerData.cs new file mode 100644 index 0000000..f5a0d63 --- /dev/null +++ b/src/WorkerData.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Cyotek.DitheringTest.Transforms; +using Cyotek.Drawing.Imaging.ColorReduction; + +namespace Cyotek.DitheringTest +{ +internal sealed class WorkerData + { + public Bitmap Image { get; set; } + + public IErrorDiffusion Dither { get; set; } + + public IPixelTransform Transform { get; set; } + + public int ColorCount { get; set; } + } +}