Chris@376
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@376
|
2
|
Chris@376
|
3 /*
|
Chris@376
|
4 Sonic Visualiser
|
Chris@376
|
5 An audio file viewer and annotation editor.
|
Chris@376
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@376
|
7 This file copyright 2006-2007 Chris Cannam and QMUL.
|
Chris@376
|
8
|
Chris@376
|
9 This program is free software; you can redistribute it and/or
|
Chris@376
|
10 modify it under the terms of the GNU General Public License as
|
Chris@376
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@376
|
12 License, or (at your option) any later version. See the file
|
Chris@376
|
13 COPYING included with this distribution for more information.
|
Chris@376
|
14 */
|
Chris@376
|
15
|
Chris@376
|
16 #include "ColourMapper.h"
|
Chris@376
|
17
|
Chris@376
|
18 #include <iostream>
|
Chris@376
|
19
|
Chris@376
|
20 #include <cmath>
|
Chris@376
|
21
|
Chris@682
|
22 #include "base/Debug.h"
|
Chris@682
|
23
|
Chris@902
|
24 ColourMapper::ColourMapper(int map, double min, double max) :
|
Chris@376
|
25 QObject(),
|
Chris@376
|
26 m_map(map),
|
Chris@376
|
27 m_min(min),
|
Chris@376
|
28 m_max(max)
|
Chris@376
|
29 {
|
Chris@376
|
30 if (m_min == m_max) {
|
Chris@682
|
31 cerr << "WARNING: ColourMapper: min == max (== " << m_min
|
Chris@682
|
32 << "), adjusting" << endl;
|
Chris@376
|
33 m_max = m_min + 1;
|
Chris@376
|
34 }
|
Chris@376
|
35 }
|
Chris@376
|
36
|
Chris@376
|
37 ColourMapper::~ColourMapper()
|
Chris@376
|
38 {
|
Chris@376
|
39 }
|
Chris@376
|
40
|
Chris@376
|
41 int
|
Chris@376
|
42 ColourMapper::getColourMapCount()
|
Chris@376
|
43 {
|
Chris@536
|
44 return 12;
|
Chris@376
|
45 }
|
Chris@376
|
46
|
Chris@376
|
47 QString
|
Chris@376
|
48 ColourMapper::getColourMapName(int n)
|
Chris@376
|
49 {
|
Chris@376
|
50 if (n >= getColourMapCount()) return tr("<unknown>");
|
Chris@376
|
51 StandardMap map = (StandardMap)n;
|
Chris@376
|
52
|
Chris@376
|
53 switch (map) {
|
Chris@376
|
54 case DefaultColours: return tr("Default");
|
Chris@376
|
55 case WhiteOnBlack: return tr("White on Black");
|
Chris@376
|
56 case BlackOnWhite: return tr("Black on White");
|
Chris@376
|
57 case RedOnBlue: return tr("Red on Blue");
|
Chris@376
|
58 case YellowOnBlack: return tr("Yellow on Black");
|
Chris@376
|
59 case BlueOnBlack: return tr("Blue on Black");
|
Chris@376
|
60 case Sunset: return tr("Sunset");
|
Chris@376
|
61 case FruitSalad: return tr("Fruit Salad");
|
Chris@376
|
62 case Banded: return tr("Banded");
|
Chris@376
|
63 case Highlight: return tr("Highlight");
|
Chris@376
|
64 case Printer: return tr("Printer");
|
Chris@536
|
65 case HighGain: return tr("High Gain");
|
Chris@376
|
66 }
|
Chris@376
|
67
|
Chris@376
|
68 return tr("<unknown>");
|
Chris@376
|
69 }
|
Chris@376
|
70
|
Chris@376
|
71 QColor
|
Chris@902
|
72 ColourMapper::map(double value) const
|
Chris@376
|
73 {
|
Chris@902
|
74 double norm = (value - m_min) / (m_max - m_min);
|
Chris@902
|
75 if (norm < 0.0) norm = 0.0;
|
Chris@902
|
76 if (norm > 1.0) norm = 1.0;
|
Chris@376
|
77
|
Chris@902
|
78 double h = 0.0, s = 0.0, v = 0.0, r = 0.0, g = 0.0, b = 0.0;
|
Chris@376
|
79 bool hsv = true;
|
Chris@376
|
80
|
Chris@911
|
81 double blue = 0.6666, pieslice = 0.3333;
|
Chris@376
|
82
|
Chris@376
|
83 if (m_map >= getColourMapCount()) return Qt::black;
|
Chris@376
|
84 StandardMap map = (StandardMap)m_map;
|
Chris@376
|
85
|
Chris@376
|
86 switch (map) {
|
Chris@376
|
87
|
Chris@376
|
88 case DefaultColours:
|
Chris@902
|
89 h = blue - norm * 2.0 * pieslice;
|
Chris@902
|
90 s = 0.5f + norm/2.0;
|
Chris@376
|
91 v = norm;
|
Chris@376
|
92 break;
|
Chris@376
|
93
|
Chris@376
|
94 case WhiteOnBlack:
|
Chris@376
|
95 r = g = b = norm;
|
Chris@376
|
96 hsv = false;
|
Chris@376
|
97 break;
|
Chris@376
|
98
|
Chris@376
|
99 case BlackOnWhite:
|
Chris@902
|
100 r = g = b = 1.0 - norm;
|
Chris@376
|
101 hsv = false;
|
Chris@376
|
102 break;
|
Chris@376
|
103
|
Chris@376
|
104 case RedOnBlue:
|
Chris@902
|
105 h = blue - pieslice/4.0 + norm * (pieslice + pieslice/4.0);
|
Chris@902
|
106 s = 1.0;
|
Chris@376
|
107 v = norm;
|
Chris@376
|
108 break;
|
Chris@376
|
109
|
Chris@376
|
110 case YellowOnBlack:
|
Chris@902
|
111 h = 0.15;
|
Chris@902
|
112 s = 1.0;
|
Chris@376
|
113 v = norm;
|
Chris@376
|
114 break;
|
Chris@376
|
115
|
Chris@376
|
116 case BlueOnBlack:
|
Chris@376
|
117 h = blue;
|
Chris@902
|
118 s = 1.0;
|
Chris@902
|
119 v = norm * 2.0;
|
Chris@902
|
120 if (v > 1.0) {
|
Chris@902
|
121 v = 1.0;
|
Chris@904
|
122 s = 1.0 - (sqrt(norm) - 0.707) * 3.413;
|
Chris@902
|
123 if (s < 0.0) s = 0.0;
|
Chris@902
|
124 if (s > 1.0) s = 1.0;
|
Chris@376
|
125 }
|
Chris@376
|
126 break;
|
Chris@376
|
127
|
Chris@376
|
128 case Sunset:
|
Chris@902
|
129 r = (norm - 0.24) * 2.38;
|
Chris@902
|
130 if (r > 1.0) r = 1.0;
|
Chris@902
|
131 if (r < 0.0) r = 0.0;
|
Chris@902
|
132 g = (norm - 0.64) * 2.777;
|
Chris@902
|
133 if (g > 1.0) g = 1.0;
|
Chris@902
|
134 if (g < 0.0) g = 0.0;
|
Chris@376
|
135 b = (3.6f * norm);
|
Chris@902
|
136 if (norm > 0.277) b = 2.0 - b;
|
Chris@902
|
137 if (b > 1.0) b = 1.0;
|
Chris@902
|
138 if (b < 0.0) b = 0.0;
|
Chris@376
|
139 hsv = false;
|
Chris@376
|
140 break;
|
Chris@376
|
141
|
Chris@376
|
142 case FruitSalad:
|
Chris@902
|
143 h = blue + (pieslice/6.0) - norm;
|
Chris@902
|
144 if (h < 0.0) h += 1.0;
|
Chris@902
|
145 s = 1.0;
|
Chris@902
|
146 v = 1.0;
|
Chris@376
|
147 break;
|
Chris@376
|
148
|
Chris@376
|
149 case Banded:
|
Chris@376
|
150 if (norm < 0.125) return Qt::darkGreen;
|
Chris@376
|
151 else if (norm < 0.25) return Qt::green;
|
Chris@376
|
152 else if (norm < 0.375) return Qt::darkBlue;
|
Chris@376
|
153 else if (norm < 0.5) return Qt::blue;
|
Chris@376
|
154 else if (norm < 0.625) return Qt::darkYellow;
|
Chris@376
|
155 else if (norm < 0.75) return Qt::yellow;
|
Chris@376
|
156 else if (norm < 0.875) return Qt::darkRed;
|
Chris@376
|
157 else return Qt::red;
|
Chris@376
|
158 break;
|
Chris@376
|
159
|
Chris@376
|
160 case Highlight:
|
Chris@376
|
161 if (norm > 0.99) return Qt::white;
|
Chris@376
|
162 else return Qt::darkBlue;
|
Chris@376
|
163
|
Chris@376
|
164 case Printer:
|
Chris@376
|
165 if (norm > 0.8) {
|
Chris@902
|
166 r = 1.0;
|
Chris@376
|
167 } else if (norm > 0.7) {
|
Chris@902
|
168 r = 0.9;
|
Chris@376
|
169 } else if (norm > 0.6) {
|
Chris@902
|
170 r = 0.8;
|
Chris@376
|
171 } else if (norm > 0.5) {
|
Chris@902
|
172 r = 0.7;
|
Chris@376
|
173 } else if (norm > 0.4) {
|
Chris@902
|
174 r = 0.6;
|
Chris@376
|
175 } else if (norm > 0.3) {
|
Chris@902
|
176 r = 0.5;
|
Chris@376
|
177 } else if (norm > 0.2) {
|
Chris@902
|
178 r = 0.4;
|
Chris@376
|
179 } else {
|
Chris@902
|
180 r = 0.0;
|
Chris@376
|
181 }
|
Chris@902
|
182 r = g = b = 1.0 - r;
|
Chris@376
|
183 hsv = false;
|
Chris@376
|
184 break;
|
Chris@536
|
185
|
Chris@536
|
186 case HighGain:
|
Chris@902
|
187 if (norm <= 1.0 / 256.0) {
|
Chris@902
|
188 norm = 0.0;
|
Chris@536
|
189 } else {
|
Chris@904
|
190 norm = 0.1f + (pow(((norm - 0.5) * 2.0), 3.0) + 1.0) / 2.081;
|
Chris@536
|
191 }
|
Chris@536
|
192 // now as for Sunset
|
Chris@902
|
193 r = (norm - 0.24) * 2.38;
|
Chris@902
|
194 if (r > 1.0) r = 1.0;
|
Chris@902
|
195 if (r < 0.0) r = 0.0;
|
Chris@902
|
196 g = (norm - 0.64) * 2.777;
|
Chris@902
|
197 if (g > 1.0) g = 1.0;
|
Chris@902
|
198 if (g < 0.0) g = 0.0;
|
Chris@536
|
199 b = (3.6f * norm);
|
Chris@902
|
200 if (norm > 0.277) b = 2.0 - b;
|
Chris@902
|
201 if (b > 1.0) b = 1.0;
|
Chris@902
|
202 if (b < 0.0) b = 0.0;
|
Chris@536
|
203 hsv = false;
|
Chris@536
|
204 /*
|
Chris@902
|
205 if (r > 1.0) r = 1.0;
|
Chris@902
|
206 r = g = b = 1.0 - r;
|
Chris@536
|
207 hsv = false;
|
Chris@536
|
208 */
|
Chris@536
|
209 break;
|
Chris@376
|
210 }
|
Chris@376
|
211
|
Chris@376
|
212 if (hsv) {
|
Chris@376
|
213 return QColor::fromHsvF(h, s, v);
|
Chris@376
|
214 } else {
|
Chris@376
|
215 return QColor::fromRgbF(r, g, b);
|
Chris@376
|
216 }
|
Chris@376
|
217 }
|
Chris@376
|
218
|
Chris@376
|
219 QColor
|
Chris@376
|
220 ColourMapper::getContrastingColour() const
|
Chris@376
|
221 {
|
Chris@376
|
222 if (m_map >= getColourMapCount()) return Qt::white;
|
Chris@376
|
223 StandardMap map = (StandardMap)m_map;
|
Chris@376
|
224
|
Chris@376
|
225 switch (map) {
|
Chris@376
|
226
|
Chris@376
|
227 case DefaultColours:
|
Chris@376
|
228 return QColor(255, 150, 50);
|
Chris@376
|
229
|
Chris@376
|
230 case WhiteOnBlack:
|
Chris@376
|
231 return Qt::red;
|
Chris@376
|
232
|
Chris@376
|
233 case BlackOnWhite:
|
Chris@376
|
234 return Qt::darkGreen;
|
Chris@376
|
235
|
Chris@376
|
236 case RedOnBlue:
|
Chris@376
|
237 return Qt::green;
|
Chris@376
|
238
|
Chris@376
|
239 case YellowOnBlack:
|
Chris@376
|
240 return QColor::fromHsv(240, 255, 255);
|
Chris@376
|
241
|
Chris@376
|
242 case BlueOnBlack:
|
Chris@376
|
243 return Qt::red;
|
Chris@376
|
244
|
Chris@376
|
245 case Sunset:
|
Chris@376
|
246 return Qt::white;
|
Chris@376
|
247
|
Chris@376
|
248 case FruitSalad:
|
Chris@376
|
249 return Qt::white;
|
Chris@376
|
250
|
Chris@376
|
251 case Banded:
|
Chris@376
|
252 return Qt::cyan;
|
Chris@376
|
253
|
Chris@376
|
254 case Highlight:
|
Chris@376
|
255 return Qt::red;
|
Chris@376
|
256
|
Chris@376
|
257 case Printer:
|
Chris@376
|
258 return Qt::red;
|
Chris@536
|
259
|
Chris@536
|
260 case HighGain:
|
Chris@536
|
261 return Qt::red;
|
Chris@376
|
262 }
|
Chris@376
|
263
|
Chris@376
|
264 return Qt::white;
|
Chris@376
|
265 }
|
Chris@376
|
266
|
Chris@376
|
267 bool
|
Chris@376
|
268 ColourMapper::hasLightBackground() const
|
Chris@376
|
269 {
|
Chris@376
|
270 if (m_map >= getColourMapCount()) return false;
|
Chris@376
|
271 StandardMap map = (StandardMap)m_map;
|
Chris@376
|
272
|
Chris@376
|
273 switch (map) {
|
Chris@376
|
274
|
Chris@376
|
275 case BlackOnWhite:
|
Chris@376
|
276 case Printer:
|
Chris@536
|
277 case HighGain:
|
Chris@376
|
278 return true;
|
Chris@376
|
279
|
Chris@805
|
280 case DefaultColours:
|
Chris@805
|
281 case Sunset:
|
Chris@805
|
282 case WhiteOnBlack:
|
Chris@805
|
283 case RedOnBlue:
|
Chris@805
|
284 case YellowOnBlack:
|
Chris@805
|
285 case BlueOnBlack:
|
Chris@805
|
286 case FruitSalad:
|
Chris@805
|
287 case Banded:
|
Chris@805
|
288 case Highlight:
|
Chris@805
|
289
|
Chris@376
|
290 default:
|
Chris@376
|
291 return false;
|
Chris@376
|
292 }
|
Chris@376
|
293 }
|
Chris@376
|
294
|
Chris@376
|
295
|