78 lines
2.2 KiB
C#
78 lines
2.2 KiB
C#
using Minint.Core.Models;
|
|
|
|
namespace Minint.Core.Services.Impl;
|
|
|
|
public sealed class PaletteService : IPaletteService
|
|
{
|
|
public int FindColor(MinintDocument document, RgbaColor color)
|
|
{
|
|
var palette = document.Palette;
|
|
for (int i = 0; i < palette.Count; i++)
|
|
{
|
|
if (palette[i] == color)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public int EnsureColor(MinintDocument document, RgbaColor color)
|
|
{
|
|
int idx = FindColor(document, color);
|
|
if (idx >= 0)
|
|
return idx;
|
|
|
|
idx = document.Palette.Count;
|
|
document.Palette.Add(color);
|
|
return idx;
|
|
}
|
|
|
|
public void CompactPalette(MinintDocument document)
|
|
{
|
|
var palette = document.Palette;
|
|
if (palette.Count <= 1)
|
|
return;
|
|
|
|
// 1. Collect indices actually used across all layers
|
|
var usedIndices = new HashSet<int> { 0 }; // always keep transparent
|
|
foreach (var layer in document.Layers)
|
|
{
|
|
foreach (int idx in layer.Pixels)
|
|
usedIndices.Add(idx);
|
|
}
|
|
|
|
// 2. Build new palette and old→new mapping
|
|
var oldToNew = new int[palette.Count];
|
|
var newPalette = new List<RgbaColor>(usedIndices.Count);
|
|
|
|
// Index 0 (transparent) stays at 0
|
|
newPalette.Add(palette[0]);
|
|
oldToNew[0] = 0;
|
|
|
|
for (int i = 1; i < palette.Count; i++)
|
|
{
|
|
if (usedIndices.Contains(i))
|
|
{
|
|
oldToNew[i] = newPalette.Count;
|
|
newPalette.Add(palette[i]);
|
|
}
|
|
// unused indices don't get a mapping — they'll never be looked up
|
|
}
|
|
|
|
// 3. If nothing was removed, skip the remap
|
|
if (newPalette.Count == palette.Count)
|
|
return;
|
|
|
|
// 4. Replace palette
|
|
palette.Clear();
|
|
palette.AddRange(newPalette);
|
|
|
|
// 5. Remap all pixel arrays
|
|
foreach (var layer in document.Layers)
|
|
{
|
|
var px = layer.Pixels;
|
|
for (int i = 0; i < px.Length; i++)
|
|
px[i] = oldToNew[px[i]];
|
|
}
|
|
}
|
|
}
|