source: ntrip/branches/BNC_2.11.0/qwt/qwt_color_map.cpp@ 6611

Last change on this file since 6611 was 4271, checked in by mervart, 12 years ago
File size: 9.9 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_color_map.h"
11#include "qwt_math.h"
12#include "qwt_interval.h"
13#include <qnumeric.h>
14
15class QwtLinearColorMap::ColorStops
16{
17public:
18 ColorStops()
19 {
20 _stops.reserve( 256 );
21 }
22
23 void insert( double pos, const QColor &color );
24 QRgb rgb( QwtLinearColorMap::Mode, double pos ) const;
25
26 QVector<double> stops() const;
27
28private:
29
30 class ColorStop
31 {
32 public:
33 ColorStop():
34 pos( 0.0 ),
35 rgb( 0 )
36 {
37 };
38
39 ColorStop( double p, const QColor &c ):
40 pos( p ),
41 rgb( c.rgb() )
42 {
43 r = qRed( rgb );
44 g = qGreen( rgb );
45 b = qBlue( rgb );
46 }
47
48 double pos;
49 QRgb rgb;
50 int r, g, b;
51 };
52
53 inline int findUpper( double pos ) const;
54 QVector<ColorStop> _stops;
55};
56
57void QwtLinearColorMap::ColorStops::insert( double pos, const QColor &color )
58{
59 // Lookups need to be very fast, insertions are not so important.
60 // Anyway, a balanced tree is what we need here. TODO ...
61
62 if ( pos < 0.0 || pos > 1.0 )
63 return;
64
65 int index;
66 if ( _stops.size() == 0 )
67 {
68 index = 0;
69 _stops.resize( 1 );
70 }
71 else
72 {
73 index = findUpper( pos );
74 if ( index == _stops.size() ||
75 qAbs( _stops[index].pos - pos ) >= 0.001 )
76 {
77 _stops.resize( _stops.size() + 1 );
78 for ( int i = _stops.size() - 1; i > index; i-- )
79 _stops[i] = _stops[i-1];
80 }
81 }
82
83 _stops[index] = ColorStop( pos, color );
84}
85
86inline QVector<double> QwtLinearColorMap::ColorStops::stops() const
87{
88 QVector<double> positions( _stops.size() );
89 for ( int i = 0; i < _stops.size(); i++ )
90 positions[i] = _stops[i].pos;
91 return positions;
92}
93
94inline int QwtLinearColorMap::ColorStops::findUpper( double pos ) const
95{
96 int index = 0;
97 int n = _stops.size();
98
99 const ColorStop *stops = _stops.data();
100
101 while ( n > 0 )
102 {
103 const int half = n >> 1;
104 const int middle = index + half;
105
106 if ( stops[middle].pos <= pos )
107 {
108 index = middle + 1;
109 n -= half + 1;
110 }
111 else
112 n = half;
113 }
114
115 return index;
116}
117
118inline QRgb QwtLinearColorMap::ColorStops::rgb(
119 QwtLinearColorMap::Mode mode, double pos ) const
120{
121 if ( pos <= 0.0 )
122 return _stops[0].rgb;
123 if ( pos >= 1.0 )
124 return _stops[ _stops.size() - 1 ].rgb;
125
126 const int index = findUpper( pos );
127 if ( mode == FixedColors )
128 {
129 return _stops[index-1].rgb;
130 }
131 else
132 {
133 const ColorStop &s1 = _stops[index-1];
134 const ColorStop &s2 = _stops[index];
135
136 const double ratio = ( pos - s1.pos ) / ( s2.pos - s1.pos );
137
138 const int r = s1.r + qRound( ratio * ( s2.r - s1.r ) );
139 const int g = s1.g + qRound( ratio * ( s2.g - s1.g ) );
140 const int b = s1.b + qRound( ratio * ( s2.b - s1.b ) );
141
142 return qRgb( r, g, b );
143 }
144}
145
146//! Constructor
147QwtColorMap::QwtColorMap( Format format ):
148 d_format( format )
149{
150}
151
152//! Destructor
153QwtColorMap::~QwtColorMap()
154{
155}
156
157/*!
158 Build and return a color map of 256 colors
159
160 The color table is needed for rendering indexed images in combination
161 with using colorIndex().
162
163 \param interval Range for the values
164 \return A color table, that can be used for a QImage
165*/
166QVector<QRgb> QwtColorMap::colorTable( const QwtInterval &interval ) const
167{
168 QVector<QRgb> table( 256 );
169
170 if ( interval.isValid() )
171 {
172 const double step = interval.width() / ( table.size() - 1 );
173 for ( int i = 0; i < table.size(); i++ )
174 table[i] = rgb( interval, interval.minValue() + step * i );
175 }
176
177 return table;
178}
179
180class QwtLinearColorMap::PrivateData
181{
182public:
183 ColorStops colorStops;
184 QwtLinearColorMap::Mode mode;
185};
186
187/*!
188 Build a color map with two stops at 0.0 and 1.0. The color
189 at 0.0 is Qt::blue, at 1.0 it is Qt::yellow.
190
191 \param format Preferred format of the color map
192*/
193QwtLinearColorMap::QwtLinearColorMap( QwtColorMap::Format format ):
194 QwtColorMap( format )
195{
196 d_data = new PrivateData;
197 d_data->mode = ScaledColors;
198
199 setColorInterval( Qt::blue, Qt::yellow );
200}
201
202/*!
203 Build a color map with two stops at 0.0 and 1.0.
204
205 \param color1 Color used for the minimum value of the value interval
206 \param color2 Color used for the maximum value of the value interval
207 \param format Preferred format of the coor map
208*/
209QwtLinearColorMap::QwtLinearColorMap( const QColor &color1,
210 const QColor &color2, QwtColorMap::Format format ):
211 QwtColorMap( format )
212{
213 d_data = new PrivateData;
214 d_data->mode = ScaledColors;
215 setColorInterval( color1, color2 );
216}
217
218//! Destructor
219QwtLinearColorMap::~QwtLinearColorMap()
220{
221 delete d_data;
222}
223
224/*!
225 \brief Set the mode of the color map
226
227 FixedColors means the color is calculated from the next lower
228 color stop. ScaledColors means the color is calculated
229 by interpolating the colors of the adjacent stops.
230
231 \sa mode()
232*/
233void QwtLinearColorMap::setMode( Mode mode )
234{
235 d_data->mode = mode;
236}
237
238/*!
239 \return Mode of the color map
240 \sa setMode()
241*/
242QwtLinearColorMap::Mode QwtLinearColorMap::mode() const
243{
244 return d_data->mode;
245}
246
247/*!
248 Set the color range
249
250 Add stops at 0.0 and 1.0.
251
252 \param color1 Color used for the minimum value of the value interval
253 \param color2 Color used for the maximum value of the value interval
254
255 \sa color1(), color2()
256*/
257void QwtLinearColorMap::setColorInterval(
258 const QColor &color1, const QColor &color2 )
259{
260 d_data->colorStops = ColorStops();
261 d_data->colorStops.insert( 0.0, color1 );
262 d_data->colorStops.insert( 1.0, color2 );
263}
264
265/*!
266 Add a color stop
267
268 The value has to be in the range [0.0, 1.0].
269 F.e. a stop at position 17.0 for a range [10.0,20.0] must be
270 passed as: (17.0 - 10.0) / (20.0 - 10.0)
271
272 \param value Value between [0.0, 1.0]
273 \param color Color stop
274*/
275void QwtLinearColorMap::addColorStop( double value, const QColor& color )
276{
277 if ( value >= 0.0 && value <= 1.0 )
278 d_data->colorStops.insert( value, color );
279}
280
281/*!
282 Return all positions of color stops in increasing order
283*/
284QVector<double> QwtLinearColorMap::colorStops() const
285{
286 return d_data->colorStops.stops();
287}
288
289/*!
290 \return the first color of the color range
291 \sa setColorInterval()
292*/
293QColor QwtLinearColorMap::color1() const
294{
295 return QColor( d_data->colorStops.rgb( d_data->mode, 0.0 ) );
296}
297
298/*!
299 \return the second color of the color range
300 \sa setColorInterval()
301*/
302QColor QwtLinearColorMap::color2() const
303{
304 return QColor( d_data->colorStops.rgb( d_data->mode, 1.0 ) );
305}
306
307/*!
308 Map a value of a given interval into a rgb value
309
310 \param interval Range for all values
311 \param value Value to map into a rgb value
312*/
313QRgb QwtLinearColorMap::rgb(
314 const QwtInterval &interval, double value ) const
315{
316 if ( qIsNaN(value) )
317 return qRgba(0, 0, 0, 0);
318
319 const double width = interval.width();
320
321 double ratio = 0.0;
322 if ( width > 0.0 )
323 ratio = ( value - interval.minValue() ) / width;
324
325 return d_data->colorStops.rgb( d_data->mode, ratio );
326}
327
328/*!
329 Map a value of a given interval into a color index, between 0 and 255
330
331 \param interval Range for all values
332 \param value Value to map into a color index
333*/
334unsigned char QwtLinearColorMap::colorIndex(
335 const QwtInterval &interval, double value ) const
336{
337 const double width = interval.width();
338
339 if ( qIsNaN(value) || width <= 0.0 || value <= interval.minValue() )
340 return 0;
341
342 if ( value >= interval.maxValue() )
343 return ( unsigned char )255;
344
345 const double ratio = ( value - interval.minValue() ) / width;
346
347 unsigned char index;
348 if ( d_data->mode == FixedColors )
349 index = ( unsigned char )( ratio * 255 ); // always floor
350 else
351 index = ( unsigned char )qRound( ratio * 255 );
352
353 return index;
354}
355
356class QwtAlphaColorMap::PrivateData
357{
358public:
359 QColor color;
360 QRgb rgb;
361};
362
363
364/*!
365 Constructor
366 \param color Color of the map
367*/
368QwtAlphaColorMap::QwtAlphaColorMap( const QColor &color ):
369 QwtColorMap( QwtColorMap::RGB )
370{
371 d_data = new PrivateData;
372 d_data->color = color;
373 d_data->rgb = color.rgb() & qRgba( 255, 255, 255, 0 );
374}
375
376//! Destructor
377QwtAlphaColorMap::~QwtAlphaColorMap()
378{
379 delete d_data;
380}
381
382/*!
383 Set the color
384
385 \param color Color
386 \sa color()
387*/
388void QwtAlphaColorMap::setColor( const QColor &color )
389{
390 d_data->color = color;
391 d_data->rgb = color.rgb();
392}
393
394/*!
395 \return the color
396 \sa setColor()
397*/
398QColor QwtAlphaColorMap::color() const
399{
400 return d_data->color;
401}
402
403/*!
404 \brief Map a value of a given interval into a alpha value
405
406 alpha := (value - interval.minValue()) / interval.width();
407
408 \param interval Range for all values
409 \param value Value to map into a rgb value
410 \return rgb value, with an alpha value
411*/
412QRgb QwtAlphaColorMap::rgb( const QwtInterval &interval, double value ) const
413{
414 const double width = interval.width();
415 if ( !qIsNaN(value) && width >= 0.0 )
416 {
417 const double ratio = ( value - interval.minValue() ) / width;
418 int alpha = qRound( 255 * ratio );
419 if ( alpha < 0 )
420 alpha = 0;
421 if ( alpha > 255 )
422 alpha = 255;
423
424 return d_data->rgb | ( alpha << 24 );
425 }
426 return d_data->rgb;
427}
428
429/*!
430 Dummy function, needed to be implemented as it is pure virtual
431 in QwtColorMap. Color indices make no sense in combination with
432 an alpha channel.
433
434 \return Always 0
435*/
436unsigned char QwtAlphaColorMap::colorIndex(
437 const QwtInterval &, double ) const
438{
439 return 0;
440}
Note: See TracBrowser for help on using the repository browser.