// ----------------------------------------------------------------------- // // 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; } }