mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: 69da68a4a3d8b6a1b0e0ea0f980b90c1f76a5c27 Former-commit-id: 7d3352f72d9aeae1e9a6a37366ef87af6809f3cf Former-commit-id: df1f8fe540d0cdf3548133acd57693bbda7a9dbcpull/1/head
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