mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 69da68a4a3d8b6a1b0e0ea0f980b90c1f76a5c27 Former-commit-id: 7d3352f72d9aeae1e9a6a37366ef87af6809f3cf Former-commit-id: df1f8fe540d0cdf3548133acd57693bbda7a9dbcaf/merge-core
7 changed files with 415 additions and 111 deletions
@ -0,0 +1,179 @@ |
|||
// <copyright file="ColorConstants.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// Provides useful color definitions.
|
|||
/// </summary>
|
|||
public static class ColorConstants |
|||
{ |
|||
/// <summary>
|
|||
/// Provides a lazy, one time method of returning the colors.
|
|||
/// </summary>
|
|||
private static readonly Lazy<Color[]> SafeColors = new Lazy<Color[]>(GetWebSafeColors); |
|||
|
|||
/// <summary>
|
|||
/// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4.
|
|||
/// </summary>
|
|||
public static Color[] WebSafeColors => SafeColors.Value; |
|||
|
|||
/// <summary>
|
|||
/// Returns an array of web safe colors.
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
private static Color[] GetWebSafeColors() |
|||
{ |
|||
return new List<Color> |
|||
{ |
|||
Color.AliceBlue, |
|||
Color.AntiqueWhite, |
|||
Color.Aqua, |
|||
Color.Aquamarine, |
|||
Color.Azure, |
|||
Color.Beige, |
|||
Color.Bisque, |
|||
Color.Black, |
|||
Color.BlanchedAlmond, |
|||
Color.Blue, |
|||
Color.BlueViolet, |
|||
Color.Brown, |
|||
Color.BurlyWood, |
|||
Color.CadetBlue, |
|||
Color.Chartreuse, |
|||
Color.Chocolate, |
|||
Color.Coral, |
|||
Color.CornflowerBlue, |
|||
Color.Cornsilk, |
|||
Color.Crimson, |
|||
Color.Cyan, |
|||
Color.DarkBlue, |
|||
Color.DarkCyan, |
|||
Color.DarkGoldenrod, |
|||
Color.DarkGray, |
|||
Color.DarkGreen, |
|||
Color.DarkKhaki, |
|||
Color.DarkMagenta, |
|||
Color.DarkOliveGreen, |
|||
Color.DarkOrange, |
|||
Color.DarkOrchid, |
|||
Color.DarkRed, |
|||
Color.DarkSalmon, |
|||
Color.DarkSeaGreen, |
|||
Color.DarkSlateBlue, |
|||
Color.DarkSlateGray, |
|||
Color.DarkTurquoise, |
|||
Color.DarkViolet, |
|||
Color.DeepPink, |
|||
Color.DeepSkyBlue, |
|||
Color.DimGray, |
|||
Color.DodgerBlue, |
|||
Color.Firebrick, |
|||
Color.FloralWhite, |
|||
Color.ForestGreen, |
|||
Color.Fuchsia, |
|||
Color.Gainsboro, |
|||
Color.GhostWhite, |
|||
Color.Gold, |
|||
Color.Goldenrod, |
|||
Color.Gray, |
|||
Color.Green, |
|||
Color.GreenYellow, |
|||
Color.Honeydew, |
|||
Color.HotPink, |
|||
Color.IndianRed, |
|||
Color.Indigo, |
|||
Color.Ivory, |
|||
Color.Khaki, |
|||
Color.Lavender, |
|||
Color.LavenderBlush, |
|||
Color.LawnGreen, |
|||
Color.LemonChiffon, |
|||
Color.LightBlue, |
|||
Color.LightCoral, |
|||
Color.LightCyan, |
|||
Color.LightGoldenrodYellow, |
|||
Color.LightGray, |
|||
Color.LightGreen, |
|||
Color.LightPink, |
|||
Color.LightSalmon, |
|||
Color.LightSeaGreen, |
|||
Color.LightSkyBlue, |
|||
Color.LightSlateGray, |
|||
Color.LightSteelBlue, |
|||
Color.LightYellow, |
|||
Color.Lime, |
|||
Color.LimeGreen, |
|||
Color.Linen, |
|||
Color.Magenta, |
|||
Color.Maroon, |
|||
Color.MediumAquamarine, |
|||
Color.MediumBlue, |
|||
Color.MediumOrchid, |
|||
Color.MediumPurple, |
|||
Color.MediumSeaGreen, |
|||
Color.MediumSlateBlue, |
|||
Color.MediumSpringGreen, |
|||
Color.MediumTurquoise, |
|||
Color.MediumVioletRed, |
|||
Color.MidnightBlue, |
|||
Color.MintCream, |
|||
Color.MistyRose, |
|||
Color.Moccasin, |
|||
Color.NavajoWhite, |
|||
Color.Navy, |
|||
Color.OldLace, |
|||
Color.Olive, |
|||
Color.OliveDrab, |
|||
Color.Orange, |
|||
Color.OrangeRed, |
|||
Color.Orchid, |
|||
Color.PaleGoldenrod, |
|||
Color.PaleGreen, |
|||
Color.PaleTurquoise, |
|||
Color.PaleVioletRed, |
|||
Color.PapayaWhip, |
|||
Color.PeachPuff, |
|||
Color.Peru, |
|||
Color.Pink, |
|||
Color.Plum, |
|||
Color.PowderBlue, |
|||
Color.Purple, |
|||
Color.RebeccaPurple, |
|||
Color.Red, |
|||
Color.RosyBrown, |
|||
Color.RoyalBlue, |
|||
Color.SaddleBrown, |
|||
Color.Salmon, |
|||
Color.SandyBrown, |
|||
Color.SeaGreen, |
|||
Color.SeaShell, |
|||
Color.Sienna, |
|||
Color.Silver, |
|||
Color.SkyBlue, |
|||
Color.SlateBlue, |
|||
Color.SlateGray, |
|||
Color.Snow, |
|||
Color.SpringGreen, |
|||
Color.SteelBlue, |
|||
Color.Tan, |
|||
Color.Teal, |
|||
Color.Thistle, |
|||
Color.Tomato, |
|||
Color.Transparent, |
|||
Color.Turquoise, |
|||
Color.Violet, |
|||
Color.Wheat, |
|||
Color.White, |
|||
Color.WhiteSmoke, |
|||
Color.Yellow, |
|||
Color.YellowGreen |
|||
}.ToArray(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
// <copyright file="PaletteQuantizer.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessorCore.Quantizers |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods to create a quantized image based upon the given palette.
|
|||
/// <see href="http://msdn.microsoft.com/en-us/library/aa479306.aspx"/>
|
|||
/// </summary>
|
|||
public class PaletteQuantizer : Quantizer |
|||
{ |
|||
/// <summary>
|
|||
/// A lookup table for colors
|
|||
/// </summary>
|
|||
private readonly Dictionary<int, byte> colorMap = new Dictionary<int, byte>(); |
|||
|
|||
/// <summary>
|
|||
/// List of all colors in the palette
|
|||
/// </summary>
|
|||
private Bgra32[] colors; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PaletteQuantizer"/> class.
|
|||
/// </summary>
|
|||
/// <param name="palette">
|
|||
/// The color palette. If none is given this will default to the web safe colors defined
|
|||
/// in the CSS Color Module Level 4.
|
|||
/// </param>
|
|||
public PaletteQuantizer(Color[] palette = null) |
|||
: base(true) |
|||
{ |
|||
this.colors = palette == null |
|||
? ColorConstants.WebSafeColors.Select(c => (Bgra32)c).ToArray() |
|||
: palette.Select(c => (Bgra32)c).ToArray(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override QuantizedImage Quantize(ImageBase image, int maxColors) |
|||
{ |
|||
Array.Resize(ref this.colors, maxColors.Clamp(1, 256)); |
|||
return base.Quantize(image, maxColors); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override byte QuantizePixel(Bgra32 pixel) |
|||
{ |
|||
byte colorIndex = 0; |
|||
int colorHash = pixel.Bgra; |
|||
|
|||
// Check if the color is in the lookup table
|
|||
if (this.colorMap.ContainsKey(colorHash)) |
|||
{ |
|||
colorIndex = this.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 (pixel.A == 0) |
|||
{ |
|||
// Transparent. Lookup the first color with an alpha value of 0
|
|||
for (int index = 0; index < this.colors.Length; index++) |
|||
{ |
|||
if (this.colors[index].A == 0) |
|||
{ |
|||
colorIndex = (byte)index; |
|||
this.TransparentIndex = colorIndex; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
// Not transparent...
|
|||
int leastDistance = int.MaxValue; |
|||
int red = pixel.R; |
|||
int green = pixel.G; |
|||
int blue = pixel.B; |
|||
|
|||
// Loop through the entire palette, looking for the closest color match
|
|||
for (int index = 0; index < this.colors.Length; index++) |
|||
{ |
|||
Bgra32 paletteColor = this.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 (distance == 0) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Now I have the color, pop it into the cache for next time
|
|||
this.colorMap.Add(colorHash, colorIndex); |
|||
} |
|||
|
|||
return colorIndex; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override List<Bgra32> GetPalette() |
|||
{ |
|||
return this.colors.ToList(); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue