Logo ROOT  
Reference Guide
RColor.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2020, 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#include <unordered_map>
12
13using namespace ROOT::Experimental;
14
15using namespace std::string_literals;
16
19constexpr RColor::RGB_t RColor::kLime;
20constexpr RColor::RGB_t RColor::kAqua;
21constexpr RColor::RGB_t RColor::kPurple;
22constexpr RColor::RGB_t RColor::kGrey;
24constexpr RColor::RGB_t RColor::kNavy;
27constexpr RColor::RGB_t RColor::kOlive;
28constexpr RColor::RGB_t RColor::kSilver;
29constexpr RColor::RGB_t RColor::kMaroon;
33constexpr float RColor::kTransparent;
34constexpr float RColor::kSemiTransparent;
35constexpr float RColor::kOpaque;
36
37
38///////////////////////////////////////////////////////////////////////////
39/// Converts string name of color in RGB value - when possible
40
41bool RColor::ConvertToRGB(const std::string &name, std::vector<uint8_t> &rgba)
42{
43 if (name.empty()) {
44 rgba.clear();
45 return false;
46 }
47
48 if (name[0] == '#') {
49 if ((name.length() != 7) && (name.length() != 9)) return false;
50
51 rgba.resize((name.length() == 7) ? 3 : 4);
52
53 try {
54 rgba[0] = std::stoi(name.substr(1,2), nullptr, 16);
55 rgba[1] = std::stoi(name.substr(3,2), nullptr, 16);
56 rgba[2] = std::stoi(name.substr(5,2), nullptr, 16);
57 if (name.length() == 9)
58 rgba[3] = std::stoi(name.substr(7,2), nullptr, 16);
59 } catch(...) {
60 return false;
61 }
62
63 return true;
64 }
65
66 // see https://www.december.com/html/spec/colorsvghex.html
67
68 static std::unordered_map<std::string,RGB_t> known_colors = {
69 {"black", kWhite},
70 {"green", kGreen},
71 {"lime", kLime},
72 {"aqua", kAqua},
73 {"purple", kPurple},
74 {"grey", kGrey},
75 {"fuchsia", kFuchsia},
76 {"navy", kNavy},
77 {"blue", kBlue},
78 {"teal", kTeal},
79 {"olive", kOlive},
80 {"silver", kSilver},
81 {"maroon", kMaroon},
82 {"red", kRed},
83 {"yellow", kYellow},
84 {"white", kWhite}
85 };
86
87 rgba.resize(3);
88 rgba[0] = rgba[1] = rgba[2] = 0;
89
90 auto known = known_colors.find(name);
91 if (known != known_colors.end()) {
92 rgba[0] = known->second[0];
93 rgba[1] = known->second[1];
94 rgba[2] = known->second[2];
95 return true;
96 }
97
98 return true;
99}
100
101
102///////////////////////////////////////////////////////////////////////////
103/// Converts integer from 0 to 255 into hex format with two digits like 00
104
106{
107 static const char *digits = "0123456789ABCDEF";
108 std::string res(2,'0');
109 res[0] = digits[v >> 4];
110 res[1] = digits[v & 0xf];
111 return res;
112}
113
114
115///////////////////////////////////////////////////////////////////////////
116/// Set RGB values as hex
117
118bool RColor::SetRGBHex(const std::string &hex)
119{
120 if (hex.length() != 6) return false;
121
122 try {
123 SetRGB( std::stoi(hex.substr(0,2), nullptr, 16),
124 std::stoi(hex.substr(2,2), nullptr, 16),
125 std::stoi(hex.substr(4,2), nullptr, 16));
126 } catch (...) {
127 return false;
128 }
129 return true;
130}
131
132///////////////////////////////////////////////////////////////////////////
133/// Set Alpha value as hex
134
135bool RColor::SetAlphaHex(const std::string &hex)
136{
137 if (hex.length() != 6) return false;
138
139 SetAlpha(std::stoi(hex, nullptr, 16));
140 return true;
141}
142
143///////////////////////////////////////////////////////////////////////////
144/// Returns color as RGBA array, includes optionally alpha parameter 0..255
145
146std::vector<uint8_t> RColor::AsRGBA() const
147{
148 if (fRGBA.size() > 0)
149 return fRGBA;
150
151 std::vector<uint8_t> rgba;
152
153 ConvertToRGB(fName, rgba);
154
155 return rgba;
156}
157
158///////////////////////////////////////////////////////////////////////////
159/// Returns color value in hex format like "66FF66" - without any prefix
160/// Alpha parameter can be optionally included
161
162std::string RColor::AsHex(bool with_alpha) const
163{
164 auto rgba = AsRGBA();
165 std::string res;
166 if (!rgba.empty()) {
167 res = toHex(rgba[0]) + toHex(rgba[1]) + toHex(rgba[2]);
168 if ((rgba.size() == 4) && with_alpha)
169 res += toHex((rgba.size() == 4) ? rgba[3] : 0xff);
170 }
171 return res;
172}
173
174///////////////////////////////////////////////////////////////////////////
175/// Returns color value as it will be used in SVG drawing
176/// It either include hex format #66FF66 or just plain SVG name
177
178std::string RColor::AsSVG() const
179{
180 if (!fName.empty())
181 return fName;
182
183 auto hex = AsHex();
184 if (!hex.empty()) hex = "#"s + hex;
185 return hex;
186}
187
188
189///////////////////////////////////////////////////////////////////////////
190/// Returns the Hue, Light, Saturation (HLS) definition of this RColor
191/// If color was not specified as hex, method returns false
192
193bool RColor::GetHLS(float &hue, float &light, float &satur) const
194{
195 auto arr = AsRGBA();
196 if (arr.size() < 3)
197 return false;
198
199 float red = arr[0]/255., green = arr[1]/255., blue = arr[2]/255.;
200
201 hue = light = satur = 0.;
202
203 float rnorm, gnorm, bnorm, minval, maxval, msum, mdiff;
204 minval = maxval = 0 ;
205
206 minval = red;
207 if (green < minval) minval = green;
208 if (blue < minval) minval = blue;
209 maxval = red;
210 if (green > maxval) maxval = green;
211 if (blue > maxval) maxval = blue;
212
213 rnorm = gnorm = bnorm = 0;
214 mdiff = maxval - minval;
215 msum = maxval + minval;
216 light = 0.5 * msum;
217 if (maxval != minval) {
218 rnorm = (maxval - red)/mdiff;
219 gnorm = (maxval - green)/mdiff;
220 bnorm = (maxval - blue)/mdiff;
221 } else {
222 satur = hue = 0;
223 return true;
224 }
225
226 if (light < 0.5) satur = mdiff/msum;
227 else satur = mdiff/(2.0 - msum);
228
229 if (red == maxval) hue = 60.0 * (6.0 + bnorm - gnorm);
230 else if (green == maxval) hue = 60.0 * (2.0 + rnorm - bnorm);
231 else hue = 60.0 * (4.0 + gnorm - rnorm);
232
233 if (hue > 360) hue = hue - 360;
234 return true;
235}
236
237///////////////////////////////////////////////////////////////////////////
238/// Set the color value from the Hue, Light, Saturation (HLS).
239
240void RColor::SetHLS(float hue, float light, float satur)
241{
242 float rh, rl, rs, rm1, rm2;
243 rh = rl = rs = 0;
244 if (hue > 0) { rh = hue; if (rh > 360) rh = 360; }
245 if (light > 0) { rl = light; if (rl > 1) rl = 1; }
246 if (satur > 0) { rs = satur; if (rs > 1) rs = 1; }
247
248 if (rl <= 0.5) rm2 = rl*(1.0 + rs);
249 else rm2 = rl + rs - rl*rs;
250 rm1 = 2.0*rl - rm2;
251
252 if (!rs) {
253 SetRGB((uint8_t) (rl*255.), (uint8_t) (rl*255.), (uint8_t) (rl*255.));
254 return;
255 }
256
257 auto toRGB = [rm1, rm2] (float h) {
258 if (h > 360) h = h - 360;
259 if (h < 0) h = h + 360;
260 if (h < 60 ) return rm1 + (rm2-rm1)*h/60;
261 if (h < 180) return rm2;
262 if (h < 240) return rm1 + (rm2-rm1)*(240-h)/60;
263 return rm1;
264 };
265
266 SetRGB(toRGB(rh+120), toRGB(rh), toRGB(rh-120));
267}
uint8_t
Definition: Converters.cxx:858
#define h(i)
Definition: RSha256.hxx:106
@ kTeal
Definition: Rtypes.h:65
@ kRed
Definition: Rtypes.h:64
@ kBlack
Definition: Rtypes.h:63
@ kGreen
Definition: Rtypes.h:64
@ kWhite
Definition: Rtypes.h:63
@ kBlue
Definition: Rtypes.h:64
@ kYellow
Definition: Rtypes.h:64
@ kFuchsia
Definition: TColor.h:117
char name[80]
Definition: TGX11.cxx:109
static constexpr RGB_t kRed
Definition: RColor.hxx:219
static constexpr RGB_t kLime
Definition: RColor.hxx:208
void SetRGB(const RGB_t &rgb)
Set r/g/b components of color.
Definition: RColor.hxx:72
static bool ConvertToRGB(const std::string &name, std::vector< uint8_t > &rgba)
Converts string name of color in RGB value - when possible.
Definition: RColor.cxx:41
std::vector< uint8_t > fRGBA
RGB + Alpha.
Definition: RColor.hxx:42
static constexpr RGB_t kYellow
Definition: RColor.hxx:220
void SetHLS(float hue, float light, float satur)
Set the Red Green and Blue (RGB) values from the Hue, Light, Saturation (HLS).
Definition: RColor.cxx:240
static constexpr RGB_t kPurple
Definition: RColor.hxx:210
static constexpr RGB_t kGreen
Definition: RColor.hxx:207
bool GetHLS(float &hue, float &light, float &satur) const
Return the Hue, Light, Saturation (HLS) definition of this RColor.
Definition: RColor.cxx:193
std::string fName
name of color - if any
Definition: RColor.hxx:43
bool SetRGBHex(const std::string &hex)
Set RGB values as hex.
Definition: RColor.cxx:118
std::vector< uint8_t > AsRGBA() const
Returns color as RGBA array, trying also convert color name into RGBA value.
Definition: RColor.cxx:146
static constexpr RGB_t kFuchsia
Definition: RColor.hxx:212
static constexpr RGB_t kWhite
Definition: RColor.hxx:221
bool SetAlphaHex(const std::string &hex)
Set Alpha value as hex.
Definition: RColor.cxx:135
std::string AsSVG() const
Returns color value as it will be used in SVG drawing It either include hex format #66FF66 or just pl...
Definition: RColor.cxx:178
static constexpr RGB_t kGrey
Definition: RColor.hxx:211
static constexpr RGB_t kTeal
Definition: RColor.hxx:215
static constexpr RGB_t kAqua
Definition: RColor.hxx:209
static constexpr RGB_t kBlue
Definition: RColor.hxx:214
static constexpr RGB_t kNavy
Definition: RColor.hxx:213
std::string AsHex(bool with_alpha=false) const
Returns color value in hex format like "66FF66" - without any prefix Alpha parameter can be optionall...
Definition: RColor.cxx:162
static constexpr RGB_t kOlive
Definition: RColor.hxx:216
static constexpr RGB_t kMaroon
Definition: RColor.hxx:218
void SetAlpha(uint8_t alpha)
Set alpha as value from range 0..255.
Definition: RColor.hxx:106
std::array< uint8_t, 3 > RGB_t
Definition: RColor.hxx:38
static std::string toHex(uint8_t v)
Converts integer from 0 to 255 into hex format with two digits like 00.
Definition: RColor.cxx:105
static constexpr RGB_t kSilver
Definition: RColor.hxx:217
static constexpr double s