comparison layer/ColourMapper.cpp @ 1374:631897ba9fca zoom

Merge from default branch
author Chris Cannam
date Tue, 06 Nov 2018 08:59:03 +0000
parents d79e21855aef
children c8a6fd3f9dff
comparison
equal deleted inserted replaced
1360:e848ea0850fe 1374:631897ba9fca
25 25
26 #include <QPainter> 26 #include <QPainter>
27 27
28 using namespace std; 28 using namespace std;
29 29
30 static vector<QColor> convertStrings(const vector<QString> &strs) 30 static vector<QColor> convertStrings(const vector<QString> &strs,
31 bool reversed)
31 { 32 {
32 vector<QColor> converted; 33 vector<QColor> converted;
33 for (const auto &s: strs) converted.push_back(QColor(s)); 34 for (const auto &s: strs) converted.push_back(QColor(s));
34 reverse(converted.begin(), converted.end()); 35 if (reversed) {
36 reverse(converted.begin(), converted.end());
37 }
35 return converted; 38 return converted;
36 } 39 }
37 40
38 static vector<QColor> ice = convertStrings({ 41 static vector<QColor> ice = convertStrings({
39 // Based on ColorBrewer ylGnBu 42 // Based on ColorBrewer ylGnBu
40 "#ffffff", "#ffff00", "#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5", 43 "#ffffff", "#ffff00", "#f7fcf0", "#e0f3db", "#ccebc5", "#a8ddb5",
41 "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081", "#042040" 44 "#7bccc4", "#4eb3d3", "#2b8cbe", "#0868ac", "#084081", "#042040"
42 }); 45 },
46 true);
43 47
44 static vector<QColor> cherry = convertStrings({ 48 static vector<QColor> cherry = convertStrings({
45 "#f7f7f7", "#fddbc7", "#f4a582", "#d6604d", "#b2182b", "#dd3497", 49 "#f7f7f7", "#fddbc7", "#f4a582", "#d6604d", "#b2182b", "#dd3497",
46 "#ae017e", "#7a0177", "#49006a" 50 "#ae017e", "#7a0177", "#49006a"
47 }); 51 },
48 52 true);
53
54 static vector<QColor> magma = convertStrings({
55 "#FCFFB2", "#FCDF96", "#FBC17D", "#FBA368", "#FA8657", "#F66B4D",
56 "#ED504A", "#E03B50", "#C92D59", "#B02363", "#981D69", "#81176D",
57 "#6B116F", "#57096E", "#43006A", "#300060", "#1E0848", "#110B2D",
58 "#080616", "#000005"
59 },
60 true);
61
62 static vector<QColor> cividis = convertStrings({
63 "#00204c", "#00204e", "#002150", "#002251", "#002353", "#002355",
64 "#002456", "#002558", "#00265a", "#00265b", "#00275d", "#00285f",
65 "#002861", "#002963", "#002a64", "#002a66", "#002b68", "#002c6a",
66 "#002d6c", "#002d6d", "#002e6e", "#002e6f", "#002f6f", "#002f6f",
67 "#00306f", "#00316f", "#00316f", "#00326e", "#00336e", "#00346e",
68 "#00346e", "#01356e", "#06366e", "#0a376d", "#0e376d", "#12386d",
69 "#15396d", "#17396d", "#1a3a6c", "#1c3b6c", "#1e3c6c", "#203c6c",
70 "#223d6c", "#243e6c", "#263e6c", "#273f6c", "#29406b", "#2b416b",
71 "#2c416b", "#2e426b", "#2f436b", "#31446b", "#32446b", "#33456b",
72 "#35466b", "#36466b", "#37476b", "#38486b", "#3a496b", "#3b496b",
73 "#3c4a6b", "#3d4b6b", "#3e4b6b", "#404c6b", "#414d6b", "#424e6b",
74 "#434e6b", "#444f6b", "#45506b", "#46506b", "#47516b", "#48526b",
75 "#49536b", "#4a536b", "#4b546b", "#4c556b", "#4d556b", "#4e566b",
76 "#4f576c", "#50586c", "#51586c", "#52596c", "#535a6c", "#545a6c",
77 "#555b6c", "#565c6c", "#575d6d", "#585d6d", "#595e6d", "#5a5f6d",
78 "#5b5f6d", "#5c606d", "#5d616e", "#5e626e", "#5f626e", "#5f636e",
79 "#60646e", "#61656f", "#62656f", "#63666f", "#64676f", "#65676f",
80 "#666870", "#676970", "#686a70", "#686a70", "#696b71", "#6a6c71",
81 "#6b6d71", "#6c6d72", "#6d6e72", "#6e6f72", "#6f6f72", "#6f7073",
82 "#707173", "#717273", "#727274", "#737374", "#747475", "#757575",
83 "#757575", "#767676", "#777776", "#787876", "#797877", "#7a7977",
84 "#7b7a77", "#7b7b78", "#7c7b78", "#7d7c78", "#7e7d78", "#7f7e78",
85 "#807e78", "#817f78", "#828078", "#838178", "#848178", "#858278",
86 "#868378", "#878478", "#888578", "#898578", "#8a8678", "#8b8778",
87 "#8c8878", "#8d8878", "#8e8978", "#8f8a78", "#908b78", "#918c78",
88 "#928c78", "#938d78", "#948e78", "#958f78", "#968f77", "#979077",
89 "#989177", "#999277", "#9a9377", "#9b9377", "#9c9477", "#9d9577",
90 "#9e9676", "#9f9776", "#a09876", "#a19876", "#a29976", "#a39a75",
91 "#a49b75", "#a59c75", "#a69c75", "#a79d75", "#a89e74", "#a99f74",
92 "#aaa074", "#aba174", "#aca173", "#ada273", "#aea373", "#afa473",
93 "#b0a572", "#b1a672", "#b2a672", "#b4a771", "#b5a871", "#b6a971",
94 "#b7aa70", "#b8ab70", "#b9ab70", "#baac6f", "#bbad6f", "#bcae6e",
95 "#bdaf6e", "#beb06e", "#bfb16d", "#c0b16d", "#c1b26c", "#c2b36c",
96 "#c3b46c", "#c5b56b", "#c6b66b", "#c7b76a", "#c8b86a", "#c9b869",
97 "#cab969", "#cbba68", "#ccbb68", "#cdbc67", "#cebd67", "#d0be66",
98 "#d1bf66", "#d2c065", "#d3c065", "#d4c164", "#d5c263", "#d6c363",
99 "#d7c462", "#d8c561", "#d9c661", "#dbc760", "#dcc860", "#ddc95f",
100 "#deca5e", "#dfcb5d", "#e0cb5d", "#e1cc5c", "#e3cd5b", "#e4ce5b",
101 "#e5cf5a", "#e6d059", "#e7d158", "#e8d257", "#e9d356", "#ebd456",
102 "#ecd555", "#edd654", "#eed753", "#efd852", "#f0d951", "#f1da50",
103 "#f3db4f", "#f4dc4e", "#f5dd4d", "#f6de4c", "#f7df4b", "#f9e049",
104 "#fae048", "#fbe147", "#fce246", "#fde345", "#ffe443", "#ffe542",
105 "#ffe642", "#ffe743", "#ffe844", "#ffe945"
106 },
107 false);
108
49 static void 109 static void
50 mapDiscrete(double norm, vector<QColor> &colours, double &r, double &g, double &b) 110 mapDiscrete(double norm, vector<QColor> &colours, double &r, double &g, double &b)
51 { 111 {
52 int n = int(colours.size()); 112 int n = int(colours.size());
53 double m = norm * (n-1); 113 double m = norm * (n-1);
59 r = c0.redF() * prop0 + c1.redF() * prop1; 119 r = c0.redF() * prop0 + c1.redF() * prop1;
60 g = c0.greenF() * prop0 + c1.greenF() * prop1; 120 g = c0.greenF() * prop0 + c1.greenF() * prop1;
61 b = c0.blueF() * prop0 + c1.blueF() * prop1; 121 b = c0.blueF() * prop0 + c1.blueF() * prop1;
62 } 122 }
63 123
64 ColourMapper::ColourMapper(int map, double min, double max) : 124 ColourMapper::ColourMapper(int map, bool inverted, double min, double max) :
65 m_map(map), 125 m_map(map),
126 m_inverted(inverted),
66 m_min(min), 127 m_min(min),
67 m_max(max) 128 m_max(max)
68 { 129 {
69 if (m_min == m_max) { 130 if (m_min == m_max) {
70 SVCERR << "WARNING: ColourMapper: min == max (== " << m_min 131 SVCERR << "WARNING: ColourMapper: min == max (== " << m_min
78 } 139 }
79 140
80 int 141 int
81 ColourMapper::getColourMapCount() 142 ColourMapper::getColourMapCount()
82 { 143 {
83 return 12; 144 return 15;
84 } 145 }
85 146
86 QString 147 QString
87 ColourMapper::getColourMapName(int n) 148 ColourMapper::getColourMapLabel(int n)
88 { 149 {
150 // When adding a map, be sure to also update getColourMapCount()
151
89 if (n >= getColourMapCount()) return QObject::tr("<unknown>"); 152 if (n >= getColourMapCount()) return QObject::tr("<unknown>");
90 StandardMap map = (StandardMap)n; 153 ColourMap map = (ColourMap)n;
91 154
92 switch (map) { 155 switch (map) {
93 case Green: return QObject::tr("Green"); 156 case Green: return QObject::tr("Green");
94 case WhiteOnBlack: return QObject::tr("White on Black"); 157 case WhiteOnBlack: return QObject::tr("White on Black");
95 case BlackOnWhite: return QObject::tr("Black on White"); 158 case BlackOnWhite: return QObject::tr("Black on White");
100 case FruitSalad: return QObject::tr("Fruit Salad"); 163 case FruitSalad: return QObject::tr("Fruit Salad");
101 case Banded: return QObject::tr("Banded"); 164 case Banded: return QObject::tr("Banded");
102 case Highlight: return QObject::tr("Highlight"); 165 case Highlight: return QObject::tr("Highlight");
103 case Printer: return QObject::tr("Printer"); 166 case Printer: return QObject::tr("Printer");
104 case HighGain: return QObject::tr("High Gain"); 167 case HighGain: return QObject::tr("High Gain");
168 case BlueOnBlack: return QObject::tr("Blue on Black");
169 case Cividis: return QObject::tr("Cividis");
170 case Magma: return QObject::tr("Magma");
105 } 171 }
106 172
107 return QObject::tr("<unknown>"); 173 return QObject::tr("<unknown>");
174 }
175
176 QString
177 ColourMapper::getColourMapId(int n)
178 {
179 if (n >= getColourMapCount()) return "<unknown>";
180 ColourMap map = (ColourMap)n;
181
182 switch (map) {
183 case Green: return "Green";
184 case WhiteOnBlack: return "White on Black";
185 case BlackOnWhite: return "Black on White";
186 case Cherry: return "Cherry";
187 case Wasp: return "Wasp";
188 case Ice: return "Ice";
189 case Sunset: return "Sunset";
190 case FruitSalad: return "Fruit Salad";
191 case Banded: return "Banded";
192 case Highlight: return "Highlight";
193 case Printer: return "Printer";
194 case HighGain: return "High Gain";
195 case BlueOnBlack: return "Blue on Black";
196 case Cividis: return "Cividis";
197 case Magma: return "Magma";
198 }
199
200 return "<unknown>";
201 }
202
203 int
204 ColourMapper::getColourMapById(QString id)
205 {
206 ColourMap map = (ColourMap)getColourMapCount();
207
208 if (id == "Green") { map = Green; }
209 else if (id == "White on Black") { map = WhiteOnBlack; }
210 else if (id == "Black on White") { map = BlackOnWhite; }
211 else if (id == "Cherry") { map = Cherry; }
212 else if (id == "Wasp") { map = Wasp; }
213 else if (id == "Ice") { map = Ice; }
214 else if (id == "Sunset") { map = Sunset; }
215 else if (id == "Fruit Salad") { map = FruitSalad; }
216 else if (id == "Banded") { map = Banded; }
217 else if (id == "Highlight") { map = Highlight; }
218 else if (id == "Printer") { map = Printer; }
219 else if (id == "High Gain") { map = HighGain; }
220 else if (id == "Blue on Black") { map = BlueOnBlack; }
221 else if (id == "Cividis") { map = Cividis; }
222 else if (id == "Magma") { map = Magma; }
223
224 if (map == (ColourMap)getColourMapCount()) {
225 return -1;
226 } else {
227 return int(map);
228 }
229 }
230
231 int
232 ColourMapper::getBackwardCompatibilityColourMap(int n)
233 {
234 /* Returned value should be an index into the series
235 * (Default/Green, Sunset, WhiteOnBlack, BlackOnWhite, RedOnBlue,
236 * YellowOnBlack, BlueOnBlack, FruitSalad, Banded, Highlight,
237 * Printer, HighGain). Minimum 0, maximum 11.
238 */
239
240 if (n >= getColourMapCount()) return 0;
241 ColourMap map = (ColourMap)n;
242
243 switch (map) {
244 case Green: return 0;
245 case WhiteOnBlack: return 2;
246 case BlackOnWhite: return 3;
247 case Cherry: return 4;
248 case Wasp: return 5;
249 case Ice: return 6;
250 case Sunset: return 1;
251 case FruitSalad: return 7;
252 case Banded: return 8;
253 case Highlight: return 9;
254 case Printer: return 10;
255 case HighGain: return 11;
256 case BlueOnBlack: return 6;
257 case Cividis: return 6;
258 case Magma: return 1;
259 }
260
261 return 0;
108 } 262 }
109 263
110 QColor 264 QColor
111 ColourMapper::map(double value) const 265 ColourMapper::map(double value) const
112 { 266 {
113 double norm = (value - m_min) / (m_max - m_min); 267 double norm = (value - m_min) / (m_max - m_min);
114 if (norm < 0.0) norm = 0.0; 268 if (norm < 0.0) norm = 0.0;
115 if (norm > 1.0) norm = 1.0; 269 if (norm > 1.0) norm = 1.0;
270
271 if (m_inverted) {
272 norm = 1.0 - norm;
273 }
116 274
117 double h = 0.0, s = 0.0, v = 0.0, r = 0.0, g = 0.0, b = 0.0; 275 double h = 0.0, s = 0.0, v = 0.0, r = 0.0, g = 0.0, b = 0.0;
118 bool hsv = true; 276 bool hsv = true;
119 277
120 double blue = 0.6666, pieslice = 0.3333; 278 double blue = 0.6666, pieslice = 0.3333;
121 279
122 if (m_map >= getColourMapCount()) return Qt::black; 280 if (m_map >= getColourMapCount()) return Qt::black;
123 StandardMap map = (StandardMap)m_map; 281 ColourMap map = (ColourMap)m_map;
124 282
125 switch (map) { 283 switch (map) {
126 284
127 case Green: 285 case Green:
128 h = blue - norm * 2.0 * pieslice; 286 h = blue - norm * 2.0 * pieslice;
147 305
148 case Wasp: 306 case Wasp:
149 h = 0.15; 307 h = 0.15;
150 s = 1.0; 308 s = 1.0;
151 v = norm; 309 v = norm;
310 break;
311
312 case BlueOnBlack:
313 h = blue;
314 s = 1.0;
315 v = norm * 2.0;
316 if (v > 1.0) {
317 v = 1.0;
318 s = 1.0 - (sqrt(norm) - 0.707) * 3.413;
319 if (s < 0.0) s = 0.0;
320 if (s > 1.0) s = 1.0;
321 }
152 break; 322 break;
153 323
154 case Sunset: 324 case Sunset:
155 r = (norm - 0.24) * 2.38; 325 r = (norm - 0.24) * 2.38;
156 if (r > 1.0) r = 1.0; 326 if (r > 1.0) r = 1.0;
235 break; 405 break;
236 406
237 case Ice: 407 case Ice:
238 hsv = false; 408 hsv = false;
239 mapDiscrete(norm, ice, r, g, b); 409 mapDiscrete(norm, ice, r, g, b);
410 break;
411
412 case Cividis:
413 hsv = false;
414 mapDiscrete(norm, cividis, r, g, b);
415 break;
416
417 case Magma:
418 hsv = false;
419 mapDiscrete(norm, magma, r, g, b);
420 break;
240 } 421 }
241 422
242 if (hsv) { 423 if (hsv) {
243 return QColor::fromHsvF(h, s, v); 424 return QColor::fromHsvF(h, s, v);
244 } else { 425 } else {
248 429
249 QColor 430 QColor
250 ColourMapper::getContrastingColour() const 431 ColourMapper::getContrastingColour() const
251 { 432 {
252 if (m_map >= getColourMapCount()) return Qt::white; 433 if (m_map >= getColourMapCount()) return Qt::white;
253 StandardMap map = (StandardMap)m_map; 434 ColourMap map = (ColourMap)m_map;
254 435
255 switch (map) { 436 switch (map) {
256 437
257 case Green: 438 case Green:
258 return QColor(255, 150, 50); 439 return QColor(255, 150, 50);
287 case Printer: 468 case Printer:
288 return Qt::red; 469 return Qt::red;
289 470
290 case HighGain: 471 case HighGain:
291 return Qt::red; 472 return Qt::red;
473
474 case BlueOnBlack:
475 return Qt::red;
476
477 case Cividis:
478 return Qt::white;
479
480 case Magma:
481 return Qt::white;
292 } 482 }
293 483
294 return Qt::white; 484 return Qt::white;
295 } 485 }
296 486
297 bool 487 bool
298 ColourMapper::hasLightBackground() const 488 ColourMapper::hasLightBackground() const
299 { 489 {
300 if (m_map >= getColourMapCount()) return false; 490 if (m_map >= getColourMapCount()) return false;
301 StandardMap map = (StandardMap)m_map; 491 ColourMap map = (ColourMap)m_map;
302 492
303 switch (map) { 493 switch (map) {
304 494
305 case BlackOnWhite: 495 case BlackOnWhite:
306 case Printer: 496 case Printer:
314 case Wasp: 504 case Wasp:
315 case Ice: 505 case Ice:
316 case FruitSalad: 506 case FruitSalad:
317 case Banded: 507 case Banded:
318 case Highlight: 508 case Highlight:
509 case BlueOnBlack:
510 case Cividis:
511 case Magma:
319 512
320 default: 513 default:
321 return false; 514 return false;
322 } 515 }
323 } 516 }