diff --git a/src/ImageProcessorCore/Colors/ColorConstants.cs b/src/ImageProcessorCore/Colors/ColorConstants.cs new file mode 100644 index 000000000..ed9718423 --- /dev/null +++ b/src/ImageProcessorCore/Colors/ColorConstants.cs @@ -0,0 +1,179 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore +{ + using System; + using System.Collections.Generic; + + /// + /// Provides useful color definitions. + /// + public static class ColorConstants + { + /// + /// Provides a lazy, one time method of returning the colors. + /// + private static readonly Lazy SafeColors = new Lazy(GetWebSafeColors); + + /// + /// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4. + /// + public static Color[] WebSafeColors => SafeColors.Value; + + /// + /// Returns an array of web safe colors. + /// + /// + private static Color[] GetWebSafeColors() + { + return new List + { + 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(); + } + } +} diff --git a/src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs b/src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs index f5f80e689..1080daf0e 100644 --- a/src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs @@ -101,7 +101,6 @@ namespace ImageProcessorCore.Formats amount = 4 - amount; } - // TODO: Make this parallel. for (int y = image.Height - 1; y >= 0; y--) { for (int x = 0; x < image.Width; x++) diff --git a/src/ImageProcessorCore/Formats/Gif/GifEncoder.cs b/src/ImageProcessorCore/Formats/Gif/GifEncoder.cs index 995cab207..877931772 100644 --- a/src/ImageProcessorCore/Formats/Gif/GifEncoder.cs +++ b/src/ImageProcessorCore/Formats/Gif/GifEncoder.cs @@ -26,7 +26,7 @@ namespace ImageProcessorCore.Formats /// /// The quantizer for reducing the color count. /// - public IQuantizer Quantizer { get; set; } = new WuQuantizer(); + public IQuantizer Quantizer { get; set; } = new OctreeQuantizer(); /// public string Extension => "gif"; @@ -130,12 +130,12 @@ namespace ImageProcessorCore.Formats /// The private QuantizedImage WriteColorTable(ImageBase image, Stream stream, int quality, int bitDepth) { - // Quantize the image returning a pallete. + // Quantize the image returning a palette. QuantizedImage quantizedImage = this.Quantizer.Quantize(image, quality.Clamp(1, 255)); - // Grab the pallete and write it to the stream. - Bgra32[] pallete = quantizedImage.Palette; - int pixelCount = pallete.Length; + // Grab the palette and write it to the stream. + Bgra32[] palette = quantizedImage.Palette; + int pixelCount = palette.Length; // Get max colors for bit depth. int colorTableLength = (int)Math.Pow(2, bitDepth) * 3; @@ -145,7 +145,7 @@ namespace ImageProcessorCore.Formats i => { int offset = i * 3; - Bgra32 color = pallete[i]; + Bgra32 color = palette[i]; colorTable[offset] = color.R; colorTable[offset + 1] = color.G; diff --git a/src/ImageProcessorCore/ImageExtensions.cs b/src/ImageProcessorCore/ImageExtensions.cs index 50665b747..6a6d0e3f0 100644 --- a/src/ImageProcessorCore/ImageExtensions.cs +++ b/src/ImageProcessorCore/ImageExtensions.cs @@ -40,7 +40,7 @@ namespace ImageProcessorCore /// The stream to save the image to. /// The quality to save the image to. Between 1 and 100. /// Thrown if the stream is null. - public static void SaveAsJpeg(this ImageBase source, Stream stream, int quality = 80) => new JpegEncoder { Quality = quality }.Encode(source, stream); + public static void SaveAsJpeg(this ImageBase source, Stream stream, int quality = 75) => new JpegEncoder { Quality = quality }.Encode(source, stream); /// /// Saves the image to the given stream with the gif format. diff --git a/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs b/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs index 2a330f782..5ee54d762 100644 --- a/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs +++ b/src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs @@ -58,7 +58,7 @@ namespace ImageProcessorCore.Quantizers byte[] quantizedPixels = new byte[width * height]; - // Get the pallete + // Get the palette List palette = this.GetPalette(); this.SecondPass(image, quantizedPixels, width, height); diff --git a/src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs b/src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs new file mode 100644 index 000000000..74f192834 --- /dev/null +++ b/src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs @@ -0,0 +1,126 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore.Quantizers +{ + using System; + using System.Collections.Generic; + using System.Linq; + + /// + /// Encapsulates methods to create a quantized image based upon the given palette. + /// + /// + public class PaletteQuantizer : Quantizer + { + /// + /// A lookup table for colors + /// + private readonly Dictionary colorMap = new Dictionary(); + + /// + /// List of all colors in the palette + /// + private Bgra32[] colors; + + /// + /// Initializes a new instance of the class. + /// + /// + /// The color palette. If none is given this will default to the web safe colors defined + /// in the CSS Color Module Level 4. + /// + public PaletteQuantizer(Color[] palette = null) + : base(true) + { + this.colors = palette == null + ? ColorConstants.WebSafeColors.Select(c => (Bgra32)c).ToArray() + : palette.Select(c => (Bgra32)c).ToArray(); + } + + /// + public override QuantizedImage Quantize(ImageBase image, int maxColors) + { + Array.Resize(ref this.colors, maxColors.Clamp(1, 256)); + return base.Quantize(image, maxColors); + } + + /// + 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; + } + + /// + protected override List GetPalette() + { + return this.colors.ToList(); + } + } +} diff --git a/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs b/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs index aa2a88048..660e5e5af 100644 --- a/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs +++ b/src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs @@ -136,7 +136,7 @@ namespace ImageProcessorCore.Quantizers /// The blue value. /// The alpha value. /// The index. - private static int GetPalleteIndex(int r, int g, int b, int a) + private static int GetPaletteIndex(int r, int g, int b, int a) { return (r << ((IndexBits * 2) + IndexAlphaBits)) + (r << (IndexBits + IndexAlphaBits + 1)) @@ -156,22 +156,22 @@ namespace ImageProcessorCore.Quantizers /// The result. private static double Volume(Box cube, long[] moment) { - return moment[GetPalleteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - - moment[GetPalleteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - - moment[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] + - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; } /// @@ -187,47 +187,47 @@ namespace ImageProcessorCore.Quantizers { // Red case 0: - return -moment[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Green case 1: - return -moment[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Blue case 2: - return -moment[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; // Alpha case 3: - return -moment[GetPalleteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + return -moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; default: throw new ArgumentOutOfRangeException(nameof(direction)); @@ -248,47 +248,47 @@ namespace ImageProcessorCore.Quantizers { // Red case 0: - return moment[GetPalleteIndex(position, cube.G1, cube.B1, cube.A1)] - - moment[GetPalleteIndex(position, cube.G1, cube.B1, cube.A0)] - - moment[GetPalleteIndex(position, cube.G1, cube.B0, cube.A1)] - + moment[GetPalleteIndex(position, cube.G1, cube.B0, cube.A0)] - - moment[GetPalleteIndex(position, cube.G0, cube.B1, cube.A1)] - + moment[GetPalleteIndex(position, cube.G0, cube.B1, cube.A0)] - + moment[GetPalleteIndex(position, cube.G0, cube.B0, cube.A1)] - - moment[GetPalleteIndex(position, cube.G0, cube.B0, cube.A0)]; + return moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A1)] + - moment[GetPaletteIndex(position, cube.G1, cube.B1, cube.A0)] + - moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A1)] + + moment[GetPaletteIndex(position, cube.G1, cube.B0, cube.A0)] + - moment[GetPaletteIndex(position, cube.G0, cube.B1, cube.A1)] + + moment[GetPaletteIndex(position, cube.G0, cube.B1, cube.A0)] + + moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A1)] + - moment[GetPaletteIndex(position, cube.G0, cube.B0, cube.A0)]; // Green case 1: - return moment[GetPalleteIndex(cube.R1, position, cube.B1, cube.A1)] - - moment[GetPalleteIndex(cube.R1, position, cube.B1, cube.A0)] - - moment[GetPalleteIndex(cube.R1, position, cube.B0, cube.A1)] - + moment[GetPalleteIndex(cube.R1, position, cube.B0, cube.A0)] - - moment[GetPalleteIndex(cube.R0, position, cube.B1, cube.A1)] - + moment[GetPalleteIndex(cube.R0, position, cube.B1, cube.A0)] - + moment[GetPalleteIndex(cube.R0, position, cube.B0, cube.A1)] - - moment[GetPalleteIndex(cube.R0, position, cube.B0, cube.A0)]; + return moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A1)] + - moment[GetPaletteIndex(cube.R1, position, cube.B1, cube.A0)] + - moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A1)] + + moment[GetPaletteIndex(cube.R1, position, cube.B0, cube.A0)] + - moment[GetPaletteIndex(cube.R0, position, cube.B1, cube.A1)] + + moment[GetPaletteIndex(cube.R0, position, cube.B1, cube.A0)] + + moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A1)] + - moment[GetPaletteIndex(cube.R0, position, cube.B0, cube.A0)]; // Blue case 2: - return moment[GetPalleteIndex(cube.R1, cube.G1, position, cube.A1)] - - moment[GetPalleteIndex(cube.R1, cube.G1, position, cube.A0)] - - moment[GetPalleteIndex(cube.R1, cube.G0, position, cube.A1)] - + moment[GetPalleteIndex(cube.R1, cube.G0, position, cube.A0)] - - moment[GetPalleteIndex(cube.R0, cube.G1, position, cube.A1)] - + moment[GetPalleteIndex(cube.R0, cube.G1, position, cube.A0)] - + moment[GetPalleteIndex(cube.R0, cube.G0, position, cube.A1)] - - moment[GetPalleteIndex(cube.R0, cube.G0, position, cube.A0)]; + return moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A1)] + - moment[GetPaletteIndex(cube.R1, cube.G1, position, cube.A0)] + - moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A1)] + + moment[GetPaletteIndex(cube.R1, cube.G0, position, cube.A0)] + - moment[GetPaletteIndex(cube.R0, cube.G1, position, cube.A1)] + + moment[GetPaletteIndex(cube.R0, cube.G1, position, cube.A0)] + + moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A1)] + - moment[GetPaletteIndex(cube.R0, cube.G0, position, cube.A0)]; // Alpha case 3: - return moment[GetPalleteIndex(cube.R1, cube.G1, cube.B1, position)] - - moment[GetPalleteIndex(cube.R1, cube.G1, cube.B0, position)] - - moment[GetPalleteIndex(cube.R1, cube.G0, cube.B1, position)] - + moment[GetPalleteIndex(cube.R1, cube.G0, cube.B0, position)] - - moment[GetPalleteIndex(cube.R0, cube.G1, cube.B1, position)] - + moment[GetPalleteIndex(cube.R0, cube.G1, cube.B0, position)] - + moment[GetPalleteIndex(cube.R0, cube.G0, cube.B1, position)] - - moment[GetPalleteIndex(cube.R0, cube.G0, cube.B0, position)]; + return moment[GetPaletteIndex(cube.R1, cube.G1, cube.B1, position)] + - moment[GetPaletteIndex(cube.R1, cube.G1, cube.B0, position)] + - moment[GetPaletteIndex(cube.R1, cube.G0, cube.B1, position)] + + moment[GetPaletteIndex(cube.R1, cube.G0, cube.B0, position)] + - moment[GetPaletteIndex(cube.R0, cube.G1, cube.B1, position)] + + moment[GetPaletteIndex(cube.R0, cube.G1, cube.B0, position)] + + moment[GetPaletteIndex(cube.R0, cube.G0, cube.B1, position)] + - moment[GetPaletteIndex(cube.R0, cube.G0, cube.B0, position)]; default: throw new ArgumentOutOfRangeException(nameof(direction)); @@ -332,7 +332,7 @@ namespace ImageProcessorCore.Quantizers int inb = b >> (8 - IndexBits); int ina = a >> (8 - IndexAlphaBits); - int ind = GetPalleteIndex(inr + 1, ing + 1, inb + 1, ina + 1); + int ind = GetPaletteIndex(inr + 1, ing + 1, inb + 1, ina + 1); this.vwt[ind]++; this.vmr[ind] += r; @@ -393,7 +393,7 @@ namespace ImageProcessorCore.Quantizers for (int a = 1; a < IndexAlphaCount; a++) { - int ind1 = GetPalleteIndex(r, g, b, a); + int ind1 = GetPaletteIndex(r, g, b, a); line += this.vwt[ind1]; lineR += this.vmr[ind1]; @@ -418,7 +418,7 @@ namespace ImageProcessorCore.Quantizers volumeA[inv] += areaA[a]; volume2[inv] += area2[a]; - int ind2 = ind1 - GetPalleteIndex(1, 0, 0, 0); + int ind2 = ind1 - GetPaletteIndex(1, 0, 0, 0); this.vwt[ind1] = this.vwt[ind2] + volume[inv]; this.vmr[ind1] = this.vmr[ind2] + volumeR[inv]; @@ -445,22 +445,22 @@ namespace ImageProcessorCore.Quantizers double da = Volume(cube, this.vma); double xx = - this.m2[GetPalleteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] - - this.m2[GetPalleteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] - - this.m2[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] - + this.m2[GetPalleteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] - - this.m2[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] - + this.m2[GetPalleteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] - + this.m2[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] - - this.m2[GetPalleteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] - - this.m2[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] - + this.m2[GetPalleteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] - + this.m2[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] - - this.m2[GetPalleteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] - + this.m2[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] - - this.m2[GetPalleteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] - - this.m2[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] - + this.m2[GetPalleteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; + this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A1)] + - this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B1, cube.A0)] + - this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A1)] + + this.m2[GetPaletteIndex(cube.R1, cube.G1, cube.B0, cube.A0)] + - this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A1)] + + this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B1, cube.A0)] + + this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A1)] + - this.m2[GetPaletteIndex(cube.R1, cube.G0, cube.B0, cube.A0)] + - this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A1)] + + this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B1, cube.A0)] + + this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A1)] + - this.m2[GetPaletteIndex(cube.R0, cube.G1, cube.B0, cube.A0)] + + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A1)] + - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B1, cube.A0)] + - this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A1)] + + this.m2[GetPaletteIndex(cube.R0, cube.G0, cube.B0, cube.A0)]; return xx - (((dr * dr) + (dg * dg) + (db * db) + (da * da)) / Volume(cube, this.vwt)); } @@ -643,7 +643,7 @@ namespace ImageProcessorCore.Quantizers { for (int a = cube.A0 + 1; a <= cube.A1; a++) { - this.tag[GetPalleteIndex(r, g, b, a)] = label; + this.tag[GetPaletteIndex(r, g, b, a)] = label; } } } @@ -758,7 +758,7 @@ namespace ImageProcessorCore.Quantizers int g = color.G >> (8 - IndexBits); int b = color.B >> (8 - IndexBits); - int ind = GetPalleteIndex(r + 1, g + 1, b + 1, a + 1); + int ind = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1); pixels[i++] = this.tag[ind]; } }