Generate a specific color for each string?
I have a DataGrid that shows orders that belong to product.
I want to have a generated SolidColorBrush that is unique to each product.
Update
I开发者_高级运维 need these colors to be solid and distinctive, or at least to be ordered in a distinctive way, i.e., there shouldn't be black, blue, green as these 3 colors can be confused with each other. Besides it should be black, red, blue etc.
The formula has to be:
- Group all the colors into subgroups of main colors
- Order them by darkness
- Order it again the ping-pong alternation way (dark-light dark-light etc.) with the pervious group.
- I just noticed there is a cool function:
Color.AreClose
, it might be useful, I still donno how to implement it. - I am sure you have more ideas.
Related: Is there a .NET list of 256 colors only?
Well you can create a function that will return color based on some sort of seed. Then just bind the item backcolor in xaml. The seed can be for example just an ordinary byte that will take R(of RGB) and add +10. The thing is that you need to give more info. Like akellehe asked whether the colors have to look nice, whether two items that are close to each other will need two really different colors or something similar will do (for example RGB (128,128,128) and (128,128,129) ). Also how many items can there be?
It may be helpful to consider colors in terms of Hue, Saturation and Value. Now you can consider different sampling functions in Hue and Value, for instance, to generate your colors. You might increment in Hue, for instance, then repeat at a different Value to get darker versions of the same colors. You could also offset your Hue at alternating Value locations to get additional variability in color. For best results, you probably want to alternate 'warm' and 'cool' colors (favor red vs. favor blue) during your sampling.
EDIT:
For a technical overview of Hue, see this article for conversions HSV <-> RGB. They're a bit awkward, as HSV is typically interpreted as a cone, with hue taken as the angle about the normal axis. It's constructed that way because once you reach V=0, Hue and Saturation are both undefined (basically, Black is Black; it has no hues; Gray colors (the vertical axis) also have no hue) For your purposes you can simply use the equations (see the sections "Hue and chroma" and "Converting to RGB").
Once you have the HSV conversions implemented, the simplest color sampling that varies purely in hue is to just take hue from 0 to 360/(N-1), where N is the number of samples. You can set Saturation and Value however you like; S=1 and V=1 will give you the brightest, most 'colorful' (saturated) colors. If you have too many points to simply sample in Hue, you can start combining this with changes in Value (for darker colors) or Saturation (for more desaturated, 'grayish' colors).
There's a crude color difference formula suggested in a Working Draft on the W3C site:
Color difference is determined by the following formula: (maximum (Red value 1, Red value 2) - minimum (Red value 1, Red value 2)) + (maximum (Green value 1, Green value 2) - minimum (Green value 1, Green value 2)) + (maximum (Blue value 1, Blue value 2) - minimum (Blue value 1, Blue value 2))
The ra[n]ge for color brightness difference is 125. The range for color difference is 500.
There are also other, more complex ones too that you might need for best results.
You might then use that function in an algorithm that would store all the possible colors in a set, choose one color from that set (say black), and use that as a starting point for an iterative sort.
This is neither optimized nor tested, but it might work:
static List<Color> SortColors(IEnumerable<Color> colors)
{
var hashed = new HashSet<Color>(colors);
var sorted = new List<Color>(hashed.Count);
//Start with black
var last = hashed.Single(x => x.Red == 0 && x.Green == 0 && x.Blue == 0);
hashed.Remove(last);
sorted.Add(last);
while (hashed.Any())
{
//This could of course be optimized by doing these two steps in a single loop
var bestDiff = hashed
.Max(x => Difference(x, last));
var best = hashed.First(x => Difference(x, last) == bestDiff);
hashed.Remove(best);
sorted.Add(best);
last = best;
}
return sorted;
}
static int Difference(Color a, Color b)
{
return Math.Abs(a.Red - b.Red)
+ Math.Abs(a.Green - b.Green)
+ Math.Abs(a.Blue - b.Blue);
}
Worked best for me:
Private Shared ReadOnly rndm As New Random
Public Shared ReadOnly m_ColorsList As IEnumerable(Of Color) =
Enumerable.Range(0, 100).Select(
Function(i) Color.FromRgb(rndm.Next(256), rndm.Next(256), rndm.Next(256)))
Replace the number 100 with the desired amount of colors.
精彩评论