I am trying to generate colors on the fly for a chart control. I want the colors to be visually distinctive. I don't just want the colors to be distinctive from the adjacent colors, but all colors generated so far.
I also don't want to have to have a known color collection size. Some algorithms I have seen for this require the number of things to color to be known. I want to implement a GetNextColor() for my color generator so I will not know at the time of choosing how many colors I will ultimately have and choosing a number up front feels wrong.
I am not just trying to graph a bunch of stuff in different colors, I am interested in this problem and want some feedback.
This isn't a very effective method, it works OK, but it could be much more scientific. It started out with a lot of thought and then morphed into this mess.
Any ideas on how to do this elegantly?
(It shouldn't matter, but I am using C# and I will post code when I get back to my computer I have all this stuff on.)
I believe that your question should be split into two questions:
And now the answers:
Color difference is calculated using the The CIEDE2000 Color-Difference Formula. The CIEDE2000 formula is based on the LCH color space (Luminosity, Chroma, and Hue). LCH color space is represented as a cylinder (see image here).
However, the difference formula is highly nonlinear. Therefore it would be impossible to map the colors into a square grid such that Euclidean distance would give the CIEDE2000 color-difference.
Settling on a less accurate model, we can use the CIE76 Color-Difference formula, which is based on the Lab color space ( L*a*b*). We can use Euclidean distance directly on this color space to measure the difference. There are no simple formulas for conversion between RGB or CMYK values and L*a*b*, because the RGB and CMYK color models are device dependent. The RGB or CMYK values first need to be transformed to a specific absolute color space, such as sRGB or Adobe RGB. This adjustment will be device dependent, but the resulting data from the transform will be device independent, allowing data to be transformed to the CIE 1931 color space and then transformed into L*a*b*. This article explains the procedure and the formulas.
For the L*a*b* color space and the CIE76 Color-Difference formula - we'll need to solve the problem for a 3D cube.
I believe that your best strategy would be to divide the cube into 8 cubes, which will generate 27 points. Use these points. Now divide each of the 8 cubes into another 8 cubes. For each of these cubes, 12 out of the 27 points have already been used, so you're left with 15*8 new points. In each additional step n, you can generate 15*8^n additional points.
The points-set in each step should be sorted such that the minimal distance between two consecutive points would be maximized. I don't know how to do it - I've just posted a question.
Edit:
I've crossposted on https://cstheory.stackexchange.com/ and got a good answer. See https://cstheory.stackexchange.com/questions/8609/sorting-points-such-that-the-minimal-euclidean-distance-between-consecutive-poin.
If you map the whole color space linearly then your next color would map into it using the powers of 2. Your first choice would be the center, your 2nd choice would be between start and center. Your 3rd choice would be between center and end.
Some JavaScript to illustrate.
// initialize start and end of our linear transform
var START = 0;
var END = 100;
// next function
var _level = 1;
var _index = 1;
function next() {
var pow2 = 2 << (_level - 1);
var result = (END-START) / pow2;
result = result * _index
_index = (_index + 2) % pow2;
if(_index == 1) {
_level++;
}
return result;
}
// testing
for(var i=0; i<32; i++)
console.log(next());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With