Browse Source

Add palette quantizer.

Former-commit-id: 69da68a4a3d8b6a1b0e0ea0f980b90c1f76a5c27
Former-commit-id: 7d3352f72d9aeae1e9a6a37366ef87af6809f3cf
Former-commit-id: df1f8fe540d0cdf3548133acd57693bbda7a9dbc
af/merge-core
James Jackson-South 10 years ago
parent
commit
cba61c1fb5
  1. 179
      src/ImageProcessorCore/Colors/ColorConstants.cs
  2. 1
      src/ImageProcessorCore/Formats/Bmp/BmpEncoder.cs
  3. 12
      src/ImageProcessorCore/Formats/Gif/GifEncoder.cs
  4. 2
      src/ImageProcessorCore/ImageExtensions.cs
  5. 2
      src/ImageProcessorCore/Quantizers/Octree/Quantizer.cs
  6. 126
      src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs
  7. 204
      src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs

179
src/ImageProcessorCore/Colors/ColorConstants.cs

@ -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();
}
}
}

1
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++)

12
src/ImageProcessorCore/Formats/Gif/GifEncoder.cs

@ -26,7 +26,7 @@ namespace ImageProcessorCore.Formats
/// <summary>
/// The quantizer for reducing the color count.
/// </summary>
public IQuantizer Quantizer { get; set; } = new WuQuantizer();
public IQuantizer Quantizer { get; set; } = new OctreeQuantizer();
/// <inheritdoc/>
public string Extension => "gif";
@ -130,12 +130,12 @@ namespace ImageProcessorCore.Formats
/// <returns>The <see cref="QuantizedImage"/></returns>
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;

2
src/ImageProcessorCore/ImageExtensions.cs

@ -40,7 +40,7 @@ namespace ImageProcessorCore
/// <param name="stream">The stream to save the image to.</param>
/// <param name="quality">The quality to save the image to. Between 1 and 100.</param>
/// <exception cref="ArgumentNullException">Thrown if the stream is null.</exception>
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);
/// <summary>
/// Saves the image to the given stream with the gif format.

2
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<Bgra32> palette = this.GetPalette();
this.SecondPass(image, quantizedPixels, width, height);

126
src/ImageProcessorCore/Quantizers/Palette/PaletteQuantizer.cs

@ -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();
}
}
}

204
src/ImageProcessorCore/Quantizers/Wu/WuQuantizer.cs

@ -136,7 +136,7 @@ namespace ImageProcessorCore.Quantizers
/// <param name="b">The blue value.</param>
/// <param name="a">The alpha value.</param>
/// <returns>The index.</returns>
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
/// <returns>The result.</returns>
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)];
}
/// <summary>
@ -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];
}
}

Loading…
Cancel
Save