Files
Shrlalgo.RvKits/WPFluent/Extensions/HsbExtensions.cs
2025-04-24 20:56:44 +08:00

124 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Linq;
using WPFluent.Controls;
namespace WPFluent.Extensions
{
public static class HsbExtensions
{
private static bool IsCloseTo(this double value, double target, double tolerance = double.Epsilon) => Math.Abs(
value - target) <
tolerance;
/// <summary>
/// 将 HSB色相、饱和度、亮度颜色空间转换为 Color 对象。
/// </summary>
/// <param name="hsb"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public static Color ToColor(this Controls.Hsb hsb)
{
//0~1
var hue = hsb.Hue;
var saturation = hsb.Saturation;
var brightness = hsb.Brightness;
var opacity = hsb.Opacity;
brightness *= 255;
//饱和度为0直接返回亮度值
if (saturation.IsCloseTo(0))
return Color.FromArgb((byte)brightness, (byte)brightness, (byte)brightness, (byte)brightness);
opacity *= 255;
//处理色相超出范围
if (hue.IsCloseTo(360))
hue = 0;
while (hue > 360)
hue -= 360;
while (hue < 0)
hue += 360;
//通过色相返回颜色
hue /= 60;
//以60作为一个区间通过switch判断
var i = (int)Math.Floor(hue);
//计算出色相值在当前区间内的偏移量
var f = hue - i;
//计算出低饱和度情况下的亮度值
var p = brightness * (1 - saturation);
//计算出中间饱和度情况下的亮度值
var q = brightness * (1 - saturation * f);
//计算出高饱和度情况下的亮度值
var t = brightness * (1 - saturation * (1 - f));
return i switch
{
//[0~60)红色区间
0 => Color.FromArgb((byte)opacity, (byte)brightness, (byte)t, (byte)p),
//[60~120)黄色区间
1 => Color.FromArgb((byte)opacity, (byte)q, (byte)brightness, (byte)p),
//[120~180)绿色区间
2 => Color.FromArgb((byte)opacity, (byte)p, (byte)brightness, (byte)t),
//[180~240)青色区间
3 => Color.FromArgb((byte)opacity, (byte)p, (byte)q, (byte)brightness),
//[240~300)蓝色区间
4 => Color.FromArgb((byte)opacity, (byte)t, (byte)p, (byte)brightness),
//[300~360)洋红色区间
5 => Color.FromArgb((byte)opacity, (byte)brightness, (byte)p, (byte)q),
_ => throw new InvalidOperationException("不可用的HSB值"),
};
}
/// <summary>
/// 将 Color 对象转换为 HSB色相、饱和度、亮度颜色空间。
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
public static Controls.Hsb ToHsb(this Color color)
{
double r = color.R;
double g = color.G;
double b = color.B;
double a = color.A;
r /= 255;
g /= 255;
b /= 255;
a /= 255;
var rgb = new[] { r, g, b };
var max = rgb.Max();
var min = rgb.Min();
var brightness = max;
var hue = max;
var delta = max - min;
var saturation = max.IsCloseTo(0) ? 0 : delta / max;
if (max.IsCloseTo(min))
{
hue = 0; // 无色,未定义
}
else
{
if (max.IsCloseTo(r))
{
hue = (g - b) / delta + (g < b ? 6 : 0);
}
else if (max.IsCloseTo(g))
{
hue = (b - r) / delta + 2;
}
else if (max.IsCloseTo(b))
{
hue = (r - g) / delta + 4;
}
hue *= 60;
}
return new Hsb(hue, saturation, brightness, a);
}
}
}