#region License Information (GPL v3)
/*
ShareX - A program that allows you to take screenshots and share any file type
Copyright (c) 2007-2017 ShareX Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Optionally you can also view the license at .
*/
#endregion License Information (GPL v3)
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
namespace ShareX.HelpersLib
{
///
/// Summary description for PaletteQuantizer.
///
public class PaletteQuantizer : Quantizer
{
///
/// Construct the palette quantizer
///
/// 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;
}
}