diff --git a/src/ImageProcessor.Playground/Program.cs b/src/ImageProcessor.Playground/Program.cs
index 8fc789a8a..603aee091 100644
--- a/src/ImageProcessor.Playground/Program.cs
+++ b/src/ImageProcessor.Playground/Program.cs
@@ -94,7 +94,7 @@ namespace ImageProcessor.PlayGround
//.EntropyCrop()
//.Filter(MatrixFilters.Invert)
//.Contrast(50)
- .Filter(MatrixFilters.Comic)
+ //.Filter(MatrixFilters.Comic)
//.Flip()
//.Filter(MatrixFilters.HiSatch)
//.Pixelate(8)
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index d47dd3b5d..8b855632f 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -182,6 +182,7 @@
+
@@ -192,9 +193,6 @@
-
- Code
-
diff --git a/src/ImageProcessor/Imaging/Colors/Color32.cs b/src/ImageProcessor/Imaging/Colors/Color32.cs
index 06d336932..8e919eefb 100644
--- a/src/ImageProcessor/Imaging/Colors/Color32.cs
+++ b/src/ImageProcessor/Imaging/Colors/Color32.cs
@@ -76,6 +76,9 @@ namespace ImageProcessor.Imaging.Colors
this.R = red;
this.G = green;
this.B = blue;
+
+ // Stolen from Color.
+ this.Argb = (int)(((uint)((((red << 0x10) | (green << 8)) | blue) | (alpha << 0x18))) & 0xffffffffL);
}
///
diff --git a/src/ImageProcessor/Imaging/Formats/PngFormat.cs b/src/ImageProcessor/Imaging/Formats/PngFormat.cs
index 88a187d7e..998e46b99 100644
--- a/src/ImageProcessor/Imaging/Formats/PngFormat.cs
+++ b/src/ImageProcessor/Imaging/Formats/PngFormat.cs
@@ -14,7 +14,6 @@ namespace ImageProcessor.Imaging.Formats
using System.Drawing.Imaging;
using System.IO;
- using ImageProcessor.Imaging.Quantizers;
using ImageProcessor.Imaging.Quantizers.WuQuantizer;
///
@@ -80,7 +79,7 @@ namespace ImageProcessor.Imaging.Formats
{
if (this.IsIndexed)
{
- image = new OctreeQuantizer(255, 8).Quantize(image);
+ image = new WuQuantizer().Quantize(image);
}
return base.Save(stream, image);
@@ -99,28 +98,7 @@ namespace ImageProcessor.Imaging.Formats
{
if (this.IsIndexed)
{
- // The Wu Quantizer expects a 32bbp image.
- //if (Image.GetPixelFormatSize(image.PixelFormat) != 32)
- //{
- Bitmap clone = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb);
- clone.SetResolution(image.HorizontalResolution, image.VerticalResolution);
-
- using (Graphics graphics = Graphics.FromImage(clone))
- {
- graphics.Clear(Color.Transparent);
- graphics.DrawImage(image, new Rectangle(0, 0, clone.Width, clone.Height));
- }
-
- image.Dispose();
-
- image = new WuQuantizer().QuantizeImage(clone);
-
- // image = new OctreeQuantizer(255, 8).Quantize(image);
- //}
- //else
- //{
- // image = new WuQuantizer().QuantizeImage((Bitmap)image);
- //}
+ image = new WuQuantizer().Quantize(image);
}
return base.Save(path, image);
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ColorMoment.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ColorMoment.cs
index 542aabbd4..6d6aa05b8 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ColorMoment.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ColorMoment.cs
@@ -11,6 +11,8 @@
namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
+ using ImageProcessor.Imaging.Colors;
+
///
/// The cumulative color moment for holding pixel information.
/// Adapted from
@@ -119,12 +121,12 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The pixel to add.
///
- public void Add(Pixel pixel)
+ public void Add(Color32 pixel)
{
- byte alpha = pixel.Alpha;
- byte red = pixel.Red;
- byte green = pixel.Green;
- byte blue = pixel.Blue;
+ byte alpha = pixel.A;
+ byte red = pixel.R;
+ byte green = pixel.G;
+ byte blue = pixel.B;
this.Alpha += alpha;
this.Red += red;
this.Green += green;
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
index 1bdcc4749..19fee034c 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
@@ -18,6 +18,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
using System.Runtime.InteropServices;
using ImageProcessor.Common.Exceptions;
+ using ImageProcessor.Imaging.Colors;
///
/// The image buffer for storing and manipulating pixel information.
@@ -47,13 +48,13 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// Thrown if the given image is not a 32 bit per pixel image.
///
- public IEnumerable PixelLines
+ public IEnumerable PixelLines
{
get
{
int width = this.Image.Width;
int height = this.Image.Height;
- Pixel[] pixels = new Pixel[width];
+ Color32[] pixels = new Color32[width];
using (FastBitmap bitmap = new FastBitmap(this.Image))
{
@@ -62,7 +63,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
for (int x = 0; x < width; x++)
{
Color color = bitmap.GetPixel(x, y);
- pixels[x] = new Pixel(color.A, color.R, color.G, color.B);
+ pixels[x] = new Color32(color.A, color.R, color.G, color.B);
}
yield return pixels;
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteColorHistory.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteColorHistory.cs
index 3f0cafb65..ee155b7de 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteColorHistory.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteColorHistory.cs
@@ -13,6 +13,8 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
using System.Drawing;
+ using ImageProcessor.Imaging.Colors;
+
///
/// The palette color history containing the sum of all pixel data.
/// Adapted from
@@ -61,12 +63,12 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The pixel to add.
///
- public void AddPixel(Pixel pixel)
+ public void AddPixel(Color32 pixel)
{
- this.Alpha += pixel.Alpha;
- this.Red += pixel.Red;
- this.Green += pixel.Green;
- this.Blue += pixel.Blue;
+ this.Alpha += pixel.A;
+ this.Red += pixel.R;
+ this.Green += pixel.G;
+ this.Blue += pixel.B;
this.Sum++;
}
}
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
index d69cfb240..f00438bf1 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
@@ -15,6 +15,8 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
using System.Collections.Generic;
using System.Linq;
+ using ImageProcessor.Imaging.Colors;
+
///
/// Stores the indexed color palette of an image for fast access.
/// Adapted from
@@ -37,14 +39,14 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The palette.
///
- public PaletteLookup(Pixel[] palette)
+ public PaletteLookup(Color32[] palette)
{
this.Palette = new LookupNode[palette.Length];
for (int paletteIndex = 0; paletteIndex < palette.Length; paletteIndex++)
{
this.Palette[paletteIndex] = new LookupNode
{
- Pixel = palette[paletteIndex],
+ Color32 = palette[paletteIndex],
PaletteIndex = (byte)paletteIndex
};
}
@@ -66,7 +68,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The representing the index.
///
- public byte GetPaletteIndex(Pixel pixel)
+ public byte GetPaletteIndex(Color32 pixel)
{
int pixelKey = pixel.Argb & this.paletteMask;
LookupNode[] bucket;
@@ -84,18 +86,18 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
byte bestMatch = 0;
foreach (LookupNode lookup in bucket)
{
- Pixel lookupPixel = lookup.Pixel;
+ Color32 lookupPixel = lookup.Color32;
- int deltaAlpha = pixel.Alpha - lookupPixel.Alpha;
+ int deltaAlpha = pixel.A - lookupPixel.A;
int distance = deltaAlpha * deltaAlpha;
- int deltaRed = pixel.Red - lookupPixel.Red;
+ int deltaRed = pixel.R - lookupPixel.R;
distance += deltaRed * deltaRed;
- int deltaGreen = pixel.Green - lookupPixel.Green;
+ int deltaGreen = pixel.G - lookupPixel.G;
distance += deltaGreen * deltaGreen;
- int deltaBlue = pixel.Blue - lookupPixel.Blue;
+ int deltaBlue = pixel.B - lookupPixel.B;
distance += deltaBlue * deltaBlue;
if (distance >= bestDistance)
@@ -159,21 +161,21 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The representing the component value of the mask.
///
- private static int GetMask(Pixel[] palette)
+ private static int GetMask(Color32[] palette)
{
- IEnumerable alphas = palette.Select(p => p.Alpha).ToArray();
+ IEnumerable alphas = palette.Select(p => p.A).ToArray();
byte maxAlpha = alphas.Max();
int uniqueAlphas = alphas.Distinct().Count();
- IEnumerable reds = palette.Select(p => p.Red).ToArray();
+ IEnumerable reds = palette.Select(p => p.R).ToArray();
byte maxRed = reds.Max();
int uniqueReds = reds.Distinct().Count();
- IEnumerable greens = palette.Select(p => p.Green).ToArray();
+ IEnumerable greens = palette.Select(p => p.G).ToArray();
byte maxGreen = greens.Max();
int uniqueGreens = greens.Distinct().Count();
- IEnumerable blues = palette.Select(p => p.Green).ToArray();
+ IEnumerable blues = palette.Select(p => p.B).ToArray();
byte maxBlue = blues.Max();
int uniqueBlues = blues.Distinct().Count();
@@ -186,7 +188,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
byte greenMask = ComputeBitMask(maxGreen, Convert.ToInt32(Math.Round(uniqueGreens / totalUniques * availableBits)));
byte blueMask = ComputeBitMask(maxBlue, Convert.ToInt32(Math.Round(uniqueBlues / totalUniques * availableBits)));
- Pixel maskedPixel = new Pixel(alphaMask, redMask, greenMask, blueMask);
+ Color32 maskedPixel = new Color32(alphaMask, redMask, greenMask, blueMask);
return maskedPixel.Argb;
}
@@ -221,13 +223,13 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The palette.
///
- private void BuildLookup(Pixel[] palette)
+ private void BuildLookup(Color32[] palette)
{
int mask = GetMask(palette);
Dictionary> tempLookup = new Dictionary>();
foreach (LookupNode lookup in this.Palette)
{
- int pixelKey = lookup.Pixel.Argb & mask;
+ int pixelKey = lookup.Color32.Argb & mask;
List bucket;
if (!tempLookup.TryGetValue(pixelKey, out bucket))
@@ -261,7 +263,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The pixel.
///
- public Pixel Pixel;
+ public Color32 Color32;
}
}
}
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/Pixel.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/Pixel.cs
deleted file mode 100644
index be63cda10..000000000
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/Pixel.cs
+++ /dev/null
@@ -1,104 +0,0 @@
-// --------------------------------------------------------------------------------------------------------------------
-//
-// Copyright (c) James South.
-// Licensed under the Apache License, Version 2.0.
-//
-// --------------------------------------------------------------------------------------------------------------------
-
-
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
-{
- ///
- /// The pixel.
- ///
- [StructLayout(LayoutKind.Explicit)]
- public struct Pixel
- {
- ///
- /// Initializes a new instance of the struct.
- ///
- ///
- /// The alpha.
- ///
- ///
- /// The red.
- ///
- ///
- /// The green.
- ///
- ///
- /// The blue.
- ///
- public Pixel(byte alpha, byte red, byte green, byte blue)
- : this()
- {
- Alpha = alpha;
- Red = red;
- Green = green;
- Blue = blue;
-
- Debug.Assert(Argb == (alpha << 24 | red << 16 | green << 8 | blue));
- }
-
- ///
- /// Initializes a new instance of the struct.
- ///
- ///
- /// The argb.
- ///
- public Pixel(int argb)
- : this()
- {
- Argb = argb;
- Debug.Assert(Alpha == ((uint)argb >> 24));
- Debug.Assert(Red == ((uint)(argb >> 16) & 255));
- Debug.Assert(Green == ((uint)(argb >> 8) & 255));
- Debug.Assert(Blue == ((uint)argb & 255));
- }
-
- ///
- /// The alpha.
- ///
- [FieldOffset(3)]
- public byte Alpha;
-
- ///
- /// The red.
- ///
- [FieldOffset(2)]
- public byte Red;
-
- ///
- /// The green.
- ///
- [FieldOffset(1)]
- public byte Green;
-
- ///
- /// The blue.
- ///
- [FieldOffset(0)]
- public byte Blue;
-
- ///
- /// The argb.
- ///
- [FieldOffset(0)]
- public int Argb;
-
- ///
- /// The to string.
- ///
- ///
- /// The .
- ///
- public override string ToString()
- {
- return string.Format("Alpha:{0} Red:{1} Green:{2} Blue:{3}", Alpha, Red, Green, Blue);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs
index dd4936d7e..40f82caee 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizer.cs
@@ -16,6 +16,8 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
using System.Drawing;
using System.Drawing.Imaging;
+ using ImageProcessor.Imaging.Colors;
+
///
/// Encapsulates methods to calculate the color palette of an image using
/// a Wu color quantizer .
@@ -33,7 +35,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
/// The maximum number of colors apply to the image.
///
///
- /// The array of containing indexed versions of the images colors.
+ /// The array of containing indexed versions of the images colors.
///
///
/// All colors with an alpha value less than this will be considered fully transparent.
@@ -41,7 +43,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The quantized .
///
- internal override Bitmap GetQuantizedImage(ImageBuffer imageBuffer, int colorCount, Pixel[] lookups, int alphaThreshold)
+ internal override Bitmap GetQuantizedImage(ImageBuffer imageBuffer, int colorCount, Color32[] lookups, int alphaThreshold)
{
Bitmap result = new Bitmap(imageBuffer.Image.Width, imageBuffer.Image.Height, PixelFormat.Format8bppIndexed);
result.SetResolution(imageBuffer.Image.HorizontalResolution, imageBuffer.Image.VerticalResolution);
@@ -82,7 +84,7 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
/// The for storing and manipulating pixel information.
///
///
- /// The array of containing indexed versions of the images colors.
+ /// The array of containing indexed versions of the images colors.
///
///
/// The alpha threshold.
@@ -93,21 +95,21 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
///
/// The enumerable list of representing each pixel.
///
- private static IEnumerable IndexedPixels(ImageBuffer image, Pixel[] lookups, int alphaThreshold, PaletteColorHistory[] paletteHistogram)
+ private static IEnumerable IndexedPixels(ImageBuffer image, Color32[] lookups, int alphaThreshold, PaletteColorHistory[] paletteHistogram)
{
byte[] lineIndexes = new byte[image.Image.Width];
PaletteLookup lookup = new PaletteLookup(lookups);
// Determine the correct fallback color.
byte fallback = lookups.Length < AlphaMax ? AlphaMin : AlphaMax;
- foreach (Pixel[] pixelLine in image.PixelLines)
+ foreach (Color32[] pixelLine in image.PixelLines)
{
int length = pixelLine.Length;
for (int i = 0; i < length; i++)
{
- Pixel pixel = pixelLine[i];
+ Color32 pixel = pixelLine[i];
byte bestMatch = fallback;
- if (pixel.Alpha > alphaThreshold)
+ if (pixel.A > alphaThreshold)
{
bestMatch = lookup.GetPaletteIndex(pixel);
paletteHistogram[bestMatch].AddPixel(pixel);
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizerBase.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizerBase.cs
index 8e801bc9c..ee212abcc 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizerBase.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/WuQuantizerBase.cs
@@ -1,4 +1,16 @@
-namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// Encapsulates methods to calculate the color palette of an image using
+// a Wu color quantizer .
+// Adapted from
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
using System;
using System.Diagnostics.CodeAnalysis;
@@ -7,6 +19,7 @@
using System.Linq;
using ImageProcessor.Common.Exceptions;
+ using ImageProcessor.Imaging.Colors;
///
/// Encapsulates methods to calculate the color palette of an image using
@@ -148,7 +161,7 @@
BuildHistogram(histogram, buffer, alphaThreshold, alphaFader);
CalculateMoments(histogram.Moments);
Box[] cubes = SplitData(ref maxColors, histogram.Moments);
- Pixel[] lookups = BuildLookups(cubes, histogram.Moments);
+ Color32[] lookups = BuildLookups(cubes, histogram.Moments);
return this.GetQuantizedImage(buffer, maxColors, lookups, alphaThreshold);
}
catch (Exception ex)
@@ -167,7 +180,7 @@
/// The maximum number of colors apply to the image.
///
///
- /// The array of containing indexed versions of the images colors.
+ /// The array of containing indexed versions of the images colors.
///
///
/// All colors with an alpha value less than this will be considered fully transparent.
@@ -175,7 +188,7 @@
///
/// The quantized .
///
- internal abstract Bitmap GetQuantizedImage(ImageBuffer imageBuffer, int colorCount, Pixel[] lookups, int alphaThreshold);
+ internal abstract Bitmap GetQuantizedImage(ImageBuffer imageBuffer, int colorCount, Color32[] lookups, int alphaThreshold);
///
/// Builds a histogram from the current image.
@@ -197,22 +210,22 @@
{
ColorMoment[, , ,] moments = histogram.Moments;
- foreach (Pixel[] pixelLine in imageBuffer.PixelLines)
+ foreach (Color32[] pixelLine in imageBuffer.PixelLines)
{
- foreach (Pixel pixel in pixelLine)
+ foreach (Color32 pixel in pixelLine)
{
- byte pixelAlpha = pixel.Alpha;
+ byte pixelAlpha = pixel.A;
if (pixelAlpha > alphaThreshold)
{
if (pixelAlpha < 255)
{
- int alpha = pixel.Alpha + (pixel.Alpha % alphaFader);
+ int alpha = pixel.A + (pixel.A % alphaFader);
pixelAlpha = (byte)(alpha > 255 ? 255 : alpha);
}
- byte pixelRed = pixel.Red;
- byte pixelGreen = pixel.Green;
- byte pixelBlue = pixel.Blue;
+ byte pixelRed = pixel.R;
+ byte pixelGreen = pixel.G;
+ byte pixelBlue = pixel.B;
pixelAlpha = (byte)((pixelAlpha >> 3) + 1);
pixelRed = (byte)((pixelRed >> 3) + 1);
@@ -224,7 +237,7 @@
}
// Set a default pixel for images with less than 256 colors.
- moments[0, 0, 0, 0].Add(new Pixel(0, 0, 0, 0));
+ moments[0, 0, 0, 0].Add(new Color32(0, 0, 0, 0));
}
///
@@ -689,12 +702,12 @@
/// The three dimensional array of .
///
///
- /// The array of .
+ /// The array of .
///
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1001:CommasMustBeSpacedCorrectly", Justification = "Reviewed. Suppression is OK here.")]
- private static Pixel[] BuildLookups(Box[] cubes, ColorMoment[, , ,] moments)
+ private static Color32[] BuildLookups(Box[] cubes, ColorMoment[, , ,] moments)
{
- Pixel[] lookups = new Pixel[cubes.Length];
+ Color32[] lookups = new Color32[cubes.Length];
for (int cubeIndex = 0; cubeIndex < cubes.Length; cubeIndex++)
{
@@ -705,12 +718,12 @@
continue;
}
- Pixel lookup = new Pixel
+ Color32 lookup = new Color32
{
- Alpha = (byte)(volume.Alpha / volume.Weight),
- Red = (byte)(volume.Red / volume.Weight),
- Green = (byte)(volume.Green / volume.Weight),
- Blue = (byte)(volume.Blue / volume.Weight)
+ A = (byte)(volume.Alpha / volume.Weight),
+ R = (byte)(volume.Red / volume.Weight),
+ G = (byte)(volume.Green / volume.Weight),
+ B = (byte)(volume.Blue / volume.Weight)
};
lookups[cubeIndex] = lookup;