2009-04-26 125 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/