有些時候咱們須要爲一些對象附上隨機的顏色,好比咱們有這麼一個需求,在一個chart裏添加顯示曲線,剛開始曲線的顏色默認都是黑色的很很差看,後來爲了顯示的美觀咱們想給添加的曲線隨機的附上顏色,可是有一個要求,曲線的顏色不能太淡,好比不能是白色。由於咱們的chart的背景顏色是白色的,若是曲線也是白色那曲線就會看不到了。spa
咱們首先想到的方法是以下:code
Color c(rand()%256,rand()%256,rand()%256);
這樣能夠實現咱們對隨機顏色的要求,可是不知足咱們不能爲白色的要求,爲了不白色,咱們在對這個顏色進行檢查,若是r、g、b份量的值都超過230,表示顏色太淡從新隨機,可是這樣的方法總讓人感受不那麼舒服。對象
後來想到了在HSL顏色空間裏作文章是否會更舒服呢?blog
因而經過Wiki複習HSL顏色空間的知識。發如今HSL空間裏若是L份量大於200,顏色看起來就比較淡了,因此咱們能夠隨機生成小於200的數值做爲L份量,再借助強大的Qt因而咱們能夠這樣實現咱們的需求:get
首先借助Qt的QColor生成一個顏色對象:it
QColor qc = QColor::fromHsl(rand()%360,rand()%256,rand()%200);
這裏要注意的是H份量的值域是0到359的。class
最後獲得的顏色爲:test
Color c(qc.red(),qc.green(),qc.blue());
若是不用Qt的話,網上有不少HSL顏色空間轉RGB顏色空間的代碼和公式也但是替代上面用到的Qt。這樣咱們就省略了第一種方法裏的循環,實現的方法看起來更加舒服了。循環
有些時候咱們可能會有這樣的需求,好比咱們想給一張地圖上色,相鄰的國家的顏色視覺區別要儘量大,因而咱們給的一種或幾種顏色,要找到與這些顏色差異最大的顏色,這要怎麼實現呢?下面是別人寫的代碼。我以爲仍是有改進的空間的:方法
1 static ColorType getUniqueColor(const std::vector<ColorType>& excludedColors) 2 { 3 unsigned int i,j,k; 4 ColorType uniqueColor(0,0,0); 5 //若是當前沒有顏色
6 if (excludedColors.size()==0) 7 { 8 return uniqueColor; //由於沒有顏色因此隨便返回一個顏色
9 } 10 //若是當前只有一個顏色
11 if (excludedColors.size()==1) 12 { 13 int maxDist=-1; 14 int red=excludedColors[0].mRed; 15 int green=excludedColors[0].mGreen; 16 int blue=excludedColors[0].mBlue; 17
18 for (i=0;i<256;i+=255) 19 { 20 for (j=0;j<256;j+=255) 21 { 22 for (k=0;k<256;k+=255) 23 { 24 int dist=(i-red)*(i-red)+(j-green)*(j-green)+(k-blue)*(k-blue); 25 if (dist>maxDist) 26 { 27 maxDist=dist; 28 uniqueColor.mRed=i; 29 uniqueColor.mGreen=j; 30 uniqueColor.mBlue=k; 31 } 32 } 33 } 34 } 35 return uniqueColor; 36 } 37
38 std::vector<unsigned int> badColors; 39 badColors.reserve(excludedColors.size()); //預留空間
40
41 std::vector<ColorType>::const_iterator iter; 42 for (iter=excludedColors.begin();iter!=excludedColors.end();iter++) 43 { 44 badColors.push_back((iter->mBlue<<16)+(iter->mGreen<<8)+iter->mRed); 45 } 46
47 std::sort(badColors.begin(),badColors.end()); 48
49 unsigned int duplicates=0; 50 unsigned int next; 51
52 for (i=0,next=1;i<badColors.size()-duplicates;i++) 53 { 54 for (j = next; j < badColors.size(); j++) 55 { 56 if (badColors[i] != badColors[j]) 57 { 58 badColors[i + 1] = badColors[j]; 59 next = j + 1; 60 break; 61 } 62 else
63 { 64 duplicates++; 65 } 66 } 67 } 68 badColors.erase(badColors.begin() + (badColors.size() - duplicates), badColors.end()); 69
70 std::vector<unsigned int>::iterator ulit = badColors.begin(); 71 unsigned int testColor; 72 for (testColor = 0; testColor < 0xffffff; testColor++) 73 { 74 if (testColor == *ulit) 75 { 76 ulit++; 77 } 78 else
79 { 80 break; 81 } 82 } 83
84 if (testColor == 0x01000000) // 若是搜遍了16.7百萬的顏色都沒找到的話,則返回無效的顏色
85 { 86 uniqueColor = ColorType(); 87 } 88 else
89 { 90 uniqueColor.mBlue = (testColor&0xff0000)>>16; 91 uniqueColor.mGreen = (testColor&0xff00)>>8; 92 uniqueColor.mRed = testColor&0xff; 93 } 94
95 return uniqueColor; 96 }
ColorType是顏色類型,裏面包含了三個份量。
若是咱們要同時獲取多個不一樣的顏色呢?能夠參考下面的代碼:
1 /** 2 * 產生一個或多個惟一的顏色 3 * @param count 要產生的顏色的個數 4 * @param colors 用於保存生成顏色的向量 5 * @param excludeColors 要排除的顏色 6 * @return 產生的顏色的個數 7 */
8 static unsigned int getUniqueColors(unsigned int count, std::vector<ColorType>& colors, 9 const std::vector<ColorType>& excludeColors) 10 { 11 unsigned int i, j, k, l; 12 unsigned int numUnique = 0; 13 double slValues[] = {0.0, 1.0, 0.5, 0.8, 0.3, 0.6, 0.9, 0.2, 0.7, 0.4, 0.1}; 14 ColorType baseColors[] =
15 { 16 ColorType(0,0,255), 17 ColorType(0,255,0), 18 ColorType(255,0,0), 19 ColorType(0,255,255), 20 ColorType(255,255,0), 21 ColorType(255,0,255), 22 ColorType(255,255,255) 23 }; 24
25 for (i = 0; i < sizeof(slValues) / sizeof(slValues[0]); i++) 26 { 27 for (j = 0; j < sizeof(slValues) / sizeof(slValues[0]); j++) 28 { 29 for (k = 0; k < sizeof(baseColors) / sizeof(baseColors[0]); k++) 30 { 31 int newColor[3]; 32 int maxValue; 33
34 newColor[0] = (int) (baseColors[k].mRed * slValues[j] + 0.5); 35 newColor[1] = (int) (baseColors[k].mGreen * slValues[j] + 0.5); 36 newColor[2] = (int) (baseColors[k].mBlue * slValues[j] + 0.5); 37
38 maxValue = 0; 39 for (l = 0; l < 3; l++) 40 { 41 if (newColor[l] > maxValue) 42 { 43 maxValue = newColor[l]; 44 } 45 } 46
47 maxValue = (int) (maxValue * slValues[i] + 0.5); 48 for (l = 0; l < 3; l++) 49 { 50 if (newColor[l] < maxValue) 51 { 52 newColor[l] = maxValue; 53 } 54 } 55
56 ColorType colorToInsert; 57 colorToInsert.mRed = newColor[0]; 58 colorToInsert.mGreen = newColor[1]; 59 colorToInsert.mBlue = newColor[2]; 60
61 for (l=0; l<excludeColors.size(); l++) 62 { 63 if (excludeColors[l].mRed == colorToInsert.mRed &&
64 excludeColors[l].mGreen == colorToInsert.mGreen &&
65 excludeColors[l].mBlue == colorToInsert.mBlue) 66 { 67 break; 68 } 69 } 70 if (l == excludeColors.size()) 71 { 72 for (l = 0; l < colors.size(); l++) 73 { 74 if (colors[l].mRed == colorToInsert.mRed &&
75 colors[l].mGreen == colorToInsert.mGreen &&
76 colors[l].mBlue == colorToInsert.mBlue) 77 { 78 break; 79 } 80 } 81 if (l == colors.size()) 82 { 83 colors.push_back (colorToInsert); 84 ++numUnique; 85 if (colors.size() == count) 86 { 87 return numUnique; 88 } 89 } 90 } 91 } 92 } 93 } 94 return numUnique; 95 }