添加项目文件。
This commit is contained in:
121
Wpf.Ui.Extend/Extensions/HsbExtensions.cs
Normal file
121
Wpf.Ui.Extend/Extensions/HsbExtensions.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Media;
|
||||
|
||||
using Wpf.Ui.Extend.Models;
|
||||
|
||||
namespace Wpf.Ui.Extend.Extensions
|
||||
{
|
||||
public static class HsbExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 将 HSB(色相、饱和度、亮度)颜色空间转换为 Color 对象。
|
||||
/// </summary>
|
||||
/// <param name="hsb"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException"></exception>
|
||||
public static Color ToColor(this 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 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);
|
||||
}
|
||||
|
||||
private static bool IsCloseTo(this double value, double target, double tolerance = double.Epsilon) =>
|
||||
Math.Abs(value - target) < tolerance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user