mirror of
https://github.com/DarthAffe/HPPH.git
synced 2025-12-12 13:28:37 +00:00
Added first quantization tests
This commit is contained in:
parent
5242845a3e
commit
822d9fa6f1
@ -85,6 +85,6 @@ public class ColorSourceGenerator : IIncrementalGenerator
|
||||
foreach ((string name, string source) in feature.GenerateFor(colorFormats))
|
||||
context.AddSource($"{name}.g.cs", SourceText.From(source, Encoding.UTF8));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,8 +1,94 @@
|
||||
namespace HPPH.Reference;
|
||||
using System.Numerics;
|
||||
|
||||
namespace HPPH.Reference;
|
||||
|
||||
public static partial class ReferencePixelHelper
|
||||
{
|
||||
#region Methods
|
||||
|
||||
public static IColor[] CreateColorPalette(IImage image, int paletteSize)
|
||||
=> CreateColorPalette(image.ToArray(), paletteSize);
|
||||
|
||||
public static T[] CreateColorPalette<T>(RefImage<T> image, int paletteSize)
|
||||
where T : unmanaged, IColor
|
||||
=> CreateColorPalette<T>(image.ToArray(), paletteSize);
|
||||
|
||||
public static T[] CreateColorPalette<T>(Span<T> colors, int paletteSize)
|
||||
where T : unmanaged, IColor =>
|
||||
CreateColorPalette(colors.ToArray().Cast<IColor>().ToArray(), paletteSize).Select(x => T.Create(x.R, x.G, x.B, x.A)).Cast<T>().ToArray();
|
||||
|
||||
private static IColor[] CreateColorPalette(IColor[] colors, int paletteSize)
|
||||
{
|
||||
int splits = BitOperations.Log2((uint)paletteSize);
|
||||
|
||||
List<ColorCube> cubes = [new ColorCube(colors)];
|
||||
|
||||
for (int i = 0; i < splits; i++)
|
||||
{
|
||||
List<ColorCube> currentCubes = [.. cubes];
|
||||
foreach (ColorCube currentCube in currentCubes)
|
||||
{
|
||||
currentCube.Split(out ColorCube a, out ColorCube b);
|
||||
cubes.Remove(currentCube);
|
||||
cubes.Add(a);
|
||||
cubes.Add(b);
|
||||
}
|
||||
}
|
||||
|
||||
return cubes.Select(c => c.GetAverageColor()).ToArray();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
internal class ColorCube
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private readonly List<IColor> _colors;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal ColorCube(IList<IColor> colors)
|
||||
{
|
||||
int redRange = colors.Max(c => c.R) - colors.Min(c => c.R);
|
||||
int greenRange = colors.Max(c => c.G) - colors.Min(c => c.G);
|
||||
int blueRange = colors.Max(c => c.B) - colors.Min(c => c.B);
|
||||
|
||||
if ((redRange > greenRange) && (redRange > blueRange))
|
||||
_colors = [.. colors.OrderBy(a => a.R)];
|
||||
else if (greenRange > blueRange)
|
||||
_colors = [.. colors.OrderBy(a => a.G)];
|
||||
else
|
||||
_colors = [.. colors.OrderBy(a => a.B)];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
internal void Split(out ColorCube a, out ColorCube b)
|
||||
{
|
||||
int median = _colors.Count / 2;
|
||||
|
||||
a = new ColorCube(_colors.GetRange(0, median));
|
||||
b = new ColorCube(_colors.GetRange(median, _colors.Count - median));
|
||||
}
|
||||
|
||||
internal IColor GetAverageColor()
|
||||
{
|
||||
int r = _colors.Sum(x => x.R);
|
||||
int g = _colors.Sum(x => x.G);
|
||||
int b = _colors.Sum(x => x.B);
|
||||
int a = _colors.Sum(x => x.A);
|
||||
|
||||
return new ColorRGBA((byte)(r / _colors.Count),
|
||||
(byte)(g / _colors.Count),
|
||||
(byte)(b / _colors.Count),
|
||||
(byte)(a / _colors.Count));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
117
HPPH.Test/QuantizeTests.cs
Normal file
117
HPPH.Test/QuantizeTests.cs
Normal file
@ -0,0 +1,117 @@
|
||||
using HPPH.Reference;
|
||||
|
||||
namespace HPPH.Test;
|
||||
|
||||
[TestClass]
|
||||
public class CreateColorPaletteTests
|
||||
{
|
||||
private static IEnumerable<string> GetTestImages() => Directory.EnumerateFiles(@"..\..\..\..\sample_data", "*.png", SearchOption.AllDirectories);
|
||||
|
||||
[TestMethod]
|
||||
public void CreateColorPaletteReadOnlySpan3ByteSize1()
|
||||
{
|
||||
foreach (string image in GetTestImages())
|
||||
{
|
||||
ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image);
|
||||
Span<ColorRGB> span = data;
|
||||
|
||||
ColorRGB[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 1).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
ColorRGB[] test = [.. PixelHelper.CreateColorPalette(span, 1).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
|
||||
Assert.AreEqual(reference.Length, test.Length, "Palette Size differs");
|
||||
|
||||
for (int i = 0; i < reference.Length; i++)
|
||||
Assert.AreEqual(reference[i], test[i], $"Index {i} differs");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateColorPaletteReadOnlySpan3ByteSize4()
|
||||
{
|
||||
foreach (string image in GetTestImages())
|
||||
{
|
||||
ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image);
|
||||
Span<ColorRGB> span = data;
|
||||
|
||||
ColorRGB[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 2).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
ColorRGB[] test = [.. PixelHelper.CreateColorPalette(span, 2).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
|
||||
Assert.AreEqual(reference.Length, test.Length, "Palette Size differs");
|
||||
|
||||
for (int i = 0; i < reference.Length; i++)
|
||||
Assert.AreEqual(reference[i], test[i], $"Index {i} differs");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateColorPaletteReadOnlySpan3ByteSize16()
|
||||
{
|
||||
foreach (string image in GetTestImages())
|
||||
{
|
||||
ColorRGB[] data = ImageHelper.Get3ByteColorsFromImage(image);
|
||||
Span<ColorRGB> span = data;
|
||||
|
||||
ColorRGB[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 16).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
ColorRGB[] test = [.. PixelHelper.CreateColorPalette(span, 16).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
|
||||
Assert.AreEqual(reference.Length, test.Length, "Palette Size differs");
|
||||
|
||||
for (int i = 0; i < reference.Length; i++)
|
||||
Assert.AreEqual(reference[i], test[i], $"Index {i} differs");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateColorPaletteReadOnlySpan4ByteSize1()
|
||||
{
|
||||
foreach (string image in GetTestImages())
|
||||
{
|
||||
ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image);
|
||||
Span<ColorRGBA> span = data;
|
||||
|
||||
ColorRGBA[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 1).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
ColorRGBA[] test = [.. PixelHelper.CreateColorPalette(span, 1).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
|
||||
Assert.AreEqual(reference.Length, test.Length, "Palette Size differs");
|
||||
|
||||
for (int i = 0; i < reference.Length; i++)
|
||||
Assert.AreEqual(reference[i], test[i], $"Index {i} differs");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateColorPaletteReadOnlySpan4ByteSize4()
|
||||
{
|
||||
foreach (string image in GetTestImages())
|
||||
{
|
||||
ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image);
|
||||
Span<ColorRGBA> span = data;
|
||||
|
||||
ColorRGBA[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 2).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
ColorRGBA[] test = [.. PixelHelper.CreateColorPalette(span, 2).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
|
||||
Assert.AreEqual(reference.Length, test.Length, "Palette Size differs");
|
||||
|
||||
for (int i = 0; i < reference.Length; i++)
|
||||
Assert.AreEqual(reference[i], test[i], $"Index {i} differs");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void CreateColorPaletteReadOnlySpan4ByteSize16()
|
||||
{
|
||||
foreach (string image in GetTestImages())
|
||||
{
|
||||
ColorRGBA[] data = ImageHelper.Get4ByteColorsFromImage(image);
|
||||
Span<ColorRGBA> span = data;
|
||||
|
||||
ColorRGBA[] reference = [.. ReferencePixelHelper.CreateColorPalette(span, 16).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
ColorRGBA[] test = [.. PixelHelper.CreateColorPalette(span, 16).OrderBy(x => x.R).ThenBy(x => x.G).ThenBy(x => x.B).ThenBy(x => x.A)];
|
||||
|
||||
Assert.AreEqual(reference.Length, test.Length, "Palette Size differs");
|
||||
|
||||
for (int i = 0; i < reference.Length; i++)
|
||||
Assert.AreEqual(reference[i], test[i], $"Index {i} differs");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user