Skip to content

Instantly share code, notes, and snippets.

@JimBobSquarePants
Created June 5, 2021 13:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JimBobSquarePants/7028f84ed2d934108f040cd2d15098f5 to your computer and use it in GitHub Desktop.
Save JimBobSquarePants/7028f84ed2d934108f040cd2d15098f5 to your computer and use it in GitHub Desktop.
A naïve cache for holding color distances. Needs thread safety!
/// <summary>
/// A cache for storing color distance matching results.
/// </summary>
/// <remarks>
/// The cache is limited to 646866 entries at 0.62MB.
/// </remarks>
private struct ColorDistanceCache
{
private const int IndexBits = 5;
private const int IndexAlphaBits = 3;
private const int IndexCount = (1 << IndexBits) + 1;
private const int IndexAlphaCount = (1 << IndexAlphaBits) + 1;
private const int RgbShift = 8 - IndexBits;
private const int AlphaShift = 8 - IndexAlphaBits;
private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount;
private short[] table;
public static ColorDistanceCache Create()
{
ColorDistanceCache result = default;
short[] entries = new short[TableLength];
entries.AsSpan().Fill(-1);
result.table = entries;
return result;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void Add(Rgba32 rgba, byte index)
{
int r = rgba.R >> RgbShift;
int g = rgba.G >> RgbShift;
int b = rgba.B >> RgbShift;
int a = rgba.A >> AlphaShift;
int idx = GetPaletteIndex(r, g, b, a);
this.table[idx] = index;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool TryGetValue(Rgba32 rgba, out short match)
{
int r = rgba.R >> RgbShift;
int g = rgba.G >> RgbShift;
int b = rgba.B >> RgbShift;
int a = rgba.A >> AlphaShift;
int idx = GetPaletteIndex(r, g, b, a);
match = this.table[idx];
return match > -1;
}
[MethodImpl(InliningOptions.ShortMethod)]
private static int GetPaletteIndex(int r, int g, int b, int a)
=> (r << ((IndexBits * 2) + IndexAlphaBits))
+ (r << (IndexBits + IndexAlphaBits + 1))
+ (g << (IndexBits + IndexAlphaBits))
+ (r << (IndexBits * 2))
+ (r << (IndexBits + 1))
+ (g << IndexBits)
+ ((r + g + b) << IndexAlphaBits)
+ r + g + b + a;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment