随机颜色的生成

http://blog.youkuaiyun.com/hjh2005/article/details/8821052

有些时候我们需要为一些对象附上随机的颜色,比如我们有这么一个需求,在一个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. staticColorTypegetUniqueColor(conststd::vector<ColorType>&excludedColors)
  2. {
  3. unsignedinti,j,k;
  4. ColorTypeuniqueColor(0,0,0);
  5. //如果当前没有颜色
  6. if(excludedColors.size()==0)
  7. {
  8. returnuniqueColor;//因为没有颜色所以随便返回一个颜色
  9. }
  10. //如果当前只有一个颜色
  11. if(excludedColors.size()==1)
  12. {
  13. intmaxDist=-1;
  14. intred=excludedColors[0].mRed;
  15. intgreen=excludedColors[0].mGreen;
  16. intblue=excludedColors[0].mBlue;
  17. for(i=0;i<256;i+=255)
  18. {
  19. for(j=0;j<256;j+=255)
  20. {
  21. for(k=0;k<256;k+=255)
  22. {
  23. intdist=(i-red)*(i-red)+(j-green)*(j-green)+(k-blue)*(k-blue);
  24. if(dist>maxDist)
  25. {
  26. maxDist=dist;
  27. uniqueColor.mRed=i;
  28. uniqueColor.mGreen=j;
  29. uniqueColor.mBlue=k;
  30. }
  31. }
  32. }
  33. }
  34. returnuniqueColor;
  35. }
  36. std::vector<unsignedint>badColors;
  37. badColors.reserve(excludedColors.size());//预留空间
  38. std::vector<ColorType>::const_iteratoriter;
  39. for(iter=excludedColors.begin();iter!=excludedColors.end();iter++)
  40. {
  41. badColors.push_back((iter->mBlue<<16)+(iter->mGreen<<8)+iter->mRed);
  42. }
  43. std::sort(badColors.begin(),badColors.end());
  44. unsignedintduplicates=0;
  45. unsignedintnext;
  46. for(i=0,next=1;i<badColors.size()-duplicates;i++)
  47. {
  48. for(j=next;j<badColors.size();j++)
  49. {
  50. if(badColors[i]!=badColors[j])
  51. {
  52. badColors[i+1]=badColors[j];
  53. next=j+1;
  54. break;
  55. }
  56. else
  57. {
  58. duplicates++;
  59. }
  60. }
  61. }
  62. badColors.erase(badColors.begin()+(badColors.size()-duplicates),badColors.end());
  63. std::vector<unsignedint>::iteratorulit=badColors.begin();
  64. unsignedinttestColor;
  65. for(testColor=0;testColor<0xffffff;testColor++)
  66. {
  67. if(testColor==*ulit)
  68. {
  69. ulit++;
  70. }
  71. else
  72. {
  73. break;
  74. }
  75. }
  76. if(testColor==0x01000000)//如果搜遍了16.7百万的颜色都没找到的话,则返回无效的颜色
  77. {
  78. uniqueColor=ColorType();
  79. }
  80. else
  81. {
  82. uniqueColor.mBlue=(testColor&0xff0000)>>16;
  83. uniqueColor.mGreen=(testColor&0xff00)>>8;
  84. uniqueColor.mRed=testColor&0xff;
  85. }
  86. returnuniqueColor;
  87. }

ColorType是颜色类型,里面包含了三个分量。


如果我们要同时获取多个不同的颜色呢?可以参考下面的代码:

  1. /**
  2. *产生一个或多个唯一的颜色
  3. *@paramcount要产生的颜色的个数
  4. *@paramcolors用于保存生成颜色的向量
  5. *@paramexcludeColors要排除的颜色
  6. *@return产生的颜色的个数
  7. */
  8. staticunsignedintgetUniqueColors(unsignedintcount,std::vector<ColorType>&colors,
  9. conststd::vector<ColorType>&excludeColors)
  10. {
  11. unsignedinti,j,k,l;
  12. unsignedintnumUnique=0;
  13. doubleslValues[]={0.0,1.0,0.5,0.8,0.3,0.6,0.9,0.2,0.7,0.4,0.1};
  14. ColorTypebaseColors[]=
  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. for(i=0;i<sizeof(slValues)/sizeof(slValues[0]);i++)
  25. {
  26. for(j=0;j<sizeof(slValues)/sizeof(slValues[0]);j++)
  27. {
  28. for(k=0;k<sizeof(baseColors)/sizeof(baseColors[0]);k++)
  29. {
  30. intnewColor[3];
  31. intmaxValue;
  32. newColor[0]=(int)(baseColors[k].mRed*slValues[j]+0.5);
  33. newColor[1]=(int)(baseColors[k].mGreen*slValues[j]+0.5);
  34. newColor[2]=(int)(baseColors[k].mBlue*slValues[j]+0.5);
  35. maxValue=0;
  36. for(l=0;l<3;l++)
  37. {
  38. if(newColor[l]>maxValue)
  39. {
  40. maxValue=newColor[l];
  41. }
  42. }
  43. maxValue=(int)(maxValue*slValues[i]+0.5);
  44. for(l=0;l<3;l++)
  45. {
  46. if(newColor[l]<maxValue)
  47. {
  48. newColor[l]=maxValue;
  49. }
  50. }
  51. ColorTypecolorToInsert;
  52. colorToInsert.mRed=newColor[0];
  53. colorToInsert.mGreen=newColor[1];
  54. colorToInsert.mBlue=newColor[2];
  55. for(l=0;l<excludeColors.size();l++)
  56. {
  57. if(excludeColors[l].mRed==colorToInsert.mRed&&
  58. excludeColors[l].mGreen==colorToInsert.mGreen&&
  59. excludeColors[l].mBlue==colorToInsert.mBlue)
  60. {
  61. break;
  62. }
  63. }
  64. if(l==excludeColors.size())
  65. {
  66. for(l=0;l<colors.size();l++)
  67. {
  68. if(colors[l].mRed==colorToInsert.mRed&&
  69. colors[l].mGreen==colorToInsert.mGreen&&
  70. colors[l].mBlue==colorToInsert.mBlue)
  71. {
  72. break;
  73. }
  74. }
  75. if(l==colors.size())
  76. {
  77. colors.push_back(colorToInsert);
  78. ++numUnique;
  79. if(colors.size()==count)
  80. {
  81. returnnumUnique;
  82. }
  83. }
  84. }
  85. }
  86. }
  87. }
  88. returnnumUnique;
  89. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值