我想写一个方法,它将在WPF的Color
结构上工作,以返回表示Color
的色调的字节。我正在努力与公式,我已经编写了黑色(255,255,255),红色(255,0,0),绿色(0,255,0),蓝色(0,0,255) ),黄色(255,255,0),青色(0,255,255),品红色(255,0255)和白色(255,255,255) - 它们都通过,除了黄色(返回1而不是42 )和洋红色(它试图返回-1而不是212,但失败,因为-1不会被转换成一个字节)。出现颜色的色调计算为0 - 255范围
为我的扩展方法如下:
public static byte GetHue(this Color color)
=> GetHue(color.ToRgbDictionary(), color.GetMinComponent(), color.GetMaxComponent());
private static byte GetHue(Dictionary<ColorComponent, byte> rgbDictionary, ColorComponent minimumRgbComponent, ColorComponent maximumRgbComponent)
{
decimal chroma = rgbDictionary[maximumRgbComponent] - rgbDictionary[minimumRgbComponent];
return (byte)
(
chroma == 0
? 0
: thirdOfByte
* (byte)maximumRgbComponent
+
(
rgbDictionary[MathHelper.Wrap(maximumRgbComponent + 1)]
- rgbDictionary[MathHelper.Wrap(maximumRgbComponent - 1)]
)
/chroma
);
}
ToRgbDictionary
只是将Color
到它的红,绿,蓝组成的字典; ColorComponent
是用作这些组件的关键的枚举。 MathHelper.Wrap
是一种方法,如果溢出或下溢,则会将枚举包装回声明的范围。 GetMinComponent
和GetMaxComponent
是Color
上的两个其他扩展方法,它们返回Color
(其中ColorComponent
的顺序是:红色,绿色,蓝色)的第一个最低和第一个最高的ColorComponent
。 thirdOfByte
是一个常数,等于byte.MaxValue/3
。
我已经基于这个公式在另一个我发现这里(),其看起来像这样:
private decimal GetH(RGB rgb, decimal max, decimal chroma)
{
decimal h;
if (rgb.R == max)
h = ((rgb.G - rgb.B)/chroma);
else if (rgb.G == max)
h = ((rgb.B - rgb.R)/chroma) + 2M;
else
h = ((rgb.R - rgb.G)/chroma) + 4M;
return 60M * ((h + 6M) % 6M);
}
与式的问题是它的映射到0 - 360色相范围内,而不是0 - 255这是我需要的范围。我不确定这个公式中的常数如何,但我猜测60与360/3 = 120有关,因此我的第三个字节常量试图做类似的事情。至于6Ms,我不知道它们来自哪里,也不知道为什么它们在这个阶段被添加到色调值中。任何一个有数学思想的人都可以帮我解决这个问题吗?
UPDATE 的原因0 - 255范围是,我认为这是认为需要在看到它在另一块的软件(如图所示),用于色调,饱和度和亮度中使用的所有。这也是我获得黄色42 Hue值的地方。我现在试图找到Hues的正确范围,以涵盖16777216(256 * 256 * 256)色彩范围内的所有可能的不同色调。
我使用的是0反思 - 255现在你已经说;为了节省1个字节,我不希望失去价值解决方案!这意味着我现在可以复制公式,但我仍然想要了解它(60M,两个6M,4M和2M的意义是什么)。由于随后的乘法(在可以应用舍入之后),我假设模数作为小数是重要的。 – Sphynx
为了澄清一下,360是255 * 255 * 255色彩的可能色调的总数,或者是将这些色调映射为每度1色度的圆的方法?我精确地将色相耦合到特定用户控件的形状之后。 – Sphynx