2017-10-18 230 views
0

我想写一个方法,它将在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是一种方法,如果溢出或下溢,则会将枚举包装回声明的范围。 GetMinComponentGetMaxComponentColor上的两个其他扩展方法,它们返回Color(其中ColorComponent的顺序是:红色,绿色,蓝色)的第一个最低和第一个最高的ColorComponentthirdOfByte是一个常数,等于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)色彩范围内的所有可能的不同色调。

enter image description here

回答

0
  • “......除了黄色(返回1,而不是42)”有什么背后的逻辑期待一个42?

  • 这是“映射到0-360色调范围”,因为色轮中有360个色调。即使你有一个无符号字节(保存256个值),你也会裁剪掉其他104种可能的色调。这不会是一个准确的表示。

  • 为什么不仅仅使用2个字节的short来保存可能的360度色调而不是使用1个字节?

如果您仍想以适应360一255范围之内,只是做简单的数学:

byte_value = hue_value/(360/255); //where hue_value is the 0-360 amount. 

审判涉及Math methodsMath.round获得无分数为最后一个字节的值。

例180色相:

byte_value = Math.round(180/(360/255)); //gives 127 
+0

我使用的是0反思 - 255现在你已经说;为了节省1个字节,我不希望失去价值解决方案!这意味着我现在可以复制公式,但我仍然想要了解它(60M,两个6M,4M和2M的意义是什么)。由于随后的乘法(在可以应用舍入之后),我假设模数作为小数是重要的。 – Sphynx

+0

为了澄清一下,360是255 * 255 * 255色彩的可能色调的总数,或者是将这些色调映射为每度1色度的圆的方法?我精确地将色相耦合到特定用户控件的形状之后。 – Sphynx