有些时候咱们须要为一些对象附上随机的颜色,好比咱们有这么一个需求,在一个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 }