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@1199
|
7 This file copyright 2006-2016 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@1012
|
24 #include <vector>
|
Chris@1012
|
25
|
Chris@1199
|
26 #include <QPainter>
|
Chris@1199
|
27
|
Chris@1012
|
28 using namespace std;
|
Chris@1012
|
29
|
Chris@1362
|
30 static vector<QColor> convertStrings(const vector<QString> &strs,
|
Chris@1362
|
31 bool reversed)
|
Chris@1012
|
32 {
|
Chris@1012
|
33 vector<QColor> converted;
|
Chris@1012
|
34 for (const auto &s: strs) converted.push_back(QColor(s));
|
Chris@1362
|
35 if (reversed) {
|
Chris@1362
|
36 reverse(converted.begin(), converted.end());
|
Chris@1362
|
37 }
|
Chris@1012
|
38 return converted;
|
Chris@1012
|
39 }
|
Chris@1012
|
40
|
Chris@1017
|
41 static vector<QColor> ice = convertStrings({
|
Chris@1015
|
42 // Based on ColorBrewer ylGnBu
|
Chris@1015
|
43 "#ffffff", "#ffff00", "#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5",
|
Chris@1015
|
44 "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081", "#042040"
|
Chris@1362
|
45 },
|
Chris@1362
|
46 true);
|
Chris@1012
|
47
|
Chris@1017
|
48 static vector<QColor> cherry = convertStrings({
|
Chris@1016
|
49 "#f7f7f7", "#fddbc7", "#f4a582", "#d6604d", "#b2182b", "#dd3497",
|
Chris@1016
|
50 "#ae017e", "#7a0177", "#49006a"
|
Chris@1362
|
51 },
|
Chris@1362
|
52 true);
|
Chris@1362
|
53
|
Chris@1362
|
54 static vector<QColor> magma = convertStrings({
|
Chris@1362
|
55 "#FCFFB2", "#FCDF96", "#FBC17D", "#FBA368", "#FA8657", "#F66B4D",
|
Chris@1362
|
56 "#ED504A", "#E03B50", "#C92D59", "#B02363", "#981D69", "#81176D",
|
Chris@1362
|
57 "#6B116F", "#57096E", "#43006A", "#300060", "#1E0848", "#110B2D",
|
Chris@1362
|
58 "#080616", "#000005"
|
Chris@1362
|
59 },
|
Chris@1362
|
60 true);
|
Chris@1362
|
61
|
Chris@1362
|
62 static vector<QColor> cividis = convertStrings({
|
Chris@1362
|
63 "#00204c", "#00204e", "#002150", "#002251", "#002353", "#002355",
|
Chris@1362
|
64 "#002456", "#002558", "#00265a", "#00265b", "#00275d", "#00285f",
|
Chris@1362
|
65 "#002861", "#002963", "#002a64", "#002a66", "#002b68", "#002c6a",
|
Chris@1362
|
66 "#002d6c", "#002d6d", "#002e6e", "#002e6f", "#002f6f", "#002f6f",
|
Chris@1362
|
67 "#00306f", "#00316f", "#00316f", "#00326e", "#00336e", "#00346e",
|
Chris@1362
|
68 "#00346e", "#01356e", "#06366e", "#0a376d", "#0e376d", "#12386d",
|
Chris@1362
|
69 "#15396d", "#17396d", "#1a3a6c", "#1c3b6c", "#1e3c6c", "#203c6c",
|
Chris@1362
|
70 "#223d6c", "#243e6c", "#263e6c", "#273f6c", "#29406b", "#2b416b",
|
Chris@1362
|
71 "#2c416b", "#2e426b", "#2f436b", "#31446b", "#32446b", "#33456b",
|
Chris@1362
|
72 "#35466b", "#36466b", "#37476b", "#38486b", "#3a496b", "#3b496b",
|
Chris@1362
|
73 "#3c4a6b", "#3d4b6b", "#3e4b6b", "#404c6b", "#414d6b", "#424e6b",
|
Chris@1362
|
74 "#434e6b", "#444f6b", "#45506b", "#46506b", "#47516b", "#48526b",
|
Chris@1362
|
75 "#49536b", "#4a536b", "#4b546b", "#4c556b", "#4d556b", "#4e566b",
|
Chris@1362
|
76 "#4f576c", "#50586c", "#51586c", "#52596c", "#535a6c", "#545a6c",
|
Chris@1362
|
77 "#555b6c", "#565c6c", "#575d6d", "#585d6d", "#595e6d", "#5a5f6d",
|
Chris@1362
|
78 "#5b5f6d", "#5c606d", "#5d616e", "#5e626e", "#5f626e", "#5f636e",
|
Chris@1362
|
79 "#60646e", "#61656f", "#62656f", "#63666f", "#64676f", "#65676f",
|
Chris@1362
|
80 "#666870", "#676970", "#686a70", "#686a70", "#696b71", "#6a6c71",
|
Chris@1362
|
81 "#6b6d71", "#6c6d72", "#6d6e72", "#6e6f72", "#6f6f72", "#6f7073",
|
Chris@1362
|
82 "#707173", "#717273", "#727274", "#737374", "#747475", "#757575",
|
Chris@1362
|
83 "#757575", "#767676", "#777776", "#787876", "#797877", "#7a7977",
|
Chris@1362
|
84 "#7b7a77", "#7b7b78", "#7c7b78", "#7d7c78", "#7e7d78", "#7f7e78",
|
Chris@1362
|
85 "#807e78", "#817f78", "#828078", "#838178", "#848178", "#858278",
|
Chris@1362
|
86 "#868378", "#878478", "#888578", "#898578", "#8a8678", "#8b8778",
|
Chris@1362
|
87 "#8c8878", "#8d8878", "#8e8978", "#8f8a78", "#908b78", "#918c78",
|
Chris@1362
|
88 "#928c78", "#938d78", "#948e78", "#958f78", "#968f77", "#979077",
|
Chris@1362
|
89 "#989177", "#999277", "#9a9377", "#9b9377", "#9c9477", "#9d9577",
|
Chris@1362
|
90 "#9e9676", "#9f9776", "#a09876", "#a19876", "#a29976", "#a39a75",
|
Chris@1362
|
91 "#a49b75", "#a59c75", "#a69c75", "#a79d75", "#a89e74", "#a99f74",
|
Chris@1362
|
92 "#aaa074", "#aba174", "#aca173", "#ada273", "#aea373", "#afa473",
|
Chris@1362
|
93 "#b0a572", "#b1a672", "#b2a672", "#b4a771", "#b5a871", "#b6a971",
|
Chris@1362
|
94 "#b7aa70", "#b8ab70", "#b9ab70", "#baac6f", "#bbad6f", "#bcae6e",
|
Chris@1362
|
95 "#bdaf6e", "#beb06e", "#bfb16d", "#c0b16d", "#c1b26c", "#c2b36c",
|
Chris@1362
|
96 "#c3b46c", "#c5b56b", "#c6b66b", "#c7b76a", "#c8b86a", "#c9b869",
|
Chris@1362
|
97 "#cab969", "#cbba68", "#ccbb68", "#cdbc67", "#cebd67", "#d0be66",
|
Chris@1362
|
98 "#d1bf66", "#d2c065", "#d3c065", "#d4c164", "#d5c263", "#d6c363",
|
Chris@1362
|
99 "#d7c462", "#d8c561", "#d9c661", "#dbc760", "#dcc860", "#ddc95f",
|
Chris@1362
|
100 "#deca5e", "#dfcb5d", "#e0cb5d", "#e1cc5c", "#e3cd5b", "#e4ce5b",
|
Chris@1362
|
101 "#e5cf5a", "#e6d059", "#e7d158", "#e8d257", "#e9d356", "#ebd456",
|
Chris@1362
|
102 "#ecd555", "#edd654", "#eed753", "#efd852", "#f0d951", "#f1da50",
|
Chris@1362
|
103 "#f3db4f", "#f4dc4e", "#f5dd4d", "#f6de4c", "#f7df4b", "#f9e049",
|
Chris@1362
|
104 "#fae048", "#fbe147", "#fce246", "#fde345", "#ffe443", "#ffe542",
|
Chris@1362
|
105 "#ffe642", "#ffe743", "#ffe844", "#ffe945"
|
Chris@1362
|
106 },
|
Chris@1362
|
107 false);
|
Chris@1362
|
108
|
Chris@1012
|
109 static void
|
Chris@1012
|
110 mapDiscrete(double norm, vector<QColor> &colours, double &r, double &g, double &b)
|
Chris@1012
|
111 {
|
Chris@1015
|
112 int n = int(colours.size());
|
Chris@1012
|
113 double m = norm * (n-1);
|
Chris@1408
|
114 if (m >= n-1) { colours[n-1].getRgbF(&r, &g, &b, nullptr); return; }
|
Chris@1408
|
115 if (m <= 0) { colours[0].getRgbF(&r, &g, &b, nullptr); return; }
|
Chris@1012
|
116 int base(int(floor(m)));
|
Chris@1012
|
117 double prop0 = (base + 1.0) - m, prop1 = m - base;
|
Chris@1012
|
118 QColor c0(colours[base]), c1(colours[base+1]);
|
Chris@1012
|
119 r = c0.redF() * prop0 + c1.redF() * prop1;
|
Chris@1012
|
120 g = c0.greenF() * prop0 + c1.greenF() * prop1;
|
Chris@1012
|
121 b = c0.blueF() * prop0 + c1.blueF() * prop1;
|
Chris@1012
|
122 }
|
Chris@1012
|
123
|
Chris@1362
|
124 ColourMapper::ColourMapper(int map, bool inverted, double min, double max) :
|
Chris@376
|
125 m_map(map),
|
Chris@1362
|
126 m_inverted(inverted),
|
Chris@376
|
127 m_min(min),
|
Chris@376
|
128 m_max(max)
|
Chris@376
|
129 {
|
Chris@376
|
130 if (m_min == m_max) {
|
Chris@1265
|
131 SVCERR << "WARNING: ColourMapper: min == max (== " << m_min
|
Chris@682
|
132 << "), adjusting" << endl;
|
Chris@376
|
133 m_max = m_min + 1;
|
Chris@376
|
134 }
|
Chris@376
|
135 }
|
Chris@376
|
136
|
Chris@376
|
137 ColourMapper::~ColourMapper()
|
Chris@376
|
138 {
|
Chris@376
|
139 }
|
Chris@376
|
140
|
Chris@376
|
141 int
|
Chris@376
|
142 ColourMapper::getColourMapCount()
|
Chris@376
|
143 {
|
Chris@1362
|
144 return 15;
|
Chris@376
|
145 }
|
Chris@376
|
146
|
Chris@376
|
147 QString
|
Chris@1362
|
148 ColourMapper::getColourMapLabel(int n)
|
Chris@376
|
149 {
|
Chris@1362
|
150 // When adding a map, be sure to also update getColourMapCount()
|
Chris@1362
|
151
|
Chris@1071
|
152 if (n >= getColourMapCount()) return QObject::tr("<unknown>");
|
Chris@1362
|
153 ColourMap map = (ColourMap)n;
|
Chris@376
|
154
|
Chris@376
|
155 switch (map) {
|
Chris@1071
|
156 case Green: return QObject::tr("Green");
|
Chris@1071
|
157 case WhiteOnBlack: return QObject::tr("White on Black");
|
Chris@1071
|
158 case BlackOnWhite: return QObject::tr("Black on White");
|
Chris@1071
|
159 case Cherry: return QObject::tr("Cherry");
|
Chris@1071
|
160 case Wasp: return QObject::tr("Wasp");
|
Chris@1071
|
161 case Ice: return QObject::tr("Ice");
|
Chris@1071
|
162 case Sunset: return QObject::tr("Sunset");
|
Chris@1071
|
163 case FruitSalad: return QObject::tr("Fruit Salad");
|
Chris@1071
|
164 case Banded: return QObject::tr("Banded");
|
Chris@1071
|
165 case Highlight: return QObject::tr("Highlight");
|
Chris@1071
|
166 case Printer: return QObject::tr("Printer");
|
Chris@1071
|
167 case HighGain: return QObject::tr("High Gain");
|
Chris@1362
|
168 case BlueOnBlack: return QObject::tr("Blue on Black");
|
Chris@1362
|
169 case Cividis: return QObject::tr("Cividis");
|
Chris@1362
|
170 case Magma: return QObject::tr("Magma");
|
Chris@376
|
171 }
|
Chris@376
|
172
|
Chris@1071
|
173 return QObject::tr("<unknown>");
|
Chris@376
|
174 }
|
Chris@376
|
175
|
Chris@1362
|
176 QString
|
Chris@1362
|
177 ColourMapper::getColourMapId(int n)
|
Chris@1362
|
178 {
|
Chris@1362
|
179 if (n >= getColourMapCount()) return "<unknown>";
|
Chris@1362
|
180 ColourMap map = (ColourMap)n;
|
Chris@1362
|
181
|
Chris@1362
|
182 switch (map) {
|
Chris@1362
|
183 case Green: return "Green";
|
Chris@1362
|
184 case WhiteOnBlack: return "White on Black";
|
Chris@1362
|
185 case BlackOnWhite: return "Black on White";
|
Chris@1362
|
186 case Cherry: return "Cherry";
|
Chris@1362
|
187 case Wasp: return "Wasp";
|
Chris@1362
|
188 case Ice: return "Ice";
|
Chris@1362
|
189 case Sunset: return "Sunset";
|
Chris@1362
|
190 case FruitSalad: return "Fruit Salad";
|
Chris@1362
|
191 case Banded: return "Banded";
|
Chris@1362
|
192 case Highlight: return "Highlight";
|
Chris@1362
|
193 case Printer: return "Printer";
|
Chris@1362
|
194 case HighGain: return "High Gain";
|
Chris@1362
|
195 case BlueOnBlack: return "Blue on Black";
|
Chris@1362
|
196 case Cividis: return "Cividis";
|
Chris@1362
|
197 case Magma: return "Magma";
|
Chris@1362
|
198 }
|
Chris@1362
|
199
|
Chris@1362
|
200 return "<unknown>";
|
Chris@1362
|
201 }
|
Chris@1362
|
202
|
Chris@1362
|
203 int
|
Chris@1362
|
204 ColourMapper::getColourMapById(QString id)
|
Chris@1362
|
205 {
|
Chris@1362
|
206 ColourMap map = (ColourMap)getColourMapCount();
|
Chris@1362
|
207
|
Chris@1362
|
208 if (id == "Green") { map = Green; }
|
Chris@1362
|
209 else if (id == "White on Black") { map = WhiteOnBlack; }
|
Chris@1362
|
210 else if (id == "Black on White") { map = BlackOnWhite; }
|
Chris@1362
|
211 else if (id == "Cherry") { map = Cherry; }
|
Chris@1362
|
212 else if (id == "Wasp") { map = Wasp; }
|
Chris@1362
|
213 else if (id == "Ice") { map = Ice; }
|
Chris@1362
|
214 else if (id == "Sunset") { map = Sunset; }
|
Chris@1362
|
215 else if (id == "Fruit Salad") { map = FruitSalad; }
|
Chris@1362
|
216 else if (id == "Banded") { map = Banded; }
|
Chris@1362
|
217 else if (id == "Highlight") { map = Highlight; }
|
Chris@1362
|
218 else if (id == "Printer") { map = Printer; }
|
Chris@1362
|
219 else if (id == "High Gain") { map = HighGain; }
|
Chris@1362
|
220 else if (id == "Blue on Black") { map = BlueOnBlack; }
|
Chris@1362
|
221 else if (id == "Cividis") { map = Cividis; }
|
Chris@1362
|
222 else if (id == "Magma") { map = Magma; }
|
Chris@1362
|
223
|
Chris@1362
|
224 if (map == (ColourMap)getColourMapCount()) {
|
Chris@1362
|
225 return -1;
|
Chris@1362
|
226 } else {
|
Chris@1362
|
227 return int(map);
|
Chris@1362
|
228 }
|
Chris@1362
|
229 }
|
Chris@1362
|
230
|
Chris@1362
|
231 int
|
Chris@1362
|
232 ColourMapper::getBackwardCompatibilityColourMap(int n)
|
Chris@1362
|
233 {
|
Chris@1362
|
234 /* Returned value should be an index into the series
|
Chris@1362
|
235 * (Default/Green, Sunset, WhiteOnBlack, BlackOnWhite, RedOnBlue,
|
Chris@1362
|
236 * YellowOnBlack, BlueOnBlack, FruitSalad, Banded, Highlight,
|
Chris@1362
|
237 * Printer, HighGain). Minimum 0, maximum 11.
|
Chris@1362
|
238 */
|
Chris@1362
|
239
|
Chris@1362
|
240 if (n >= getColourMapCount()) return 0;
|
Chris@1362
|
241 ColourMap map = (ColourMap)n;
|
Chris@1362
|
242
|
Chris@1362
|
243 switch (map) {
|
Chris@1362
|
244 case Green: return 0;
|
Chris@1362
|
245 case WhiteOnBlack: return 2;
|
Chris@1362
|
246 case BlackOnWhite: return 3;
|
Chris@1362
|
247 case Cherry: return 4;
|
Chris@1362
|
248 case Wasp: return 5;
|
Chris@1362
|
249 case Ice: return 6;
|
Chris@1362
|
250 case Sunset: return 1;
|
Chris@1362
|
251 case FruitSalad: return 7;
|
Chris@1362
|
252 case Banded: return 8;
|
Chris@1362
|
253 case Highlight: return 9;
|
Chris@1362
|
254 case Printer: return 10;
|
Chris@1362
|
255 case HighGain: return 11;
|
Chris@1362
|
256 case BlueOnBlack: return 6;
|
Chris@1362
|
257 case Cividis: return 6;
|
Chris@1362
|
258 case Magma: return 1;
|
Chris@1362
|
259 }
|
Chris@1362
|
260
|
Chris@1362
|
261 return 0;
|
Chris@1362
|
262 }
|
Chris@1362
|
263
|
Chris@376
|
264 QColor
|
Chris@902
|
265 ColourMapper::map(double value) const
|
Chris@376
|
266 {
|
Chris@902
|
267 double norm = (value - m_min) / (m_max - m_min);
|
Chris@902
|
268 if (norm < 0.0) norm = 0.0;
|
Chris@902
|
269 if (norm > 1.0) norm = 1.0;
|
Chris@1362
|
270
|
Chris@1362
|
271 if (m_inverted) {
|
Chris@1362
|
272 norm = 1.0 - norm;
|
Chris@1362
|
273 }
|
Chris@376
|
274
|
Chris@902
|
275 double h = 0.0, s = 0.0, v = 0.0, r = 0.0, g = 0.0, b = 0.0;
|
Chris@376
|
276 bool hsv = true;
|
Chris@376
|
277
|
Chris@911
|
278 double blue = 0.6666, pieslice = 0.3333;
|
Chris@376
|
279
|
Chris@376
|
280 if (m_map >= getColourMapCount()) return Qt::black;
|
Chris@1362
|
281 ColourMap map = (ColourMap)m_map;
|
Chris@376
|
282
|
Chris@376
|
283 switch (map) {
|
Chris@376
|
284
|
Chris@1017
|
285 case Green:
|
Chris@902
|
286 h = blue - norm * 2.0 * pieslice;
|
Chris@902
|
287 s = 0.5f + norm/2.0;
|
Chris@376
|
288 v = norm;
|
Chris@376
|
289 break;
|
Chris@376
|
290
|
Chris@376
|
291 case WhiteOnBlack:
|
Chris@376
|
292 r = g = b = norm;
|
Chris@376
|
293 hsv = false;
|
Chris@376
|
294 break;
|
Chris@376
|
295
|
Chris@376
|
296 case BlackOnWhite:
|
Chris@902
|
297 r = g = b = 1.0 - norm;
|
Chris@376
|
298 hsv = false;
|
Chris@376
|
299 break;
|
Chris@376
|
300
|
Chris@1017
|
301 case Cherry:
|
Chris@1015
|
302 hsv = false;
|
Chris@1017
|
303 mapDiscrete(norm, cherry, r, g, b);
|
Chris@376
|
304 break;
|
Chris@376
|
305
|
Chris@1017
|
306 case Wasp:
|
Chris@902
|
307 h = 0.15;
|
Chris@902
|
308 s = 1.0;
|
Chris@376
|
309 v = norm;
|
Chris@376
|
310 break;
|
Chris@1362
|
311
|
Chris@1362
|
312 case BlueOnBlack:
|
Chris@1362
|
313 h = blue;
|
Chris@1362
|
314 s = 1.0;
|
Chris@1362
|
315 v = norm * 2.0;
|
Chris@1362
|
316 if (v > 1.0) {
|
Chris@1362
|
317 v = 1.0;
|
Chris@1362
|
318 s = 1.0 - (sqrt(norm) - 0.707) * 3.413;
|
Chris@1362
|
319 if (s < 0.0) s = 0.0;
|
Chris@1362
|
320 if (s > 1.0) s = 1.0;
|
Chris@1362
|
321 }
|
Chris@1362
|
322 break;
|
Chris@376
|
323
|
Chris@376
|
324 case Sunset:
|
Chris@902
|
325 r = (norm - 0.24) * 2.38;
|
Chris@902
|
326 if (r > 1.0) r = 1.0;
|
Chris@902
|
327 if (r < 0.0) r = 0.0;
|
Chris@902
|
328 g = (norm - 0.64) * 2.777;
|
Chris@902
|
329 if (g > 1.0) g = 1.0;
|
Chris@902
|
330 if (g < 0.0) g = 0.0;
|
Chris@376
|
331 b = (3.6f * norm);
|
Chris@902
|
332 if (norm > 0.277) b = 2.0 - b;
|
Chris@902
|
333 if (b > 1.0) b = 1.0;
|
Chris@902
|
334 if (b < 0.0) b = 0.0;
|
Chris@376
|
335 hsv = false;
|
Chris@376
|
336 break;
|
Chris@376
|
337
|
Chris@376
|
338 case FruitSalad:
|
Chris@902
|
339 h = blue + (pieslice/6.0) - norm;
|
Chris@902
|
340 if (h < 0.0) h += 1.0;
|
Chris@902
|
341 s = 1.0;
|
Chris@902
|
342 v = 1.0;
|
Chris@376
|
343 break;
|
Chris@376
|
344
|
Chris@376
|
345 case Banded:
|
Chris@376
|
346 if (norm < 0.125) return Qt::darkGreen;
|
Chris@376
|
347 else if (norm < 0.25) return Qt::green;
|
Chris@376
|
348 else if (norm < 0.375) return Qt::darkBlue;
|
Chris@376
|
349 else if (norm < 0.5) return Qt::blue;
|
Chris@376
|
350 else if (norm < 0.625) return Qt::darkYellow;
|
Chris@376
|
351 else if (norm < 0.75) return Qt::yellow;
|
Chris@376
|
352 else if (norm < 0.875) return Qt::darkRed;
|
Chris@376
|
353 else return Qt::red;
|
Chris@376
|
354 break;
|
Chris@376
|
355
|
Chris@376
|
356 case Highlight:
|
Chris@376
|
357 if (norm > 0.99) return Qt::white;
|
Chris@376
|
358 else return Qt::darkBlue;
|
Chris@376
|
359
|
Chris@376
|
360 case Printer:
|
Chris@376
|
361 if (norm > 0.8) {
|
Chris@902
|
362 r = 1.0;
|
Chris@376
|
363 } else if (norm > 0.7) {
|
Chris@902
|
364 r = 0.9;
|
Chris@376
|
365 } else if (norm > 0.6) {
|
Chris@902
|
366 r = 0.8;
|
Chris@376
|
367 } else if (norm > 0.5) {
|
Chris@902
|
368 r = 0.7;
|
Chris@376
|
369 } else if (norm > 0.4) {
|
Chris@902
|
370 r = 0.6;
|
Chris@376
|
371 } else if (norm > 0.3) {
|
Chris@902
|
372 r = 0.5;
|
Chris@376
|
373 } else if (norm > 0.2) {
|
Chris@902
|
374 r = 0.4;
|
Chris@376
|
375 } else {
|
Chris@902
|
376 r = 0.0;
|
Chris@376
|
377 }
|
Chris@902
|
378 r = g = b = 1.0 - r;
|
Chris@376
|
379 hsv = false;
|
Chris@376
|
380 break;
|
Chris@536
|
381
|
Chris@536
|
382 case HighGain:
|
Chris@902
|
383 if (norm <= 1.0 / 256.0) {
|
Chris@902
|
384 norm = 0.0;
|
Chris@536
|
385 } else {
|
Chris@904
|
386 norm = 0.1f + (pow(((norm - 0.5) * 2.0), 3.0) + 1.0) / 2.081;
|
Chris@536
|
387 }
|
Chris@536
|
388 // now as for Sunset
|
Chris@902
|
389 r = (norm - 0.24) * 2.38;
|
Chris@902
|
390 if (r > 1.0) r = 1.0;
|
Chris@902
|
391 if (r < 0.0) r = 0.0;
|
Chris@902
|
392 g = (norm - 0.64) * 2.777;
|
Chris@902
|
393 if (g > 1.0) g = 1.0;
|
Chris@902
|
394 if (g < 0.0) g = 0.0;
|
Chris@536
|
395 b = (3.6f * norm);
|
Chris@902
|
396 if (norm > 0.277) b = 2.0 - b;
|
Chris@902
|
397 if (b > 1.0) b = 1.0;
|
Chris@902
|
398 if (b < 0.0) b = 0.0;
|
Chris@536
|
399 hsv = false;
|
Chris@536
|
400 /*
|
Chris@902
|
401 if (r > 1.0) r = 1.0;
|
Chris@902
|
402 r = g = b = 1.0 - r;
|
Chris@536
|
403 hsv = false;
|
Chris@536
|
404 */
|
Chris@536
|
405 break;
|
Chris@1012
|
406
|
Chris@1017
|
407 case Ice:
|
Chris@1012
|
408 hsv = false;
|
Chris@1017
|
409 mapDiscrete(norm, ice, r, g, b);
|
Chris@1362
|
410 break;
|
Chris@1362
|
411
|
Chris@1362
|
412 case Cividis:
|
Chris@1362
|
413 hsv = false;
|
Chris@1362
|
414 mapDiscrete(norm, cividis, r, g, b);
|
Chris@1362
|
415 break;
|
Chris@1362
|
416
|
Chris@1362
|
417 case Magma:
|
Chris@1362
|
418 hsv = false;
|
Chris@1362
|
419 mapDiscrete(norm, magma, r, g, b);
|
Chris@1362
|
420 break;
|
Chris@376
|
421 }
|
Chris@376
|
422
|
Chris@376
|
423 if (hsv) {
|
Chris@376
|
424 return QColor::fromHsvF(h, s, v);
|
Chris@376
|
425 } else {
|
Chris@376
|
426 return QColor::fromRgbF(r, g, b);
|
Chris@376
|
427 }
|
Chris@376
|
428 }
|
Chris@376
|
429
|
Chris@376
|
430 QColor
|
Chris@376
|
431 ColourMapper::getContrastingColour() const
|
Chris@376
|
432 {
|
Chris@376
|
433 if (m_map >= getColourMapCount()) return Qt::white;
|
Chris@1362
|
434 ColourMap map = (ColourMap)m_map;
|
Chris@376
|
435
|
Chris@376
|
436 switch (map) {
|
Chris@376
|
437
|
Chris@1017
|
438 case Green:
|
Chris@376
|
439 return QColor(255, 150, 50);
|
Chris@376
|
440
|
Chris@376
|
441 case WhiteOnBlack:
|
Chris@376
|
442 return Qt::red;
|
Chris@376
|
443
|
Chris@376
|
444 case BlackOnWhite:
|
Chris@376
|
445 return Qt::darkGreen;
|
Chris@376
|
446
|
Chris@1017
|
447 case Cherry:
|
Chris@376
|
448 return Qt::green;
|
Chris@376
|
449
|
Chris@1017
|
450 case Wasp:
|
Chris@376
|
451 return QColor::fromHsv(240, 255, 255);
|
Chris@376
|
452
|
Chris@1017
|
453 case Ice:
|
Chris@376
|
454 return Qt::red;
|
Chris@376
|
455
|
Chris@376
|
456 case Sunset:
|
Chris@376
|
457 return Qt::white;
|
Chris@376
|
458
|
Chris@376
|
459 case FruitSalad:
|
Chris@376
|
460 return Qt::white;
|
Chris@376
|
461
|
Chris@376
|
462 case Banded:
|
Chris@376
|
463 return Qt::cyan;
|
Chris@376
|
464
|
Chris@376
|
465 case Highlight:
|
Chris@376
|
466 return Qt::red;
|
Chris@376
|
467
|
Chris@376
|
468 case Printer:
|
Chris@376
|
469 return Qt::red;
|
Chris@536
|
470
|
Chris@536
|
471 case HighGain:
|
Chris@536
|
472 return Qt::red;
|
Chris@1362
|
473
|
Chris@1362
|
474 case BlueOnBlack:
|
Chris@1362
|
475 return Qt::red;
|
Chris@1362
|
476
|
Chris@1362
|
477 case Cividis:
|
Chris@1362
|
478 return Qt::white;
|
Chris@1362
|
479
|
Chris@1362
|
480 case Magma:
|
Chris@1362
|
481 return Qt::white;
|
Chris@376
|
482 }
|
Chris@376
|
483
|
Chris@376
|
484 return Qt::white;
|
Chris@376
|
485 }
|
Chris@376
|
486
|
Chris@376
|
487 bool
|
Chris@376
|
488 ColourMapper::hasLightBackground() const
|
Chris@376
|
489 {
|
Chris@376
|
490 if (m_map >= getColourMapCount()) return false;
|
Chris@1362
|
491 ColourMap map = (ColourMap)m_map;
|
Chris@376
|
492
|
Chris@376
|
493 switch (map) {
|
Chris@376
|
494
|
Chris@376
|
495 case BlackOnWhite:
|
Chris@376
|
496 case Printer:
|
Chris@536
|
497 case HighGain:
|
Chris@376
|
498 return true;
|
Chris@376
|
499
|
Chris@1017
|
500 case Green:
|
Chris@805
|
501 case Sunset:
|
Chris@805
|
502 case WhiteOnBlack:
|
Chris@1017
|
503 case Cherry:
|
Chris@1017
|
504 case Wasp:
|
Chris@1017
|
505 case Ice:
|
Chris@805
|
506 case FruitSalad:
|
Chris@805
|
507 case Banded:
|
Chris@805
|
508 case Highlight:
|
Chris@1362
|
509 case BlueOnBlack:
|
Chris@1362
|
510 case Cividis:
|
Chris@1362
|
511 case Magma:
|
Chris@805
|
512
|
Chris@376
|
513 default:
|
Chris@376
|
514 return false;
|
Chris@376
|
515 }
|
Chris@376
|
516 }
|
Chris@376
|
517
|
Chris@1199
|
518 QPixmap
|
Chris@1199
|
519 ColourMapper::getExamplePixmap(QSize size) const
|
Chris@1199
|
520 {
|
Chris@1199
|
521 QPixmap pmap(size);
|
Chris@1199
|
522 pmap.fill(Qt::white);
|
Chris@1199
|
523 QPainter paint(&pmap);
|
Chris@376
|
524
|
Chris@1199
|
525 int w = size.width(), h = size.height();
|
Chris@1199
|
526
|
Chris@1199
|
527 int margin = 2;
|
Chris@1199
|
528 if (w < 4 || h < 4) margin = 0;
|
Chris@1199
|
529 else if (w < 8 || h < 8) margin = 1;
|
Chris@1199
|
530
|
Chris@1199
|
531 int n = w - margin*2;
|
Chris@1199
|
532
|
Chris@1199
|
533 for (int x = 0; x < n; ++x) {
|
Chris@1199
|
534 double value = m_min + ((m_max - m_min) * x) / (n-1);
|
Chris@1199
|
535 QColor colour(map(value));
|
Chris@1199
|
536 paint.setPen(colour);
|
Chris@1199
|
537 paint.drawLine(x + margin, margin, x + margin, h - margin);
|
Chris@1199
|
538 }
|
Chris@1199
|
539
|
Chris@1199
|
540 return pmap;
|
Chris@1199
|
541 }
|
Chris@1199
|
542
|
Chris@1199
|
543
|