ColorQuantizer.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. using System.Collections.ObjectModel;
  2. using Terminal.Gui.Drawing.Quant;
  3. namespace Terminal.Gui;
  4. /// <summary>
  5. /// Translates colors in an image into a Palette of up to 256 colors.
  6. /// </summary>
  7. public class ColorQuantizer
  8. {
  9. /// <summary>
  10. /// Gets the current colors in the palette based on the last call to
  11. /// <see cref="BuildPalette"/>.
  12. /// </summary>
  13. public IReadOnlyCollection<Color> Palette { get; private set; } = new List<Color> ();
  14. /// <summary>
  15. /// Gets or sets the maximum number of colors to put into the <see cref="Palette"/>.
  16. /// Defaults to 256 (the maximum for sixel images).
  17. /// </summary>
  18. public int MaxColors { get; set; } = 256;
  19. /// <summary>
  20. /// Gets or sets the algorithm used to map novel colors into existing
  21. /// palette colors (closest match). Defaults to <see cref="CIE94ColorDistance"/>
  22. /// </summary>
  23. public IColorDistance DistanceAlgorithm { get; set; } = new CIE94ColorDistance ();
  24. /// <summary>
  25. /// Gets or sets the algorithm used to build the <see cref="Palette"/>.
  26. /// </summary>
  27. public IPaletteBuilder PaletteBuildingAlgorithm { get; set; } = new KMeansPaletteBuilder (new EuclideanColorDistance ()) ;
  28. public void BuildPalette (Color [,] pixels)
  29. {
  30. List<Color> allColors = new List<Color> ();
  31. int width = pixels.GetLength (0);
  32. int height = pixels.GetLength (1);
  33. for (int x = 0; x < width; x++)
  34. {
  35. for (int y = 0; y < height; y++)
  36. {
  37. allColors.Add (pixels [x, y]);
  38. }
  39. }
  40. Palette = PaletteBuildingAlgorithm.BuildPalette (allColors, MaxColors);
  41. }
  42. public int GetNearestColor (Color toTranslate)
  43. {
  44. // Simple nearest color matching based on DistanceAlgorithm
  45. double minDistance = double.MaxValue;
  46. int nearestIndex = 0;
  47. for (var index = 0; index < Palette.Count; index++)
  48. {
  49. Color color = Palette.ElementAt (index);
  50. double distance = DistanceAlgorithm.CalculateDistance (color, toTranslate);
  51. if (distance < minDistance)
  52. {
  53. minDistance = distance;
  54. nearestIndex = index;
  55. }
  56. }
  57. return nearestIndex;
  58. }
  59. }