DGtal  1.0.0
GradientColorMap.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file GradientColorMap.ih
19  * @author Sebastien Fourey (\c Sebastien.Fourey@greyc.ensicaen.fr )
20  * Groupe de Recherche en Informatique, Image, Automatique et Instrumentation de Caen - GREYC (CNRS, UMR 6072), ENSICAEN, France
21  *
22  * @date 2010/07/19
23  *
24  * Implementation of inline methods defined in GradientColorMap.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 //////////////////////////////////////////////////////////////////////////////
30 #include <cstdlib>
31 #include <cmath>
32 #include <vector>
33 //////////////////////////////////////////////////////////////////////////////
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // IMPLEMENTATION of inline methods.
37 ///////////////////////////////////////////////////////////////////////////////
38 
39 ///////////////////////////////////////////////////////////////////////////////
40 // ----------------------- Standard services ------------------------------
41 
42 template < typename PValue,
43  int PDefaultPreset,
44  int PDefaultFirstColor,
45  int PDefaultLastColor >
46 inline
47 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::GradientColorMap
48 ( const PValue & minV,
49  const PValue & maxV,
50  const ColorGradientPreset preset,
51  const Color firstColor,
52  const Color lastColor )
53  : myMin( minV ), myMax( maxV )
54 {
55  ASSERT_MSG(myMin < myMax, "Max should be strictly greather than Min in a colormap.");
56  switch ( preset ) {
57  case CMAP_GRAYSCALE:
58  myColors.push_back( Color::Black );
59  myColors.push_back( Color::White );
60  break;
61  case CMAP_SPRING:
62  myColors.push_back( Color( 255, 0, 255 ));
63  myColors.push_back( Color( 255, 255, 0 ));
64  break;
65  case CMAP_SUMMER:
66  myColors.push_back( Color( 0, 132, 100 ));
67  myColors.push_back( Color( 255, 255, 100 ));
68  break;
69  case CMAP_AUTUMN:
70  myColors.push_back( Color( 255, 0, 0 ));
71  myColors.push_back( Color( 255, 255, 0));
72  break;
73  case CMAP_WINTER:
74  myColors.push_back( Color( 0, 0, 255 ));
75  myColors.push_back( Color( 0, 255, 132 ));
76  break;
77  case CMAP_COOL:
78  myColors.push_back( Color( 0, 255, 255 ));
79  myColors.push_back( Color( 255, 0, 255 ));
80  break;
81  case CMAP_COPPER:
82  myColors.push_back( Color( 0, 0, 0 ));
83  myColors.push_back( Color( 255, 198, 123 ));
84  break;
85  case CMAP_HOT:
86  myColors.push_back( Color::Black );
87  myColors.push_back( Color::Red );
88  myColors.push_back( Color( 255, 140, 0 ) );
89  myColors.push_back( Color::Yellow );
90  myColors.push_back( Color::White );
91  break;
92  case CMAP_JET:
93  myColors.push_back( Color::Blue );
94  myColors.push_back( Color::Cyan );
95  myColors.push_back( Color::Yellow );
96  myColors.push_back( Color( 255, 140, 0 ) );
97  myColors.push_back( Color::Red );
98  myColors.push_back( Color( 132, 0, 0 ) );
99  break;
100  case CMAP_CUSTOM:
101  if ( firstColor != Color::None
102  && lastColor != Color::None ) {
103  myColors.push_back( firstColor );
104  myColors.push_back( lastColor );
105  }
106  break;
107  }
108 }
109 
110 template <typename PValue,
111  int PDefaultPreset,
112  int PDefaultFirstColor,
113  int PDefaultLastColor >
114 inline
115 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::GradientColorMap
116 ( const GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor> & other )
117  : myMin( other.myMin ), myMax( other.myMax ), myColors( other.myColors )
118 {
119  ASSERT_MSG(myMin < myMax, "Max should be strictly greather than Min in a colormap.");
120 }
121 
122 template <typename PValue,
123  int PDefaultPreset,
124  int PDefaultFirstColor,
125  int PDefaultLastColor >
126 inline
127 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::~GradientColorMap()
128 {
129 }
130 
131 template <typename PValue,
132  int PDefaultPreset,
133  int PDefaultFirstColor,
134  int PDefaultLastColor >
135 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor> &
136 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::operator=
137 ( const DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor> & other )
138 {
139  if ( &other != this ) {
140  myMin = other.myMin;
141  myMax = other.myMax;
142  ASSERT_MSG(myMin < myMax, "Max should be strictly greather than Min in a colormap.");
143  myColors = other.myColors;
144  }
145  return *this;
146 }
147 
148 ///////////////////////////////////////////////////////////////////////////////
149 // Interface - public :
150 
151 
152 template<typename PValue,
153  int PDefaultPreset,
154  int PDefaultFirstColor,
155  int PDefaultLastColor >
156 inline
157 void
158 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::addColor
159 ( const Color & color )
160 {
161  myColors.push_back( color );
162 }
163 
164 template<typename PValue,
165  int PDefaultPreset,
166  int PDefaultFirstColor,
167  int PDefaultLastColor >
168 inline
169 void
170 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::clearColors()
171 {
172  myColors.clear();
173 }
174 
175 template<typename PValue,
176  int PDefaultPreset,
177  int PDefaultFirstColor,
178  int PDefaultLastColor >
179 inline
180 const PValue &
181 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::min() const
182 {
183  return myMin;
184 }
185 
186 template<typename PValue,
187  int PDefaultPreset,
188  int PDefaultFirstColor,
189  int PDefaultLastColor >
190 inline
191 const PValue &
192 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::max() const
193 {
194  return myMax;
195 }
196 
197 template<typename PValue,
198  int PDefaultPreset,
199  int PDefaultFirstColor,
200  int PDefaultLastColor >
201 inline
202 DGtal::Color
203 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::operator()
204  ( const Value & value ) const
205 {
206  return GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::getColor( myColors,
207  myMin,
208  myMax,
209  value );
210 }
211 
212 /**
213  * Writes/Displays the object on an output stream.
214  * @param out the output stream where the object is written.
215  */
216 template <typename PValue,
217  int PDefaultPreset,
218  int PDefaultFirstColor,
219  int PDefaultLastColor >
220 inline
221 void
222 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::selfDisplay
223 ( std::ostream & out ) const
224 {
225  out << "[GradientColorMap "
226  << " min=" << myMin
227  << " max=" << myMax;
228  std::vector<Color>::iterator it = myColors.begin();
229  while ( it != myColors.end() ) {
230  out << " RGB("
231  << it->red() << ","
232  << it->green() << ","
233  << it->blue() << ") ";
234  ++it;
235  }
236  out << " ]";
237 }
238 
239 /**
240  * Checks the validity/consistency of the object.
241  * @return 'true' if the object is valid, 'false' otherwise.
242  */
243 template <typename PValue,
244  int PDefaultPreset,
245  int PDefaultFirstColor,
246  int PDefaultLastColor >
247 inline
248 bool
249 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::isValid() const
250 {
251  return true;
252 }
253 
254 template <typename PValue,
255  int PDefaultPreset,
256  int PDefaultFirstColor,
257  int PDefaultLastColor >
258 inline
259 DGtal::Color
260 DGtal::GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor>::getColor
261 ( const std::vector<Color> & colors,
262  const Value & min,
263  const Value & max,
264  Value value )
265 {
266  ASSERT_MSG(min < max, "Max should be strictly greather than Min in a colormap.");
267  if ( colors.size() < 2 )
268  return DGtal::Color::None;
269  if ( std::is_floating_point<PValue>::value
270  && ! ( std::isfinite( value ) || std::isinf( value ) ) )
271  return DGtal::Color::Black;
272  if ( value < min ) value = min;
273  if ( max < value ) value = max;
274  double scale = static_cast<double>( value - min ) / (max - min);
275  const int intervals = (const int)colors.size() - 1;
276  int upper_index = static_cast<int>( ceil( intervals * scale ) );
277  if ( !upper_index ) // Special case when value == min.
278  upper_index = 1;
279  const Color & firstColor = colors[ upper_index - 1 ];
280  const Color & lastColor = colors[ upper_index ];
281  scale = ( scale * intervals ) - (upper_index - 1);
282 
283  const unsigned char red = static_cast<unsigned char>( firstColor.red() +
284  scale * ( lastColor.red() -
285  firstColor.red() ));
286  const unsigned char green = static_cast<unsigned char>( firstColor.green() +
287  scale * ( lastColor.green() -
288  firstColor.green() ));
289  const unsigned char blue = static_cast<unsigned char>( firstColor.blue() +
290  scale * ( lastColor.blue() -
291  firstColor.blue() ));
292  return DGtal::Color( red, green, blue );
293 }
294 
295 ///////////////////////////////////////////////////////////////////////////////
296 // Implementation of inline functions //
297 
298 template <typename PValue,
299  int PDefaultPreset,
300  int PDefaultFirstColor,
301  int PDefaultLastColor >
302 inline
303 std::ostream&
304 DGtal::operator<< ( std::ostream & out,
305  const GradientColorMap<PValue,PDefaultPreset,PDefaultFirstColor,PDefaultLastColor> & object )
306 {
307  object.selfDisplay( out );
308  return out;
309 }
310 
311 // //
312 ///////////////////////////////////////////////////////////////////////////////
313 
314 
315 ///////////////////////////////////////////////////////////////////////////////
316 // Interface - private :