tags:

views:

47

answers:

3

I need to randomly generate colors for multiple items in a to do list.

(like pick up the kids from school, pick up the dry cleaning and so on)

What's the best way of doing this in ruby and also avoid colors that would be hard to see (like grey, white, and so on)?

A: 

To generate a random color in RGB form, you just need to generate each of three components randomly (like rand(256) three times).

If you don't want color to be too bright, there're many ways to ensure that. For example, allow every component to be only in half of its normal range (rand(128)). Since bigger number designates brighter color, you won't get white, beige or any other "hard to see" color.

You can also require sum of all components to be small enough or invent some other metric. For example, here you can find some more accurate formulas for 'brightness'.

But if you need only limited number of colors (like 10 or 16), it seems better to just prepare list (blue, green, orange, maroon, violet, etc) and select colors from it.

Nikita Rybak
A: 

How many different colors will you ever need?

As generating suitable colors randomly is difficult, pre-select a fix palette of colors instead which you can then choose from randomly.

0xA3
+2  A: 

Using RGB you will have harder times avoiding gray colors, as well as colors "difficult to see" (I'm guessing on a white background)

If you need them to be random, you can use HSV values to stay away from the white, gray and black spectra. That means you set a range in the value and saturation parameters (for example, ~175 to 255) while hue can be selected freely at random.

So, this may work:

def random_bright_color(threshold = 175)
  hue = rand(256 - threshold) + threshold
  saturation = rand(256 - threshold) + threshold
  value = rand(256)
  hsv_to_rgb(hue, saturation, value)
end

where

def hsv_to_rgb(h, s, v)
  if s == 0
    r = g = b = (v * 2.55).round
  else
    h /= 60.0
    s /= 100.0
    v /= 100.0

    i = h.floor
    f = h - i
    p = v * (1 - s)
    q = v * (1 - s * f)
    t = v * (1 - s * (1 - f))
    rgb = case i
      when 0 then [v, t, p]
      when 1 then [q, v, p]
      when 2 then [q, v, t]
      when 3 then [p, q, v]
      when 4 then [t, p, v]
      else        [v, p, q]
    end
  end
  rgb.map{|color| (color * 255).round}
end

is ported from here and the explanation can be found on the same Wikipedia article


However, if you additionally need to have random colors different from each other, perhaps the really true solution is to have them selected from a group of base colors, and select at random from that set.

Chubas