2009-04-26 70 views
2

我试图基于其中每种颜色已经被分配有值的调色板来画一个WPF控制的背景(例如,红色= 0,深绿色= 10,绿色= 20,浅绿= 30)和用户选择的值(例如25),这会产生最终的颜色。我希望得到的颜色是2个最接近的颜色值之间的插值(例如,对于值25,它应该在绿色和LightGreen之间给出颜色)WPF色彩插值

为此,我正在考虑在WPF中使用现有的LinearGradientBrush ;设置GradientStops,偏移并获得指定值的颜色。有没有办法做到这一点,或者我应该实现自己的颜色插值功能?

谢谢。

回答

1

你在哪里为你的DarkGreen/Green/Lightgreen颜色提供了价值10/20/30。

您需要在您指定的调色板值&之间的颜色的实际数值表示之间的某种关联表。

Color    Pal-Code  RGB   HSL 
Red    0   255,0,0  0,240,120 
Dark Green  10   0,128,0  80,240,60 
Green    20   0,255,0  80,240,120 
Light Green  30   128,255,128 80,240,180 

从该关联表,你可以采取任何用户“调色板代码”,找到从上面的表中的封闭匹配对调色板代码,做一个最好的匹配范围,找到它。例如如果一些进入25(我们使用的方便HSL),那么公式将是...

Green    20   0,255,0  80,240,120 
Light Green  30   128,255,128 80,240,180 

25是中间两个代码之间,

Palette Code  Hue  Sat  Luminence 
20    80   240  120 
30    80   240  180 
------------------------------------------------- 
25    80   240  150 

如果他们选择6,你需要在每个值之间找到.6的颜色范围。

Red    0   255,0,0  0,240,120 
Dark Green  10   0,128,0  80,240,60 

Palette Code  Hue  Sat  Luminence 
0    0   240  120 
10    80   240  60 
------------------------------------------------- 
6    48   240  84 

0->80  = +80 * 60% = +48 So 0+48 = 48 
240->240 = 0 * 60% = 0  So 240+0 = 240 
120->60 = -60 * 60% = -36 So 120-36 = 84 
5

使用LinearGradientBrush听起来好像会有一点开销。虽然没有知识。颜色插值函数虽然不难编写。

我假设你的调色板的值可以被10整除以简化。

public static Color GetColor(int value) 
{ 
    int startIndex = (value/10)*10; 
    int endIndex = startIndex + 10; 

    Color startColor = Palette[startIndex]; 
    Color endColor = Palette[endIndex]; 

    float weight = (value - startIndex)/(float)(endIndex - startIndex); 

    return Color.FromArgb(
     (int)Math.Round(startColor.R * (1 - weight) + endColor.R * weight), 
     (int)Math.Round(startColor.G * (1 - weight) + endColor.G * weight), 
     (int)Math.Round(startColor.B * (1 - weight) + endColor.B * weight)); 

} 

如果定义的颜色不通过10逻辑整除找到的开始和结束的颜色会更复杂一点。

+0

备案:要么添加255 Color.FromArgb的第一个参数,或使用Color.FromRgb。 Thx的帖子。 – GameAlchemist 2013-09-01 16:32:45

1

我想你会使用值转换器的更好,只是采取的其他答案建议插值功能之一,并把在值转换器,使用此转换器的背景属性绑定到的价值和你'重做。

1

感谢所有的回复家伙。似乎没有办法在指定的点上获得GradientBrush的“价值”。我希望这可以在框架的某个更新版本中得到纠正。所以我想现在唯一的选择就是实现插值算法米克建议。

1

我不知道,如果是这种情况退缩,但在.NET 4.0中得到从一个LinearGradientBrush颜色可以做到的。

private Color GetColor(double ratio) 
{ 
    if (ratio < 0) ratio = 0; 
    else if (ratio > 1) ratio = 1; 

    //Find gradient stops that surround the input value 
    GradientStop gs0 = ColorScale.GradientStops.Where(n => n.Offset <= ratio).OrderBy(n => n.Offset).Last(); 
    GradientStop gs1 = ColorScale.GradientStops.Where(n => n.Offset >= ratio).OrderBy(n => n.Offset).First(); 

    float y = 0f; 
    if (gs0.Offset != gs1.Offset) 
    { 
     y = (float)((ratio - gs0.Offset)/(gs1.Offset - gs0.Offset)); 
    } 

    //Interpolate color channels 
    Color cx = new Color(); 
    if (ColorScale.ColorInterpolationMode == ColorInterpolationMode.ScRgbLinearInterpolation) 
    { 
     float aVal = (gs1.Color.ScA - gs0.Color.ScA) * y + gs0.Color.ScA; 
     float rVal = (gs1.Color.ScR - gs0.Color.ScR) * y + gs0.Color.ScR; 
     float gVal = (gs1.Color.ScG - gs0.Color.ScG) * y + gs0.Color.ScG; 
     float bVal = (gs1.Color.ScB - gs0.Color.ScB) * y + gs0.Color.ScB; 
     cx = Color.FromScRgb(aVal, rVal, gVal, bVal); 
    } 
    else 
    { 
     byte aVal = (byte)((gs1.Color.A - gs0.Color.A) * y + gs0.Color.A); 
     byte rVal = (byte)((gs1.Color.R - gs0.Color.R) * y + gs0.Color.R); 
     byte gVal = (byte)((gs1.Color.G - gs0.Color.G) * y + gs0.Color.G); 
     byte bVal = (byte)((gs1.Color.B - gs0.Color.B) * y + gs0.Color.B); 
     cx = Color.FromArgb(aVal, rVal, gVal, bVal); 
    } 
    return cx; 
} 

这将与被配置为工作刷如下(例如):

var brush = new LinearGradientBrush(); 
brush.StartPoint = new Point(0, 0); 
brush.EndPoint = new Point(1, 0); 

//Set brush colors 
brush.GradientStops.Add(new GradientStop() { Color = Color.FromRgb(102, 40, 0), Offset = 0 }); 
brush.GradientStops.Add(new GradientStop() { Color = Color.FromRgb(254, 167, 80), Offset = 0.25 }); 
brush.GradientStops.Add(new GradientStop() { Color = Color.FromRgb(0, 153, 51), Offset = 0.5 }); 
brush.GradientStops.Add(new GradientStop() { Color = Color.FromRgb(232, 165, 255), Offset = 0.75 }); 
brush.GradientStops.Add(new GradientStop() { Color = Color.FromRgb(66, 0, 89), Offset = 1 }); 

来源: http://dotupdate.wordpress.com/2008/01/28/find-the-color-of-a-point-in-a-lineargradientbrush/