Qt 隨機顏色的生成


    有些時候我們需要為一些對象附上隨機的顏色,比如我們有這么一個需求,在一個chart里添加顯示曲線,剛開始曲線的顏色默認都是黑色的很不好看,后來為了顯示的美觀我們想給添加的曲線隨機的附上顏色,但是有一個要求,曲線的顏色不能太淡,比如不能是白色。因為我們的chart的背景顏色是白色的,如果曲線也是白色那曲線就會看不到了。

        我們首先想到的方法是如下:

Color c(rand()%256,rand()%256,rand()%256);

        這樣可以實現我們對隨機顏色的要求,但是不滿足我們不能為白色的要求,為了避免白色,我們在對這個顏色進行檢查,如果r、g、b分量的值都超過230,表示顏色太淡重新隨機,但是這樣的方法總讓人感覺不那么舒服。

        后來想到了在HSL顏色空間里做文章是否會更舒服呢?

        於是通過Wiki復習HSL顏色空間的知識。發現在HSL空間里如果L分量大於200,顏色看起來就比較淡了,所以我們可以隨機生成小於200的數值作為L分量,再借助強大的Qt於是我們可以這樣實現我們的需求:

        首先借助Qt的QColor生成一個顏色對象:

QColor qc = QColor::fromHsl(rand()%360,rand()%256,rand()%200);

        這里要注意的是H分量的值域是0到359的。

        最后得到的顏色為:

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     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM