// -----------------------------------------------------------------------
//
// TODO: Update copyright text.
//
// -----------------------------------------------------------------------
namespace ImageProcessor.Imaging
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
///
/// Encapsulates methods to calculate the colour palette if an image.
/// http://codebetter.com/brendantompkins/2007/06/14/gif-image-color-quantizer-now-with-safe-goodness/
///
internal class PaletteQuantizer : Quantizer
{
///
/// Initializes a new instance of the class.
///
///
/// The color palette to quantize to
///
///
/// Palette quantization only requires a single quantization step
///
public PaletteQuantizer(ArrayList palette)
: base(true)
{
_colorMap = new Hashtable();
_colors = new Color[palette.Count];
palette.CopyTo(_colors);
}
///
/// Override this to process the pixel in the second pass of the algorithm
///
/// The pixel to quantize
/// The quantized value
protected override byte QuantizePixel(Color32 pixel)
{
byte colorIndex = 0;
int colorHash = pixel.ARGB;
// Check if the color is in the lookup table
if (_colorMap.ContainsKey(colorHash))
{
colorIndex = (byte)_colorMap[colorHash];
}
else
{
// Not found - loop through the palette and find the nearest match.
// Firstly check the alpha value - if 0, lookup the transparent color
if (0 == pixel.Alpha)
{
// Transparent. Lookup the first color with an alpha value of 0
for (int index = 0; index < _colors.Length; index++)
{
if (0 == _colors[index].A)
{
colorIndex = (byte)index;
break;
}
}
}
else
{
// Not transparent...
int leastDistance = int.MaxValue;
int red = pixel.Red;
int green = pixel.Green;
int blue = pixel.Blue;
// Loop through the entire palette, looking for the closest color match
for (int index = 0; index < _colors.Length; index++)
{
Color paletteColor = _colors[index];
int redDistance = paletteColor.R - red;
int greenDistance = paletteColor.G - green;
int blueDistance = paletteColor.B - blue;
int distance = (redDistance * redDistance) +
(greenDistance * greenDistance) +
(blueDistance * blueDistance);
if (distance < leastDistance)
{
colorIndex = (byte)index;
leastDistance = distance;
// And if it's an exact match, exit the loop
if (0 == distance)
{
break;
}
}
}
}
// Now I have the color, pop it into the hashtable for next time
_colorMap.Add(colorHash, colorIndex);
}
return colorIndex;
}
///
/// Retrieve the palette for the quantized image
///
/// Any old palette, this is overrwritten
/// The new color palette
protected override ColorPalette GetPalette(ColorPalette palette)
{
for (int index = 0; index < _colors.Length; index++)
{
palette.Entries[index] = _colors[index];
}
return palette;
}
///
/// Lookup table for colors
///
private Hashtable _colorMap;
///
/// List of all colors in the palette
///
protected Color[] _colors;
}
}