我正在尝试编写一个方法,该方法将在WPF的Color
结构上起作用,以返回表示Color
的Hue的字节。我正在努力学习公式,我已经为黑色(255,255,255),红色(255,0,0),绿色(0,255,0),蓝色(0,0,255)的色调编写了单元测试),黄色(255,255,0),青色(0,255,255),洋红色(255,0,255)和白色(255,255,255) - 它们都通过除了黄色(它返回1而不是42) )和Magenta(试图返回-1而不是212但是失败,因为-1赢得了一个字节)。
GetHue
的扩展方法如下所示:
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
上的另外两种扩展方法,它们返回ColorComponent
的第一个最低Color
个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);
}
的常量。
我将此公式基于我在此处找到的另一个公式(http://www.blackwasp.co.uk/rgbhsl_2.aspx),如下所示:
function find(Image): Collection of Rects
core_rect = FindRects(Image)
split(core_rect) -> 4 rectangles (left-top, left-bottom, right-top, right-bottom)
return Merge of (find(leftTop), find(leftBottom), ...)
function findAll(Image): Collection of Rects
rects <- find(Image)
sort rectangles by X, Y
merge rectangles
sort rectangles by Y, X
merge rectangles
return merged set
该公式的问题是它被映射到0 - 360色调范围,而不是0 - 255范围,这是我需要的。我不确定这个公式中的常数是什么,但我猜测60与360/3 = 120有关,因此我的第三个字节常量试图做类似的事情。至于6M,我不知道它们来自何处,也不知道为什么它们会被添加到那个阶段的色调值并与之模拟。任何有数学思想的人都可以帮助我吗?
更新 0到255范围的原因是我认为只要看到它在另一个软件(如图所示)中用于色调,饱和度和亮度就需要了。这也是我获得黄色的42 Hue值的地方。我现在正在尝试找到Hues的正确范围,以覆盖16777216(256 * 256 * 256)颜色范围内所有可能的不同色调。
答案 0 :(得分:0)
你的“......除了黄色(返回1而不是42)”期待42的背后的逻辑是什么?
“映射到0 - 360色调范围”,因为色轮中有360种色调。即使你有一个无符号字节(保持256个值),你也会裁掉其他104种可能的色调。它不是一个准确的表示。
为什么不使用2字节short来保存可能的360色调而不是使用1个字节?
如果你仍然希望在255范围内适应360,那就做一个简单的数学运算:
byte_value = hue_value / (360/255); //where hue_value is the 0-360 amount.
尝试让Math methods与Math.round
相关,不得将任何分数作为最终字节值。
示例180色调:
byte_value = Math.round( 180 / (360/255) ); //gives 127