mirror of
https://github.com/DarthAffe/HPPH.git
synced 2025-12-12 21:38:59 +00:00
96 lines
2.8 KiB
C#
96 lines
2.8 KiB
C#
using System.Buffers;
|
|
using System.Numerics;
|
|
|
|
namespace HPPH;
|
|
|
|
public static partial class PixelHelper
|
|
{
|
|
#region Methods
|
|
|
|
public static IColor[] CreateColorPalette(this IImage image, int paletteSize)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(image);
|
|
|
|
int dataLength = image.SizeInBytes;
|
|
byte[] array = ArrayPool<byte>.Shared.Rent(dataLength);
|
|
Span<byte> buffer = array.AsSpan()[..dataLength];
|
|
try
|
|
{
|
|
image.CopyTo(buffer);
|
|
return image.ColorFormat.CreateColorPalette(buffer, paletteSize);
|
|
}
|
|
finally
|
|
{
|
|
ArrayPool<byte>.Shared.Return(array);
|
|
}
|
|
}
|
|
|
|
public static T[] CreateColorPalette<T>(this IImage<T> image, int paletteSize)
|
|
where T : unmanaged, IColor
|
|
=> image.AsRefImage().CreateColorPalette(paletteSize);
|
|
|
|
public static T[] CreateColorPalette<T>(this RefImage<T> image, int paletteSize)
|
|
where T : unmanaged, IColor
|
|
{
|
|
int dataLength = image.Width * image.Height;
|
|
T[] array = ArrayPool<T>.Shared.Rent(dataLength);
|
|
Span<T> buffer = array.AsSpan()[..(dataLength)];
|
|
try
|
|
{
|
|
image.CopyTo(buffer);
|
|
return CreateColorPalette(buffer, paletteSize);
|
|
}
|
|
finally
|
|
{
|
|
ArrayPool<T>.Shared.Return(array);
|
|
}
|
|
}
|
|
|
|
public static T[] CreateColorPalette<T>(this ReadOnlySpan<T> colors, int paletteSize)
|
|
where T : unmanaged, IColor
|
|
{
|
|
T[] buffer = ArrayPool<T>.Shared.Rent(colors.Length);
|
|
try
|
|
{
|
|
Span<T> colorBuffer = buffer.AsSpan()[..colors.Length];
|
|
colors.CopyTo(colorBuffer);
|
|
|
|
return CreateColorPalette(colorBuffer, paletteSize);
|
|
}
|
|
finally
|
|
{
|
|
ArrayPool<T>.Shared.Return(buffer);
|
|
}
|
|
}
|
|
|
|
public static T[] CreateColorPalette<T>(this Span<T> colors, int paletteSize)
|
|
where T : unmanaged, IColor
|
|
{
|
|
int splits = BitOperations.Log2((uint)paletteSize);
|
|
|
|
Span<ColorCube<T>> cubes = new ColorCube<T>[1 << splits];
|
|
cubes[0] = new ColorCube<T>(0, colors.Length, SortTarget.None);
|
|
|
|
int currentIndex = 0;
|
|
for (int i = 0; i < splits; i++)
|
|
{
|
|
int currentCubeCount = 1 << i;
|
|
Span<ColorCube<T>> currentCubes = cubes[..currentCubeCount];
|
|
for (int j = 0; j < currentCubes.Length; j++)
|
|
{
|
|
currentCubes[j].Split(colors, out ColorCube<T> a, out ColorCube<T> b);
|
|
currentCubes[j] = a;
|
|
cubes[++currentIndex] = b;
|
|
}
|
|
}
|
|
|
|
T[] result = new T[cubes.Length];
|
|
for (int i = 0; i < cubes.Length; i++)
|
|
result[i] = Average<T>(cubes[i].Slice(colors));
|
|
|
|
return result;
|
|
}
|
|
|
|
#endregion
|
|
}
|