diff --git a/Terminal.Gui/Drawing/Quant/CIE76ColorDistance.cs b/Terminal.Gui/Drawing/Quant/CIE76ColorDistance.cs
deleted file mode 100644
index c2cc4d12e..000000000
--- a/Terminal.Gui/Drawing/Quant/CIE76ColorDistance.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace Terminal.Gui;
-
-///
-/// This is the simplest method to measure color difference in the CIE Lab color space. The Euclidean distance in Lab
-/// space is more aligned with human perception than RGB space, as Lab attempts to model how humans perceive color differences.
-///
-public class CIE76ColorDistance : LabColorDistance
-{
- public override double CalculateDistance (Color c1, Color c2)
- {
- var lab1 = RgbToLab (c1);
- var lab2 = RgbToLab (c2);
-
- // Euclidean distance in Lab color space
- return Math.Sqrt (Math.Pow (lab1.L - lab2.L, 2) + Math.Pow (lab1.A - lab2.A, 2) + Math.Pow (lab1.B - lab2.B, 2));
- }
-}
diff --git a/Terminal.Gui/Drawing/Quant/CIE94ColorDistance.cs b/Terminal.Gui/Drawing/Quant/CIE94ColorDistance.cs
deleted file mode 100644
index b5103638f..000000000
--- a/Terminal.Gui/Drawing/Quant/CIE94ColorDistance.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-namespace Terminal.Gui;
-
-///
-/// CIE94 improves on CIE76 by introducing adjustments for chroma (color intensity) and lightness.
-/// This algorithm considers human visual perception more accurately by scaling differences in lightness and chroma.
-/// It is better but slower than .
-///
-public class CIE94ColorDistance : LabColorDistance
-{
- // Constants for CIE94 formula (can be modified for different use cases like textiles or graphics)
- private const double kL = 1.0;
- private const double kC = 1.0;
- private const double kH = 1.0;
-
- public override double CalculateDistance (Color first, Color second)
- {
- var lab1 = RgbToLab (first);
- var lab2 = RgbToLab (second);
-
- // Delta L, A, B
- double deltaL = lab1.L - lab2.L;
- double deltaA = lab1.A - lab2.A;
- double deltaB = lab1.B - lab2.B;
-
- // Chroma values for both colors
- double c1 = Math.Sqrt (lab1.A * lab1.A + lab1.B * lab1.B);
- double c2 = Math.Sqrt (lab2.A * lab2.A + lab2.B * lab2.B);
- double deltaC = c1 - c2;
-
- // Delta H (calculated indirectly)
- double deltaH = Math.Sqrt (Math.Pow (deltaA, 2) + Math.Pow (deltaB, 2) - Math.Pow (deltaC, 2));
-
- // Scaling factors
- double sL = 1.0;
- double sC = 1.0 + 0.045 * c1;
- double sH = 1.0 + 0.015 * c1;
-
- // CIE94 color difference formula
- return Math.Sqrt (
- Math.Pow (deltaL / (kL * sL), 2) +
- Math.Pow (deltaC / (kC * sC), 2) +
- Math.Pow (deltaH / (kH * sH), 2)
- );
- }
-}
diff --git a/Terminal.Gui/Drawing/Quant/LabColorDistance.cs b/Terminal.Gui/Drawing/Quant/LabColorDistance.cs
deleted file mode 100644
index f1d97b590..000000000
--- a/Terminal.Gui/Drawing/Quant/LabColorDistance.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using ColorHelper;
-
-namespace Terminal.Gui;
-
-public abstract class LabColorDistance : IColorDistance
-{
- // Reference white point for D65 illuminant (can be moved to constants)
- private const double RefX = 95.047;
- private const double RefY = 100.000;
- private const double RefZ = 108.883;
-
- // Conversion from RGB to Lab
- protected LabColor RgbToLab (Color c)
- {
- var xyz = ColorHelper.ColorConverter.RgbToXyz (new RGB (c.R, c.G, c.B));
-
- // Normalize XYZ values by reference white point
- double x = xyz.X / RefX;
- double y = xyz.Y / RefY;
- double z = xyz.Z / RefZ;
-
- // Apply the nonlinear transformation for Lab
- x = x > 0.008856 ? Math.Pow (x, 1.0 / 3.0) : 7.787 * x + 16.0 / 116.0;
- y = y > 0.008856 ? Math.Pow (y, 1.0 / 3.0) : 7.787 * y + 16.0 / 116.0;
- z = z > 0.008856 ? Math.Pow (z, 1.0 / 3.0) : 7.787 * z + 16.0 / 116.0;
-
- // Calculate Lab values
- double l = 116.0 * y - 16.0;
- double a = 500.0 * (x - y);
- double b = 200.0 * (y - z);
-
- return new LabColor (l, a, b);
- }
-
- // LabColor class encapsulating L, A, and B values
- protected class LabColor
- {
- public double L { get; }
- public double A { get; }
- public double B { get; }
-
- public LabColor (double l, double a, double b)
- {
- L = l;
- A = a;
- B = b;
- }
- }
-
- ///
- public abstract double CalculateDistance (Color c1, Color c2);
-}
diff --git a/UICatalog/Scenarios/Images.cs b/UICatalog/Scenarios/Images.cs
index 8e50d8914..f929cabab 100644
--- a/UICatalog/Scenarios/Images.cs
+++ b/UICatalog/Scenarios/Images.cs
@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using ColorHelper;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@@ -20,7 +21,7 @@ public class Images : Scenario
public override void Main ()
{
Application.Init ();
- var win = new Window { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName()}" };
+ var win = new Window { Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}" };
bool canTrueColor = Application.Driver?.SupportsTrueColor ?? false;
@@ -50,7 +51,7 @@ public class Images : Scenario
var btnOpenImage = new Button { X = Pos.Right (cbUseTrueColor) + 2, Y = 0, Text = "Open Image" };
win.Add (btnOpenImage);
-
+
var imageView = new ImageView
{
X = 0, Y = Pos.Bottom (lblDriverName), Width = Dim.Fill (), Height = Dim.Fill ()
@@ -105,10 +106,8 @@ public class Images : Scenario
Application.Refresh ();
};
-
-
- var btnSixel = new Button () { X = Pos.Right (btnOpenImage) + 2, Y = 0, Text = "Output Sixel" };
- btnSixel.Accept += (s, e) => { imageView.OutputSixel ();};
+ var btnSixel = new Button { X = Pos.Right (btnOpenImage) + 2, Y = 0, Text = "Output Sixel" };
+ btnSixel.Accept += (s, e) => { imageView.OutputSixel (); };
win.Add (btnSixel);
Application.Run (win);
@@ -116,7 +115,6 @@ public class Images : Scenario
Application.Shutdown ();
}
-
private class ImageView : View
{
private readonly ConcurrentDictionary _cache = new ();
@@ -147,10 +145,10 @@ public class Images : Scenario
Attribute attr = _cache.GetOrAdd (
rgb,
- rgb => new Attribute (
- new Color (),
- new Color (rgb.R, rgb.G, rgb.B)
- )
+ rgb => new (
+ new Color (),
+ new Color (rgb.R, rgb.G, rgb.B)
+ )
);
Driver.SetAttribute (attr);
@@ -174,18 +172,18 @@ public class Images : Scenario
var encoder = new SixelEncoder ();
- var encoded = encoder.EncodeSixel (ConvertToColorArray (_fullResImage));
+ string encoded = encoder.EncodeSixel (ConvertToColorArray (_fullResImage));
var pv = new PaletteView (encoder.Quantizer.Palette.ToList ());
- var dlg = new Dialog ()
+ var dlg = new Dialog
{
Title = "Palette (Esc to close)",
Width = Dim.Fill (2),
- Height = Dim.Fill (1),
+ Height = Dim.Fill (1)
};
- var btn = new Button ()
+ var btn = new Button
{
Text = "Ok"
};
@@ -197,6 +195,7 @@ public class Images : Scenario
Application.Sixel = encoded;
}
+
public static Color [,] ConvertToColorArray (Image image)
{
int width = image.Width;
@@ -204,18 +203,19 @@ public class Images : Scenario
Color [,] colors = new Color [width, height];
// Loop through each pixel and convert Rgba32 to Terminal.Gui color
- for (int x = 0; x < width; x++)
+ for (var x = 0; x < width; x++)
{
- for (int y = 0; y < height; y++)
+ for (var y = 0; y < height; y++)
{
- var pixel = image [x, y];
- colors [x, y] = new Color (pixel.R, pixel.G, pixel.B); // Convert Rgba32 to Terminal.Gui color
+ Rgba32 pixel = image [x, y];
+ colors [x, y] = new (pixel.R, pixel.G, pixel.B); // Convert Rgba32 to Terminal.Gui color
}
}
return colors;
}
}
+
public class PaletteView : View
{
private List _palette;
@@ -231,20 +231,20 @@ public class Images : Scenario
private (int columns, int rows) CalculateGridSize (Rectangle bounds)
{
// Characters are twice as wide as they are tall, so use 2:1 width-to-height ratio
- int availableWidth = bounds.Width / 2; // Each color block is 2 character wide
+ int availableWidth = bounds.Width / 2; // Each color block is 2 character wide
int availableHeight = bounds.Height;
int numColors = _palette.Count;
// Calculate the number of columns and rows we can fit within the bounds
int columns = Math.Min (availableWidth, numColors);
- int rows = (numColors + columns - 1) / columns; // Ceiling division for rows
+ int rows = (numColors + columns - 1) / columns; // Ceiling division for rows
// Ensure we do not exceed the available height
if (rows > availableHeight)
{
rows = availableHeight;
- columns = (numColors + rows - 1) / rows; // Recalculate columns if needed
+ columns = (numColors + rows - 1) / rows; // Recalculate columns if needed
}
return (columns, rows);
@@ -255,13 +255,15 @@ public class Images : Scenario
base.OnDrawContent (bounds);
if (_palette == null || _palette.Count == 0)
+ {
return;
+ }
// Calculate the grid size based on the bounds
- var (columns, rows) = CalculateGridSize (bounds);
+ (int columns, int rows) = CalculateGridSize (bounds);
// Draw the colors in the palette
- for (int i = 0; i < _palette.Count && i < columns * rows; i++)
+ for (var i = 0; i < _palette.Count && i < columns * rows; i++)
{
int row = i / columns;
int col = i % columns;
@@ -271,10 +273,10 @@ public class Images : Scenario
int y = row;
// Set the color attribute for the block
- Driver.SetAttribute (new Terminal.Gui.Attribute (_palette [i], _palette [i]));
+ Driver.SetAttribute (new (_palette [i], _palette [i]));
// Draw the block (2 characters wide per block)
- for (int dx = 0; dx < 2; dx++) // Fill the width of the block
+ for (var dx = 0; dx < 2; dx++) // Fill the width of the block
{
AddRune (x + dx, y, (Rune)' ');
}
@@ -289,3 +291,69 @@ public class Images : Scenario
}
}
}
+
+public abstract class LabColorDistance : IColorDistance
+{
+ // Reference white point for D65 illuminant (can be moved to constants)
+ private const double RefX = 95.047;
+ private const double RefY = 100.000;
+ private const double RefZ = 108.883;
+
+ // Conversion from RGB to Lab
+ protected LabColor RgbToLab (Color c)
+ {
+ XYZ xyz = ColorConverter.RgbToXyz (new (c.R, c.G, c.B));
+
+ // Normalize XYZ values by reference white point
+ double x = xyz.X / RefX;
+ double y = xyz.Y / RefY;
+ double z = xyz.Z / RefZ;
+
+ // Apply the nonlinear transformation for Lab
+ x = x > 0.008856 ? Math.Pow (x, 1.0 / 3.0) : 7.787 * x + 16.0 / 116.0;
+ y = y > 0.008856 ? Math.Pow (y, 1.0 / 3.0) : 7.787 * y + 16.0 / 116.0;
+ z = z > 0.008856 ? Math.Pow (z, 1.0 / 3.0) : 7.787 * z + 16.0 / 116.0;
+
+ // Calculate Lab values
+ double l = 116.0 * y - 16.0;
+ double a = 500.0 * (x - y);
+ double b = 200.0 * (y - z);
+
+ return new (l, a, b);
+ }
+
+ // LabColor class encapsulating L, A, and B values
+ protected class LabColor
+ {
+ public double L { get; }
+ public double A { get; }
+ public double B { get; }
+
+ public LabColor (double l, double a, double b)
+ {
+ L = l;
+ A = a;
+ B = b;
+ }
+ }
+
+ ///
+ public abstract double CalculateDistance (Color c1, Color c2);
+}
+
+///
+/// This is the simplest method to measure color difference in the CIE Lab color space. The Euclidean distance in Lab
+/// space is more aligned with human perception than RGB space, as Lab attempts to model how humans perceive color
+/// differences.
+///
+public class CIE76ColorDistance : LabColorDistance
+{
+ public override double CalculateDistance (Color c1, Color c2)
+ {
+ LabColor lab1 = RgbToLab (c1);
+ LabColor lab2 = RgbToLab (c2);
+
+ // Euclidean distance in Lab color space
+ return Math.Sqrt (Math.Pow (lab1.L - lab2.L, 2) + Math.Pow (lab1.A - lab2.A, 2) + Math.Pow (lab1.B - lab2.B, 2));
+ }
+}