Skip to content

Commit

Permalink
Tinkering
Browse files Browse the repository at this point in the history
  • Loading branch information
cyotek committed Feb 11, 2017
1 parent 29f4581 commit 5fb11e7
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 68 deletions.
1 change: 1 addition & 0 deletions src/DitheringTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
<Compile Include="Transforms\SimpleIndexedPalettePixelTransform.cs" />
<Compile Include="Transforms\SimpleIndexedPalettePixelTransform256.cs" />
<Compile Include="Transforms\SimpleIndexedPalettePixelTransform8.cs" />
<Compile Include="WorkerData.cs" />
<EmbeddedResource Include="AboutDialog.resx">
<DependentUpon>AboutDialog.cs</DependentUpon>
</EmbeddedResource>
Expand Down
158 changes: 91 additions & 67 deletions src/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ private void actualSizeToolStripButton_Click(object sender, EventArgs e)

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Tuple<Bitmap, IPixelTransform, IErrorDiffusion> data;
WorkerData data;

data = (Tuple<Bitmap, IPixelTransform, IErrorDiffusion>)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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Transforms/SimpleIndexedPalettePixelTransform16.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
22 changes: 22 additions & 0 deletions src/WorkerData.cs
Original file line number Diff line number Diff line change
@@ -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; }
}
}

0 comments on commit 5fb11e7

Please sign in to comment.