lista - Creando un color C#a partir de valores HSL
rgba color c# (2)
¿Cómo puedo crear un color C # a partir de valores HSL?
Agregue la siguiente línea a los espacios de nombres "utilizando" en su archivo de código:
using System.Runtime.InteropServices
y con P / Invoke, agregue la siguiente función:
[DllImport("shlwapi.dll")]
public static extern int ColorHLSToRGB(int H, int L, int S);
En cualquier clase que quieras en tu proyecto.
Si tiene el color en tono, luminancia y saturación como números enteros, entonces asigne estos valores a esa función, y el color RGB deseado se devolverá como entero. Luego use ColorTranslator.FromWin32 para traducir el color rgb devuelto como entero a la estructura System.Drawing.Color.
Otra forma es usar el método de sobrecarga Color.FromArgb (Int32), para crear el color que desee como estructura System.Drawing.Color a partir de ese entero.
Otra forma es crear una instancia de la clase ColorConverter , y luego llamar al método ConvertFrom , y darle el entero de color RGB devuelto por la función ColorHLSToRGB, o llamar al método ConvertTo con el mismo primer argumento, pero en el segundo argumento input typeof(System.Drawing.Color)
. Luego convierta el objeto devuelto al tipo de estructura System.Drawing.Color.
¡El resultado es exactamente lo que estás buscando y esperado!
También puede probar otros algoritmos o formas en que puede buscar, descubrir y aprender en Internet, sobre cómo convertir el color RGB como entero a la estructura System.Drawing.Color O cómo convertir los valores HLS como tres enteros al System.Drawing. Estructura de color!
Tengo una clase que realiza transformaciones RGB, HSB y HSL. NO soy un experto en color, y tampoco reclamo que esta clase tenga los algoritmos más rápidos (usa string. Convierta en lugares para asegurar que las conversiones de punto flotante salgan como se espera, lo que ahora podría ser revisado con algunos nuevos cambios de conversión de punto flotante BCL ...)
Sin embargo, esta clase ha sido probada y ha estado trabajando por un tiempo, y parece hacer el trabajo correctamente. Lo uso para crear pinceles de Wpf congelados, que no se ejecutan en bucles ajustados repetidamente (o en alguna ruta de representación de rendimiento crítico); y los resultados parecen ser los esperados.
Si tiene inquietudes críticas, debe examinar el código ... Aquí está:
using System;
using System.Drawing;
using SystemMath = System.Math;
namespace Sc.Util.Rendering
{
/// <summary>
/// Static methods for transforming argb spaces and argb values.
/// </summary>
public static class SimpleColorTransforms
{
private static double tolerance
=> 0.000000000000001;
/// <summary>
/// Defines brightness levels.
/// </summary>
public enum Brightness
: byte
{
Bright = 255,
MediumBright = 210,
Medium = 142,
Dim = 98,
XDim = 50
}
/// <summary>
/// Defines alpha levels.
/// </summary>
public enum Alpha
: byte
{
Opaque = 255,
MediumHigh = 230,
Medium = 175,
MediumLow = 142,
Low = 109,
XLow = 45
}
/// <summary>
/// Defines hint alpha levels.
/// </summary>
public enum HintAlpha
: byte
{
Low = 64,
XLow = 48,
XxLow = 32,
XxxLow = 16
}
/// <summary>
/// Specifies a mode for argb transformations.
/// </summary>
public enum ColorTransformMode
: byte
{
Hsl,
Hsb
}
/// <summary>
/// Converts RGB to HSL. Alpha is ignored.
/// Output is: { H: [0, 360], S: [0, 1], L: [0, 1] }.
/// </summary>
/// <param name="color">The color to convert.</param>
public static double[] RgBtoHsl(Color color)
{
double h = 0D;
double s = 0D;
double l;
// normalize red, green, blue values
double r = color.R / 255D;
double g = color.G / 255D;
double b = color.B / 255D;
double max = SystemMath.Max(r, SystemMath.Max(g, b));
double min = SystemMath.Min(r, SystemMath.Min(g, b));
// hue
if (SystemMath.Abs(max - min) < SimpleColorTransforms.tolerance)
h = 0D; // undefined
else if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
&& (g >= b))
h = (60D * (g - b)) / (max - min);
else if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
&& (g < b))
h = ((60D * (g - b)) / (max - min)) + 360D;
else if (SystemMath.Abs(max - g) < SimpleColorTransforms.tolerance)
h = ((60D * (b - r)) / (max - min)) + 120D;
else if (SystemMath.Abs(max - b) < SimpleColorTransforms.tolerance)
h = ((60D * (r - g)) / (max - min)) + 240D;
// luminance
l = (max + min) / 2D;
// saturation
if ((SystemMath.Abs(l) < SimpleColorTransforms.tolerance)
|| (SystemMath.Abs(max - min) < SimpleColorTransforms.tolerance))
s = 0D;
else if ((0D < l)
&& (l <= .5D))
s = (max - min) / (max + min);
else if (l > .5D)
s = (max - min) / (2D - (max + min)); //(max-min > 0)?
return new[]
{
SystemMath.Max(0D, SystemMath.Min(360D, double.Parse($"{h:0.##}"))),
SystemMath.Max(0D, SystemMath.Min(1D, double.Parse($"{s:0.##}"))),
SystemMath.Max(0D, SystemMath.Min(1D, double.Parse($"{l:0.##}")))
};
}
/// <summary>
/// Converts HSL to RGB, with a specified output Alpha.
/// Arguments are limited to the defined range:
/// does not raise exceptions.
/// </summary>
/// <param name="h">Hue, must be in [0, 360].</param>
/// <param name="s">Saturation, must be in [0, 1].</param>
/// <param name="l">Luminance, must be in [0, 1].</param>
/// <param name="a">Output Alpha, must be in [0, 255].</param>
public static Color HsLtoRgb(double h, double s, double l, int a = 255)
{
h = SystemMath.Max(0D, SystemMath.Min(360D, h));
s = SystemMath.Max(0D, SystemMath.Min(1D, s));
l = SystemMath.Max(0D, SystemMath.Min(1D, l));
a = SystemMath.Max(0, SystemMath.Min(255, a));
// achromatic argb (gray scale)
if (SystemMath.Abs(s) < SimpleColorTransforms.tolerance) {
return Color.FromArgb(
a,
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{l * 255D:0.00}")))),
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{l * 255D:0.00}")))),
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{l * 255D:0.00}")))));
}
double q = l < .5D
? l * (1D + s)
: (l + s) - (l * s);
double p = (2D * l) - q;
double hk = h / 360D;
double[] T = new double[3];
T[0] = hk + (1D / 3D); // Tr
T[1] = hk; // Tb
T[2] = hk - (1D / 3D); // Tg
for (int i = 0; i < 3; i++) {
if (T[i] < 0D)
T[i] += 1D;
if (T[i] > 1D)
T[i] -= 1D;
if ((T[i] * 6D) < 1D)
T[i] = p + ((q - p) * 6D * T[i]);
else if ((T[i] * 2D) < 1)
T[i] = q;
else if ((T[i] * 3D) < 2)
T[i] = p + ((q - p) * ((2D / 3D) - T[i]) * 6D);
else
T[i] = p;
}
return Color.FromArgb(
a,
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{T[0] * 255D:0.00}")))),
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{T[1] * 255D:0.00}")))),
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{T[2] * 255D:0.00}")))));
}
/// <summary>
/// Converts RGB to HSB. Alpha is ignored.
/// Output is: { H: [0, 360], S: [0, 1], B: [0, 1] }.
/// </summary>
/// <param name="color">The color to convert.</param>
public static double[] RgBtoHsb(Color color)
{
// normalize red, green and blue values
double r = color.R / 255D;
double g = color.G / 255D;
double b = color.B / 255D;
// conversion start
double max = SystemMath.Max(r, SystemMath.Max(g, b));
double min = SystemMath.Min(r, SystemMath.Min(g, b));
double h = 0D;
if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
&& (g >= b))
h = (60D * (g - b)) / (max - min);
else if ((SystemMath.Abs(max - r) < SimpleColorTransforms.tolerance)
&& (g < b))
h = ((60D * (g - b)) / (max - min)) + 360D;
else if (SystemMath.Abs(max - g) < SimpleColorTransforms.tolerance)
h = ((60D * (b - r)) / (max - min)) + 120D;
else if (SystemMath.Abs(max - b) < SimpleColorTransforms.tolerance)
h = ((60D * (r - g)) / (max - min)) + 240D;
double s = SystemMath.Abs(max) < SimpleColorTransforms.tolerance
? 0D
: 1D - (min / max);
return new[]
{
SystemMath.Max(0D, SystemMath.Min(360D, h)),
SystemMath.Max(0D, SystemMath.Min(1D, s)),
SystemMath.Max(0D, SystemMath.Min(1D, max))
};
}
/// <summary>
/// Converts HSB to RGB, with a specified output Alpha.
/// Arguments are limited to the defined range:
/// does not raise exceptions.
/// </summary>
/// <param name="h">Hue, must be in [0, 360].</param>
/// <param name="s">Saturation, must be in [0, 1].</param>
/// <param name="b">Brightness, must be in [0, 1].</param>
/// <param name="a">Output Alpha, must be in [0, 255].</param>
public static Color HsBtoRgb(double h, double s, double b, int a = 255)
{
h = SystemMath.Max(0D, SystemMath.Min(360D, h));
s = SystemMath.Max(0D, SystemMath.Min(1D, s));
b = SystemMath.Max(0D, SystemMath.Min(1D, b));
a = SystemMath.Max(0, SystemMath.Min(255, a));
double r = 0D;
double g = 0D;
double bl = 0D;
if (SystemMath.Abs(s) < SimpleColorTransforms.tolerance)
r = g = bl = b;
else {
// the argb wheel consists of 6 sectors. Figure out which sector
// you''re in.
double sectorPos = h / 60D;
int sectorNumber = (int)SystemMath.Floor(sectorPos);
// get the fractional part of the sector
double fractionalSector = sectorPos - sectorNumber;
// calculate values for the three axes of the argb.
double p = b * (1D - s);
double q = b * (1D - (s * fractionalSector));
double t = b * (1D - (s * (1D - fractionalSector)));
// assign the fractional colors to r, g, and b based on the sector
// the angle is in.
switch (sectorNumber) {
case 0 :
r = b;
g = t;
bl = p;
break;
case 1 :
r = q;
g = b;
bl = p;
break;
case 2 :
r = p;
g = b;
bl = t;
break;
case 3 :
r = p;
g = q;
bl = b;
break;
case 4 :
r = t;
g = p;
bl = b;
break;
case 5 :
r = b;
g = p;
bl = q;
break;
}
}
return Color.FromArgb(
a,
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{r * 255D:0.00}")))),
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{g * 255D:0.00}")))),
SystemMath.Max(0, SystemMath.Min(255, Convert.ToInt32(double.Parse($"{bl * 250D:0.00}")))));
}
/// <summary>
/// Multiplies the Color''s Luminance or Brightness by the argument;
/// and optionally specifies the output Alpha.
/// </summary>
/// <param name="color">The color to transform.</param>
/// <param name="colorTransformMode">Transform mode.</param>
/// <param name="brightnessTransform">The transformation multiplier.</param>
/// <param name="outputAlpha">Can optionally specify the Alpha to directly
/// set on the output. If null, then the input <paramref name="color"/>
/// Alpha is used.</param>
public static Color TransformBrightness(
Color color,
ColorTransformMode colorTransformMode,
double brightnessTransform,
byte? outputAlpha = null)
{
double[] hsl = colorTransformMode == ColorTransformMode.Hsl
? SimpleColorTransforms.RgBtoHsl(color)
: SimpleColorTransforms.RgBtoHsb(color);
if ((SystemMath.Abs(hsl[2]) < SimpleColorTransforms.tolerance)
&& (brightnessTransform > 1D))
hsl[2] = brightnessTransform - 1D;
else
hsl[2] *= brightnessTransform;
return colorTransformMode == ColorTransformMode.Hsl
? SimpleColorTransforms.HsLtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A)
: SimpleColorTransforms.HsBtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A);
}
/// <summary>
/// Multiplies the Color''s Saturation, and Luminance or Brightness by the argument;
/// and optionally specifies the output Alpha.
/// </summary>
/// <param name="color">The color to transform.</param>
/// <param name="colorTransformMode">Transform mode.</param>
/// <param name="saturationTransform">The transformation multiplier.</param>
/// <param name="brightnessTransform">The transformation multiplier.</param>
/// <param name="outputAlpha">Can optionally specify the Alpha to directly
/// set on the output. If null, then the input <paramref name="color"/>
/// Alpha is used.</param>
public static Color TransformSaturationAndBrightness(
Color color,
ColorTransformMode colorTransformMode,
double saturationTransform,
double brightnessTransform,
byte? outputAlpha = null)
{
double[] hsl = colorTransformMode == ColorTransformMode.Hsl
? SimpleColorTransforms.RgBtoHsl(color)
: SimpleColorTransforms.RgBtoHsb(color);
if ((SystemMath.Abs(hsl[1]) < SimpleColorTransforms.tolerance)
&& (saturationTransform > 1D))
hsl[1] = saturationTransform - 1D;
else
hsl[1] *= saturationTransform;
if ((SystemMath.Abs(hsl[2]) < SimpleColorTransforms.tolerance)
&& (brightnessTransform > 1D))
hsl[2] = brightnessTransform - 1D;
else
hsl[2] *= brightnessTransform;
return colorTransformMode == ColorTransformMode.Hsl
? SimpleColorTransforms.HsLtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A)
: SimpleColorTransforms.HsBtoRgb(hsl[0], hsl[1], hsl[2], outputAlpha ?? color.A);
}
/// <summary>
/// Creates a new Color by combining R, G, and B from each Color, scaled by the Color''s Alpha.
/// The R, G, B of each Color is scaled by the Color''s Alpha. The R, G, B of both results is
/// then added together and divided by 2. The valuea are limited to [0, 255].
/// The Alpha of the output Color is specified; and is also limited to [0, 255]
/// (does not raise exceptions).
/// </summary>
/// <param name="color1">Combined by scaling RGB by the A.</param>
/// <param name="color2">Combined by scaling RGB by the A.</param>
/// <param name="outputAlpha">The Alpha of the output Color.</param>
public static Color AlphaCombine(Color color1, Color color2, byte outputAlpha)
{
double a1 = color1.A / 255D;
double a2 = color2.A / 255D;
return Color.FromArgb(
outputAlpha,
(byte)SystemMath.Max(0D, SystemMath.Min(255D, ((color1.R * a1) + (color2.R * a2)) * .5D)),
(byte)SystemMath.Max(0D, SystemMath.Min(255D, ((color1.G * a1) + (color2.G * a2)) * .5D)),
(byte)SystemMath.Max(0D, SystemMath.Min(255D, ((color1.B * a1) + (color2.B * a2)) * .5D)));
}
}
}