diff --git a/src/ImageProcessor/Common/Exceptions/QuantizationException.cs b/src/ImageProcessor/Common/Exceptions/QuantizationException.cs
new file mode 100644
index 000000000..7c2e17946
--- /dev/null
+++ b/src/ImageProcessor/Common/Exceptions/QuantizationException.cs
@@ -0,0 +1,42 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// The exception that is thrown when quantizing an image has failed.
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Common.Exceptions
+{
+ using System;
+
+ ///
+ /// The exception that is thrown when quantizing an image has failed.
+ ///
+ [Serializable]
+ public class QuantizationException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The message.
+ ///
+ public QuantizationException(string message)
+ : base(message)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The error message that explains the reason for the exception.
+ /// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.
+ public QuantizationException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index fb8773734..d47dd3b5d 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -195,7 +195,7 @@
Code
-
+
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
index 14dbbdf31..91e5c975b 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/ImageBuffer.cs
@@ -18,6 +18,8 @@ namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
+ using ImageProcessor.Common.Exceptions;
+
///
/// The image buffer for storing pixel information.
/// Adapted from
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
index 43ba5d04b..d22486a6d 100644
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
+++ b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/PaletteLookup.cs
@@ -1,32 +1,78 @@
-namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) James South.
+// Licensed under the Apache License, Version 2.0.
+//
+//
+// Stores the indexed color palette of an image for fast access.
+// Adapted from
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
{
using System;
using System.Collections.Generic;
using System.Linq;
- class PaletteLookup
+ ///
+ /// Stores the indexed color palette of an image for fast access.
+ /// Adapted from
+ ///
+ internal class PaletteLookup
{
- private int mMask;
- private Dictionary mLookup;
- private LookupNode[] Palette { get; set; }
+ ///
+ /// The dictionary for caching lookup nodes.
+ ///
+ private Dictionary lookupNodes;
+
+ ///
+ /// The palette mask.
+ ///
+ private int paletteMask;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The palette.
+ ///
public PaletteLookup(Pixel[] palette)
{
- Palette = new LookupNode[palette.Length];
+ this.Palette = new LookupNode[palette.Length];
for (int paletteIndex = 0; paletteIndex < palette.Length; paletteIndex++)
{
- Palette[paletteIndex] = new LookupNode { Pixel = palette[paletteIndex], PaletteIndex = (byte)paletteIndex };
+ this.Palette[paletteIndex] = new LookupNode
+ {
+ Pixel = palette[paletteIndex],
+ PaletteIndex = (byte)paletteIndex
+ };
}
- BuildLookup(palette);
+
+ this.BuildLookup(palette);
}
+ ///
+ /// Gets or sets the palette.
+ ///
+ private LookupNode[] Palette { get; set; }
+
+ ///
+ /// Gets palette index for the given pixel.
+ ///
+ ///
+ /// The pixel to return the index for.
+ ///
+ ///
+ /// The representing the index.
+ ///
public byte GetPaletteIndex(Pixel pixel)
{
- int pixelKey = pixel.Argb & mMask;
+ int pixelKey = pixel.Argb & this.paletteMask;
LookupNode[] bucket;
- if (!mLookup.TryGetValue(pixelKey, out bucket))
+ if (!this.lookupNodes.TryGetValue(pixelKey, out bucket))
{
- bucket = Palette;
+ bucket = this.Palette;
}
if (bucket.Length == 1)
@@ -53,121 +99,169 @@
distance += deltaBlue * deltaBlue;
if (distance >= bestDistance)
+ {
continue;
+ }
bestDistance = distance;
bestMatch = lookup.PaletteIndex;
}
- if ((bucket == Palette) && (pixelKey != 0))
+ if ((bucket == this.Palette) && (pixelKey != 0))
{
- mLookup[pixelKey] = new LookupNode[] { bucket[bestMatch] };
+ this.lookupNodes[pixelKey] = new[] { bucket[bestMatch] };
}
return bestMatch;
}
- private void BuildLookup(Pixel[] palette)
+ ///
+ /// Computes the bit mask.
+ ///
+ ///
+ /// The maximum byte value.
+ ///
+ ///
+ /// The number of bits.
+ ///
+ ///
+ /// The .
+ ///
+ private static byte ComputeBitMask(byte max, int bits)
{
- int mask = GetMask(palette);
- Dictionary> tempLookup = new Dictionary>();
- foreach (LookupNode lookup in Palette)
+ byte mask = 0;
+
+ if (bits != 0)
{
- int pixelKey = lookup.Pixel.Argb & mask;
+ byte highestSetBitIndex = HighestSetBitIndex(max);
- List bucket;
- if (!tempLookup.TryGetValue(pixelKey, out bucket))
+ for (int i = 0; i < bits; i++)
{
- bucket = new List();
- tempLookup[pixelKey] = bucket;
+ mask <<= 1;
+ mask++;
}
- bucket.Add(lookup);
- }
- mLookup = new Dictionary(tempLookup.Count);
- foreach (var key in tempLookup.Keys)
- {
- mLookup[key] = tempLookup[key].ToArray();
+ for (int i = 0; i <= highestSetBitIndex - bits; i++)
+ {
+ mask <<= 1;
+ }
}
- mMask = mask;
+
+ return mask;
}
+ ///
+ /// Gets the mask value from the palette.
+ ///
+ ///
+ /// The palette.
+ ///
+ ///
+ /// The representing the component value of the mask.
+ ///
private static int GetMask(Pixel[] palette)
{
- IEnumerable alphas = from pixel in palette
- select pixel.Alpha;
+ IEnumerable alphas = palette.Select(p => p.Alpha).ToArray();
byte maxAlpha = alphas.Max();
int uniqueAlphas = alphas.Distinct().Count();
- IEnumerable reds = from pixel in palette
- select pixel.Red;
+ IEnumerable reds = palette.Select(p => p.Red).ToArray();
byte maxRed = reds.Max();
int uniqueReds = reds.Distinct().Count();
- IEnumerable greens = from pixel in palette
- select pixel.Green;
+ IEnumerable greens = palette.Select(p => p.Green).ToArray();
byte maxGreen = greens.Max();
int uniqueGreens = greens.Distinct().Count();
- IEnumerable blues = from pixel in palette
- select pixel.Blue;
+ IEnumerable blues = palette.Select(p => p.Green).ToArray();
byte maxBlue = blues.Max();
int uniqueBlues = blues.Distinct().Count();
double totalUniques = uniqueAlphas + uniqueReds + uniqueGreens + uniqueBlues;
- double AvailableBits = 1.0 + Math.Log(uniqueAlphas * uniqueReds * uniqueGreens * uniqueBlues);
+ double availableBits = 1.0 + Math.Log(uniqueAlphas * uniqueReds * uniqueGreens * uniqueBlues);
- byte alphaMask = ComputeBitMask(maxAlpha, Convert.ToInt32(Math.Round(uniqueAlphas / totalUniques * AvailableBits)));
- byte redMask = ComputeBitMask(maxRed, Convert.ToInt32(Math.Round(uniqueReds / totalUniques * AvailableBits)));
- byte greenMask = ComputeBitMask(maxGreen, Convert.ToInt32(Math.Round(uniqueGreens / totalUniques * AvailableBits)));
- byte blueMask = ComputeBitMask(maxBlue, Convert.ToInt32(Math.Round(uniqueBlues / totalUniques * AvailableBits)));
+ byte alphaMask = ComputeBitMask(maxAlpha, Convert.ToInt32(Math.Round(uniqueAlphas / totalUniques * availableBits)));
+ byte redMask = ComputeBitMask(maxRed, Convert.ToInt32(Math.Round(uniqueReds / totalUniques * availableBits)));
+ 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);
return maskedPixel.Argb;
}
- private static byte ComputeBitMask(byte max, int bits)
+ ///
+ /// Gets the highest set bit index.
+ ///
+ ///
+ /// The value.
+ ///
+ ///
+ /// The .
+ ///
+ private static byte HighestSetBitIndex(byte value)
{
- byte mask = 0;
-
- if (bits != 0)
+ byte index = 0;
+ for (int i = 0; i < 8; i++)
{
- byte highestSetBitIndex = HighestSetBitIndex(max);
-
-
- for (int i = 0; i < bits; i++)
+ if (0 != (value & 1))
{
- mask <<= 1;
- mask++;
+ index = (byte)i;
}
- for (int i = 0; i <= highestSetBitIndex - bits; i++)
- {
- mask <<= 1;
- }
+ value >>= 1;
}
- return mask;
+
+ return index;
}
- private static byte HighestSetBitIndex(byte value)
+ ///
+ /// The build lookup.
+ ///
+ ///
+ /// The palette.
+ ///
+ private void BuildLookup(Pixel[] palette)
{
- byte index = 0;
- for (int i = 0; i < 8; i++)
+ int mask = GetMask(palette);
+ Dictionary> tempLookup = new Dictionary>();
+ foreach (LookupNode lookup in this.Palette)
{
- if (0 != (value & 1))
+ int pixelKey = lookup.Pixel.Argb & mask;
+
+ List bucket;
+ if (!tempLookup.TryGetValue(pixelKey, out bucket))
{
- index = (byte)i;
+ bucket = new List();
+ tempLookup[pixelKey] = bucket;
}
- value >>= 1;
+
+ bucket.Add(lookup);
}
- return index;
+
+ this.lookupNodes = new Dictionary(tempLookup.Count);
+ foreach (var key in tempLookup.Keys)
+ {
+ this.lookupNodes[key] = tempLookup[key].ToArray();
+ }
+
+ this.paletteMask = mask;
}
+ ///
+ /// Represents a single node containing the index and pixel.
+ ///
private struct LookupNode
{
- public Pixel Pixel;
+ ///
+ /// The palette index.
+ ///
public byte PaletteIndex;
+
+ ///
+ /// The pixel.
+ ///
+ public Pixel Pixel;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/QuantizationException.cs b/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/QuantizationException.cs
deleted file mode 100644
index e723f7dc1..000000000
--- a/src/ImageProcessor/Imaging/Quantizers/WuQuantizer/QuantizationException.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace ImageProcessor.Imaging.Quantizers.WuQuantizer
-{
- [Serializable]
- public class QuantizationException : ApplicationException
- {
- public QuantizationException(string message) : base(message)
- {
-
- }
- }
-}