SUMO - Simulation of Urban MObility
RGBColor.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
20 // A RGB-color definition
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <cmath>
34 #include <cassert>
35 #include <string>
36 #include <sstream>
38 #include <utils/common/ToString.h>
41 #include <utils/common/StdDefs.h>
42 #include "RGBColor.h"
43 
44 
45 // ===========================================================================
46 // static member definitions
47 // ===========================================================================
48 const RGBColor RGBColor::RED = RGBColor(255, 0, 0, 255);
49 const RGBColor RGBColor::GREEN = RGBColor(0, 255, 0, 255);
50 const RGBColor RGBColor::BLUE = RGBColor(0, 0, 255, 255);
51 const RGBColor RGBColor::YELLOW = RGBColor(255, 255, 0, 255);
52 const RGBColor RGBColor::CYAN = RGBColor(0, 255, 255, 255);
53 const RGBColor RGBColor::MAGENTA = RGBColor(255, 0, 255, 255);
54 const RGBColor RGBColor::ORANGE = RGBColor(255, 128, 0, 255);
55 const RGBColor RGBColor::WHITE = RGBColor(255, 255, 255, 255);
56 const RGBColor RGBColor::BLACK = RGBColor(0, 0, 0, 255);
57 const RGBColor RGBColor::GREY = RGBColor(128, 128, 128, 255);
58 
60 const std::string RGBColor::DEFAULT_COLOR_STRING = toString(RGBColor::DEFAULT_COLOR);
61 
62 
63 // ===========================================================================
64 // method definitions
65 // ===========================================================================
67  : myRed(0), myGreen(0), myBlue(0), myAlpha(0) {}
68 
69 
70 RGBColor::RGBColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
71  : myRed(red), myGreen(green), myBlue(blue), myAlpha(alpha) {}
72 
73 
75  : myRed(col.myRed), myGreen(col.myGreen), myBlue(col.myBlue), myAlpha(col.myAlpha) {}
76 
77 
79 
80 
81 void
82 RGBColor::set(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
83  myRed = r;
84  myGreen = g;
85  myBlue = b;
86  myAlpha = a;
87 }
88 
89 
90 std::ostream&
91 operator<<(std::ostream& os, const RGBColor& col) {
92  if (col == RGBColor::RED) {
93  return os << "red";
94  }
95  if (col == RGBColor::GREEN) {
96  return os << "green";
97  }
98  if (col == RGBColor::BLUE) {
99  return os << "blue";
100  }
101  if (col == RGBColor::YELLOW) {
102  return os << "yellow";
103  }
104  if (col == RGBColor::CYAN) {
105  return os << "cyan";
106  }
107  if (col == RGBColor::MAGENTA) {
108  return os << "magenta";
109  }
110  if (col == RGBColor::ORANGE) {
111  return os << "orange";
112  }
113  if (col == RGBColor::WHITE) {
114  return os << "white";
115  }
116  if (col == RGBColor::BLACK) {
117  return os << "black";
118  }
119  if (col == RGBColor::GREY) {
120  return os << "grey";
121  }
122  os << static_cast<int>(col.myRed) << ","
123  << static_cast<int>(col.myGreen) << ","
124  << static_cast<int>(col.myBlue);
125  if (col.myAlpha < 255) {
126  os << "," << static_cast<int>(col.myAlpha);
127  }
128  return os;
129 }
130 
131 
132 bool
134  return myRed == c.myRed && myGreen == c.myGreen && myBlue == c.myBlue && myAlpha == c.myAlpha;
135 }
136 
137 
138 bool
140  return myRed != c.myRed || myGreen != c.myGreen || myBlue != c.myBlue || myAlpha != c.myAlpha;
141 }
142 
143 
144 RGBColor
146  // obtain inverse colors
147  const unsigned char r = (unsigned char)(255 - (int)myRed);
148  const unsigned char g = (unsigned char)(255 - (int)myGreen);
149  const unsigned char b = (unsigned char)(255 - (int)myBlue);
150  // return inverted RBColor
151  return RGBColor(r, g, b, myAlpha);
152 }
153 
154 
155 RGBColor
156 RGBColor::changedBrightness(int change, int toChange) const {
157  const unsigned char red = (unsigned char)(MIN2(MAX2(myRed + change, 0), 255));
158  const unsigned char blue = (unsigned char)(MIN2(MAX2(myBlue + change, 0), 255));
159  const unsigned char green = (unsigned char)(MIN2(MAX2(myGreen + change, 0), 255));
160  int changed = ((int)red - (int)myRed) + ((int)blue - (int)myBlue) + ((int)green - (int)myGreen);
161  const RGBColor result(red, green, blue, myAlpha);
162  if (changed == toChange * change) {
163  return result;
164  } else if (changed == 0) {
165  return result;
166  } else {
167  const int maxedColors = (red != myRed + change ? 1 : 0) + (blue != myBlue + change ? 1 : 0) + (green != myGreen + change ? 1 : 0);
168  if (maxedColors == 3) {
169  return result;
170  } else {
171  const int toChangeNext = 3 - maxedColors;
172  return result.changedBrightness((int)((toChange * change - changed) / toChangeNext), toChangeNext);
173  }
174  }
175 }
176 
177 
178 RGBColor
179 RGBColor::parseColor(std::string coldef) {
180  std::transform(coldef.begin(), coldef.end(), coldef.begin(), tolower);
181  if (coldef == "red") {
182  return RED;
183  }
184  if (coldef == "green") {
185  return GREEN;
186  }
187  if (coldef == "blue") {
188  return BLUE;
189  }
190  if (coldef == "yellow") {
191  return YELLOW;
192  }
193  if (coldef == "cyan") {
194  return CYAN;
195  }
196  if (coldef == "magenta") {
197  return MAGENTA;
198  }
199  if (coldef == "orange") {
200  return ORANGE;
201  }
202  if (coldef == "white") {
203  return WHITE;
204  }
205  if (coldef == "black") {
206  return BLACK;
207  }
208  if (coldef == "grey" || coldef == "gray") {
209  return GREY;
210  }
211  unsigned char r = 0;
212  unsigned char g = 0;
213  unsigned char b = 0;
214  unsigned char a = 255;
215  if (coldef[0] == '#') {
216  const int coldesc = TplConvert::_hex2int(coldef.c_str());
217  if (coldef.length() == 7) {
218  r = static_cast<unsigned char>((coldesc & 0xFF0000) >> 16);
219  g = static_cast<unsigned char>((coldesc & 0x00FF00) >> 8);
220  b = coldesc & 0xFF;
221  } else if (coldef.length() == 9) {
222  r = static_cast<unsigned char>((coldesc & 0xFF000000) >> 24);
223  g = static_cast<unsigned char>((coldesc & 0x00FF0000) >> 16);
224  b = static_cast<unsigned char>((coldesc & 0x0000FF00) >> 8);
225  a = coldesc & 0xFF;
226  } else {
227  throw EmptyData();
228  }
229  } else {
230  std::vector<std::string> st = StringTokenizer(coldef, ",").getVector();
231  if (st.size() == 3 || st.size() == 4) {
232  try {
233  r = static_cast<unsigned char>(TplConvert::_2int(st[0].c_str()));
234  g = static_cast<unsigned char>(TplConvert::_2int(st[1].c_str()));
235  b = static_cast<unsigned char>(TplConvert::_2int(st[2].c_str()));
236  if (st.size() == 4) {
237  a = static_cast<unsigned char>(TplConvert::_2int(st[3].c_str()));
238  }
239  if (r <= 1 && g <= 1 && b <= 1 && (st.size() == 3 || a <= 1)) {
240  throw NumberFormatException();
241  }
242  } catch (NumberFormatException&) {
243  r = static_cast<unsigned char>(TplConvert::_2double(st[0].c_str()) * 255. + 0.5);
244  g = static_cast<unsigned char>(TplConvert::_2double(st[1].c_str()) * 255. + 0.5);
245  b = static_cast<unsigned char>(TplConvert::_2double(st[2].c_str()) * 255. + 0.5);
246  if (st.size() == 4) {
247  a = static_cast<unsigned char>(TplConvert::_2double(st[3].c_str()) * 255. + 0.5);
248  }
249  }
250  } else {
251  throw EmptyData();
252  }
253  }
254  return RGBColor(r, g, b, a);
255 }
256 
257 
258 RGBColor
260  const std::string& coldef, const std::string& objecttype,
261  const char* objectid, bool report, bool& ok) {
262  UNUSED_PARAMETER(report);
263  try {
264  return parseColor(coldef);
265  } catch (NumberFormatException&) {
266  } catch (EmptyData&) {
267  }
268  ok = false;
269  std::ostringstream oss;
270  oss << "Attribute 'color' in definition of ";
271  if (objectid == 0) {
272  oss << "a ";
273  }
274  oss << objecttype;
275  if (objectid != 0) {
276  oss << " '" << objectid << "'";
277  }
278  oss << " is not a valid color.";
279  WRITE_ERROR(oss.str());
280  return RGBColor();
281 }
282 
283 
284 RGBColor
285 RGBColor::interpolate(const RGBColor& minColor, const RGBColor& maxColor, double weight) {
286  if (weight < 0) {
287  weight = 0;
288  }
289  if (weight > 1) {
290  weight = 1;
291  }
292  const unsigned char r = (unsigned char)((int)minColor.myRed + (((int)maxColor.myRed - (int)minColor.myRed) * weight));
293  const unsigned char g = (unsigned char)((int)minColor.myGreen + (((int)maxColor.myGreen - (int)minColor.myGreen) * weight));
294  const unsigned char b = (unsigned char)((int)minColor.myBlue + (((int)maxColor.myBlue - (int)minColor.myBlue) * weight));
295  const unsigned char a = (unsigned char)((int)minColor.myAlpha + (((int)maxColor.myAlpha - (int)minColor.myAlpha) * weight));
296  return RGBColor(r, g, b, a);
297 }
298 
299 
300 RGBColor
301 RGBColor::fromHSV(double h, double s, double v) {
302  // H is given on [0, 6] or UNDEFINED. S and V are given on [0, 1].
303  // RGB are each returned on [0, 255].
304  //float h = HSV.H, s = HSV.S, v = HSV.V,
305  double f;
306  h /= 60.;
307  int i;
308  //if (h == UNDEFINED) RETURN_RGB(v, v, v);
309  i = int(floor(h));
310  f = float(h - i);
311  if (!(i & 1)) {
312  f = 1 - f; // if i is even
313  }
314  const unsigned char m = static_cast<unsigned char>(v * (1 - s) * 255. + 0.5);
315  const unsigned char n = static_cast<unsigned char>(v * (1 - s * f) * 255. + 0.5);
316  const unsigned char vv = static_cast<unsigned char>(v * 255. + 0.5);
317  switch (i) {
318  case 6:
319  case 0:
320  return RGBColor(vv, n, m, 255);
321  case 1:
322  return RGBColor(n, vv, m, 255);
323  case 2:
324  return RGBColor(m, vv, n, 255);
325  case 3:
326  return RGBColor(m, n, vv, 255);
327  case 4:
328  return RGBColor(n, m, vv, 255);
329  case 5:
330  return RGBColor(vv, m, n, 255);
331  }
332  return RGBColor(255, 255, 255, 255);
333 }
334 
335 
336 /****************************************************************************/
337 
static int _hex2int(const E *const data)
converts a char-type array with a hex value into the integer value described by it ...
Definition: TplConvert.h:176
static const RGBColor BLUE
Definition: RGBColor.h:180
static RGBColor parseColor(std::string coldef)
Parses a color information.
Definition: RGBColor.cpp:179
RGBColor changedBrightness(int change, int toChange=3) const
Returns a new color with altered brightness.
Definition: RGBColor.cpp:156
~RGBColor()
Destructor.
Definition: RGBColor.cpp:78
static RGBColor fromHSV(double h, double s, double v)
Converts the given hsv-triplet to rgb.
Definition: RGBColor.cpp:301
static const RGBColor WHITE
Definition: RGBColor.h:185
static RGBColor parseColorReporting(const std::string &coldef, const std::string &objecttype, const char *objectid, bool report, bool &ok)
Parses a color information.
Definition: RGBColor.cpp:259
unsigned char alpha() const
Returns the alpha-amount of the color.
Definition: RGBColor.h:89
static const RGBColor ORANGE
Definition: RGBColor.h:184
T MAX2(T a, T b)
Definition: StdDefs.h:73
unsigned char blue() const
Returns the blue-amount of the color.
Definition: RGBColor.h:82
friend std::ostream & operator<<(std::ostream &os, const RGBColor &col)
Writes the color to the given stream.
Definition: RGBColor.cpp:91
static const RGBColor BLACK
Definition: RGBColor.h:186
bool operator==(const RGBColor &c) const
Definition: RGBColor.cpp:133
RGBColor invertedColor() const
obtain inverted of current RGBColor
Definition: RGBColor.cpp:145
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
bool operator!=(const RGBColor &c) const
Definition: RGBColor.cpp:139
static const RGBColor GREEN
Definition: RGBColor.h:179
static const RGBColor GREY
Definition: RGBColor.h:187
unsigned char myAlpha
Definition: RGBColor.h:198
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
unsigned char myRed
The color amounts.
Definition: RGBColor.h:198
void set(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
assigns new values
Definition: RGBColor.cpp:82
static const RGBColor DEFAULT_COLOR
The default color (for vehicle types and vehicles)
Definition: RGBColor.h:191
unsigned char myGreen
Definition: RGBColor.h:198
static const RGBColor MAGENTA
Definition: RGBColor.h:183
T MIN2(T a, T b)
Definition: StdDefs.h:67
std::vector< std::string > getVector()
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:205
static const RGBColor YELLOW
Definition: RGBColor.h:181
static int _2int(const E *const data)
converts a char-type array into the integer value described by it
Definition: TplConvert.h:155
static const RGBColor RED
named colors
Definition: RGBColor.h:178
static const RGBColor CYAN
Definition: RGBColor.h:182
unsigned char green() const
Returns the green-amount of the color.
Definition: RGBColor.h:75
static double _2double(const E *const data)
converts a char-type array into the double value described by it
Definition: TplConvert.h:311
unsigned char myBlue
Definition: RGBColor.h:198
unsigned char red() const
Returns the red-amount of the color.
Definition: RGBColor.h:68
RGBColor()
Constructor.
Definition: RGBColor.cpp:66
static RGBColor interpolate(const RGBColor &minColor, const RGBColor &maxColor, double weight)
Interpolates between two colors.
Definition: RGBColor.cpp:285
static const std::string DEFAULT_COLOR_STRING
The string description of the default color.
Definition: RGBColor.h:194