Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RColor.cxx
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
3  * All rights reserved. *
4  * *
5  * For the licensing terms see $ROOTSYS/LICENSE. *
6  * For the list of contributors see $ROOTSYS/README/CREDITS. *
7  *************************************************************************/
8 
9 #include "ROOT/RColor.hxx"
10 
11 using namespace ROOT::Experimental;
12 
13 constexpr RColor::RGB_t RColor::kRed;
14 constexpr RColor::RGB_t RColor::kGreen;
15 constexpr RColor::RGB_t RColor::kBlue;
16 constexpr RColor::RGB_t RColor::kWhite;
17 constexpr RColor::RGB_t RColor::kBlack;
18 constexpr double RColor::kTransparent;
19 constexpr double RColor::kOpaque;
20 
21 ///////////////////////////////////////////////////////////////////////////
22 /// Converts integer from 0 to 255 into hex format with two digits like 00
23 
24 std::string RColor::toHex(int v)
25 {
26  static const char *digits = "0123456789ABCDEF";
27  if (v < 0)
28  v = 0;
29  else if (v > 255)
30  v = 255;
31 
32  std::string res(2,'0');
33  res[0] = digits[v >> 4];
34  res[1] = digits[v & 0xf];
35  return res;
36 }
37 
38 ///////////////////////////////////////////////////////////////////////////
39 /// Decodes hex color value into RGB - each color component as integer from 0 to 255
40 /// If color was not specified as hex, method returns false
41 
42 bool RColor::GetRGB(int &r, int &g, int &b) const
43 {
44  auto hex = GetHex();
45  if (hex.length() != 6)
46  return false;
47 
48  r = std::stoi(hex.substr(0,2), nullptr, 16);
49  g = std::stoi(hex.substr(2,2), nullptr, 16);
50  b = std::stoi(hex.substr(4,2), nullptr, 16);
51  return true;
52 }
53 
54 ///////////////////////////////////////////////////////////////////////////
55 /// Decodes color component and returns integer from 0 to 255
56 /// Values of indx 0: Red, 1: Green, 2: Blue
57 /// If color was not specified as hex, method returns 0
58 
59 int RColor::GetColorComponent(int indx) const
60 {
61  auto hex = GetHex();
62 
63  return hex.length() == 6 ? std::stoi(hex.substr(indx * 2, 2), nullptr, 16) : 0;
64 }
65 
66 ///////////////////////////////////////////////////////////////////////////
67 /// Decodes hex color value into RGB - each color component as float from 0. to 1.
68 /// If color was not specified as hex, method returns false
69 
70 bool RColor::GetRGBFloat(float &r, float &g, float &b) const
71 {
72  int ri, gi, bi;
73  if (!GetRGB(ri,gi,bi))
74  return false;
75  r = ri/255.;
76  g = gi/255.;
77  b = bi/255.;
78  return true;
79 }
80 
81 ///////////////////////////////////////////////////////////////////////////
82 /// Returns the Hue, Light, Saturation (HLS) definition of this RColor
83 /// If color was not specified as hex, method returns false
84 
85 bool RColor::GetHLS(float &hue, float &light, float &satur) const
86 {
87  float red, green, blue;
88  if (!GetRGBFloat(red,green,blue))
89  return false;
90 
91  hue = light = satur = 0.;
92 
93  float rnorm, gnorm, bnorm, minval, maxval, msum, mdiff;
94  minval = maxval =0 ;
95 
96  minval = red;
97  if (green < minval) minval = green;
98  if (blue < minval) minval = blue;
99  maxval = red;
100  if (green > maxval) maxval = green;
101  if (blue > maxval) maxval = blue;
102 
103  rnorm = gnorm = bnorm = 0;
104  mdiff = maxval - minval;
105  msum = maxval + minval;
106  light = 0.5 * msum;
107  if (maxval != minval) {
108  rnorm = (maxval - red)/mdiff;
109  gnorm = (maxval - green)/mdiff;
110  bnorm = (maxval - blue)/mdiff;
111  } else {
112  satur = hue = 0;
113  return true;
114  }
115 
116  if (light < 0.5) satur = mdiff/msum;
117  else satur = mdiff/(2.0 - msum);
118 
119  if (red == maxval) hue = 60.0 * (6.0 + bnorm - gnorm);
120  else if (green == maxval) hue = 60.0 * (2.0 + rnorm - bnorm);
121  else hue = 60.0 * (4.0 + gnorm - rnorm);
122 
123  if (hue > 360) hue = hue - 360;
124  return true;
125 }
126 
127 ///////////////////////////////////////////////////////////////////////////
128 /// Set the color value from the Hue, Light, Saturation (HLS).
129 
130 RColor &RColor::SetHLS(float hue, float light, float satur)
131 {
132  float rh, rl, rs, rm1, rm2;
133  rh = rl = rs = 0;
134  if (hue > 0) { rh = hue; if (rh > 360) rh = 360; }
135  if (light > 0) { rl = light; if (rl > 1) rl = 1; }
136  if (satur > 0) { rs = satur; if (rs > 1) rs = 1; }
137 
138  if (rl <= 0.5) rm2 = rl*(1.0 + rs);
139  else rm2 = rl + rs - rl*rs;
140  rm1 = 2.0*rl - rm2;
141 
142  if (!rs) { SetRGBFloat(rl, rl, rl); return *this; }
143 
144  auto toRGB = [rm1, rm2] (float h) {
145  if (h > 360) h = h - 360;
146  if (h < 0) h = h + 360;
147  if (h < 60 ) return rm1 + (rm2-rm1)*h/60;
148  if (h < 180) return rm2;
149  if (h < 240) return rm1 + (rm2-rm1)*(240-h)/60;
150  return rm1;
151  };
152 
153  return SetRGBFloat(toRGB(rh+120), toRGB(rh), toRGB(rh-120));
154 }