views:

86

answers:

4

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.

So basically the formula has to be:

  1. Group all the colors into subgroups of main colors
  2. Order them by darkness
  3. Order it again the ping-pong alternation way (dark-light dark-light etc.) with the pervious group.
  4. I just noticed there is a cool function: Color.AreClose, it might be useful, I still donno how to implement it.
  5. I am sure you have more ideas.

Related: Is there a .NET list of 256 colors only?

A: 

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?

nomail
There should be 0-50 items, I need the colors to be distinctive; something like IE8's tab group coloring.
Shimmy
Take a look here. Guy uses system colors, which maybe will suit you.http://www.codeproject.com/KB/custom-controls/csMultiColorDropDownList.aspx
nomail
A: 

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.

Shimmy
+2  A: 

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).

Dan Bryant
+1. I've done similar things in other language and HSB was the way to go. The Hue is a 360 degree color wheel which is easy to divide by the exact number of colors you need for the given data -- creating 50 colors in advance and picking 7 is way harder then just dividing the available color space into 7.
David Blevins
Sounds a great idea.I never dealt with hue tho, can you please add an example of to create a randomized color-list based on hue divided by count: `Color GetColors(int count)`?
Shimmy
+1  A: 

There's a crude color difference formula suggested by W3C:

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 rage 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);
}
Rei Miyasaka
+1, looks pretty good, but what am I supposed to supply for the colors arg? I just want to supply an int specifying how many colors to return. Also I want the start color to be randomized.
Shimmy
Probably a parsed palette -- maybe you can use reflection to get a list of all the properties in System.Windows.Media.Colors.To randomize it, you'd just use Random to select a first value for last at a random index: `var last = hashed.ElementAt(new Random().Next(hashed.Count - 1));`
Rei Miyasaka
You might use this for the argument: `var colors = typeof(Colors).GetProperties().Select(p => (Color)p.GetValue(null, null));`
Rei Miyasaka
But I don't get why I have to supply a value rather than using a count int argument instead, and iterate on it, creating the new color on each iteration?
Shimmy
There's probably an algorithmic way to find the furthest perceived color from another given the entire 24 bit spectrum and then find the midpoint and then the furthest again etc, but I'd imagine that it's pretty complex. I certainly don't know the math for it. I thought that that was why you were looking for a 256 color palette in your other thread; sorry I misunderstood.Either way, the human eye can easily tell several hundred colors apart if they're all lined up in a clunky gradient, but most people won't remember about one color in a palette of several hundred being repeated elsewhere.
Rei Miyasaka