annotate layer/ColourMapper.cpp @ 1014:6338d7dc3b6d colourschemes

Remove debug out
author Chris Cannam
date Tue, 19 Jan 2016 13:02:32 +0000
parents ac69043f82b6
children 352fa17af9f0
rev   line source
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@1012 24 #include <vector>
Chris@1012 25
Chris@1012 26 using namespace std;
Chris@1012 27
Chris@1012 28 static vector<QColor> convertStrings(const vector<QString> &strs)
Chris@1012 29 {
Chris@1012 30 vector<QColor> converted;
Chris@1012 31 for (const auto &s: strs) converted.push_back(QColor(s));
Chris@1012 32 reverse(converted.begin(), converted.end());
Chris@1012 33 return converted;
Chris@1012 34 }
Chris@1012 35
Chris@1013 36 static vector<QColor> xRay = convertStrings({
Chris@1013 37 // Based on ColorBrewer ylGnBu scale
Chris@1013 38 "#ffffff", "#ffff00", "#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081","#042040"
Chris@1013 39 });
Chris@1012 40
Chris@1012 41 static void
Chris@1012 42 mapDiscrete(double norm, vector<QColor> &colours, double &r, double &g, double &b)
Chris@1012 43 {
Chris@1012 44 int n = colours.size();
Chris@1012 45 double m = norm * (n-1);
Chris@1012 46 if (m >= n-1) { colours[n-1].getRgbF(&r, &g, &b, 0); return; }
Chris@1012 47 if (m <= 0) { colours[0].getRgbF(&r, &g, &b, 0); return; }
Chris@1012 48 int base(int(floor(m)));
Chris@1012 49 double prop0 = (base + 1.0) - m, prop1 = m - base;
Chris@1012 50 QColor c0(colours[base]), c1(colours[base+1]);
Chris@1012 51 r = c0.redF() * prop0 + c1.redF() * prop1;
Chris@1012 52 g = c0.greenF() * prop0 + c1.greenF() * prop1;
Chris@1012 53 b = c0.blueF() * prop0 + c1.blueF() * prop1;
Chris@1012 54 }
Chris@1012 55
Chris@902 56 ColourMapper::ColourMapper(int map, double min, double max) :
Chris@376 57 QObject(),
Chris@376 58 m_map(map),
Chris@376 59 m_min(min),
Chris@376 60 m_max(max)
Chris@376 61 {
Chris@376 62 if (m_min == m_max) {
Chris@682 63 cerr << "WARNING: ColourMapper: min == max (== " << m_min
Chris@682 64 << "), adjusting" << endl;
Chris@376 65 m_max = m_min + 1;
Chris@376 66 }
Chris@376 67 }
Chris@376 68
Chris@376 69 ColourMapper::~ColourMapper()
Chris@376 70 {
Chris@376 71 }
Chris@376 72
Chris@376 73 int
Chris@376 74 ColourMapper::getColourMapCount()
Chris@376 75 {
Chris@1012 76 return 13;
Chris@376 77 }
Chris@376 78
Chris@376 79 QString
Chris@376 80 ColourMapper::getColourMapName(int n)
Chris@376 81 {
Chris@376 82 if (n >= getColourMapCount()) return tr("<unknown>");
Chris@376 83 StandardMap map = (StandardMap)n;
Chris@376 84
Chris@376 85 switch (map) {
Chris@376 86 case DefaultColours: return tr("Default");
Chris@376 87 case WhiteOnBlack: return tr("White on Black");
Chris@376 88 case BlackOnWhite: return tr("Black on White");
Chris@376 89 case RedOnBlue: return tr("Red on Blue");
Chris@376 90 case YellowOnBlack: return tr("Yellow on Black");
Chris@376 91 case BlueOnBlack: return tr("Blue on Black");
Chris@376 92 case Sunset: return tr("Sunset");
Chris@376 93 case FruitSalad: return tr("Fruit Salad");
Chris@376 94 case Banded: return tr("Banded");
Chris@376 95 case Highlight: return tr("Highlight");
Chris@376 96 case Printer: return tr("Printer");
Chris@536 97 case HighGain: return tr("High Gain");
Chris@1013 98 case XRay: return tr("X-Ray");
Chris@376 99 }
Chris@376 100
Chris@376 101 return tr("<unknown>");
Chris@376 102 }
Chris@376 103
Chris@376 104 QColor
Chris@902 105 ColourMapper::map(double value) const
Chris@376 106 {
Chris@902 107 double norm = (value - m_min) / (m_max - m_min);
Chris@902 108 if (norm < 0.0) norm = 0.0;
Chris@902 109 if (norm > 1.0) norm = 1.0;
Chris@376 110
Chris@902 111 double h = 0.0, s = 0.0, v = 0.0, r = 0.0, g = 0.0, b = 0.0;
Chris@376 112 bool hsv = true;
Chris@376 113
Chris@911 114 double blue = 0.6666, pieslice = 0.3333;
Chris@376 115
Chris@376 116 if (m_map >= getColourMapCount()) return Qt::black;
Chris@376 117 StandardMap map = (StandardMap)m_map;
Chris@376 118
Chris@376 119 switch (map) {
Chris@376 120
Chris@376 121 case DefaultColours:
Chris@902 122 h = blue - norm * 2.0 * pieslice;
Chris@902 123 s = 0.5f + norm/2.0;
Chris@376 124 v = norm;
Chris@376 125 break;
Chris@376 126
Chris@376 127 case WhiteOnBlack:
Chris@376 128 r = g = b = norm;
Chris@376 129 hsv = false;
Chris@376 130 break;
Chris@376 131
Chris@376 132 case BlackOnWhite:
Chris@902 133 r = g = b = 1.0 - norm;
Chris@376 134 hsv = false;
Chris@376 135 break;
Chris@376 136
Chris@376 137 case RedOnBlue:
Chris@902 138 h = blue - pieslice/4.0 + norm * (pieslice + pieslice/4.0);
Chris@902 139 s = 1.0;
Chris@376 140 v = norm;
Chris@376 141 break;
Chris@376 142
Chris@376 143 case YellowOnBlack:
Chris@902 144 h = 0.15;
Chris@902 145 s = 1.0;
Chris@376 146 v = norm;
Chris@376 147 break;
Chris@376 148
Chris@376 149 case BlueOnBlack:
Chris@376 150 h = blue;
Chris@902 151 s = 1.0;
Chris@902 152 v = norm * 2.0;
Chris@902 153 if (v > 1.0) {
Chris@902 154 v = 1.0;
Chris@904 155 s = 1.0 - (sqrt(norm) - 0.707) * 3.413;
Chris@902 156 if (s < 0.0) s = 0.0;
Chris@902 157 if (s > 1.0) s = 1.0;
Chris@376 158 }
Chris@376 159 break;
Chris@376 160
Chris@376 161 case Sunset:
Chris@902 162 r = (norm - 0.24) * 2.38;
Chris@902 163 if (r > 1.0) r = 1.0;
Chris@902 164 if (r < 0.0) r = 0.0;
Chris@902 165 g = (norm - 0.64) * 2.777;
Chris@902 166 if (g > 1.0) g = 1.0;
Chris@902 167 if (g < 0.0) g = 0.0;
Chris@376 168 b = (3.6f * norm);
Chris@902 169 if (norm > 0.277) b = 2.0 - b;
Chris@902 170 if (b > 1.0) b = 1.0;
Chris@902 171 if (b < 0.0) b = 0.0;
Chris@376 172 hsv = false;
Chris@376 173 break;
Chris@376 174
Chris@376 175 case FruitSalad:
Chris@902 176 h = blue + (pieslice/6.0) - norm;
Chris@902 177 if (h < 0.0) h += 1.0;
Chris@902 178 s = 1.0;
Chris@902 179 v = 1.0;
Chris@376 180 break;
Chris@376 181
Chris@376 182 case Banded:
Chris@376 183 if (norm < 0.125) return Qt::darkGreen;
Chris@376 184 else if (norm < 0.25) return Qt::green;
Chris@376 185 else if (norm < 0.375) return Qt::darkBlue;
Chris@376 186 else if (norm < 0.5) return Qt::blue;
Chris@376 187 else if (norm < 0.625) return Qt::darkYellow;
Chris@376 188 else if (norm < 0.75) return Qt::yellow;
Chris@376 189 else if (norm < 0.875) return Qt::darkRed;
Chris@376 190 else return Qt::red;
Chris@376 191 break;
Chris@376 192
Chris@376 193 case Highlight:
Chris@376 194 if (norm > 0.99) return Qt::white;
Chris@376 195 else return Qt::darkBlue;
Chris@376 196
Chris@376 197 case Printer:
Chris@376 198 if (norm > 0.8) {
Chris@902 199 r = 1.0;
Chris@376 200 } else if (norm > 0.7) {
Chris@902 201 r = 0.9;
Chris@376 202 } else if (norm > 0.6) {
Chris@902 203 r = 0.8;
Chris@376 204 } else if (norm > 0.5) {
Chris@902 205 r = 0.7;
Chris@376 206 } else if (norm > 0.4) {
Chris@902 207 r = 0.6;
Chris@376 208 } else if (norm > 0.3) {
Chris@902 209 r = 0.5;
Chris@376 210 } else if (norm > 0.2) {
Chris@902 211 r = 0.4;
Chris@376 212 } else {
Chris@902 213 r = 0.0;
Chris@376 214 }
Chris@902 215 r = g = b = 1.0 - r;
Chris@376 216 hsv = false;
Chris@376 217 break;
Chris@536 218
Chris@536 219 case HighGain:
Chris@902 220 if (norm <= 1.0 / 256.0) {
Chris@902 221 norm = 0.0;
Chris@536 222 } else {
Chris@904 223 norm = 0.1f + (pow(((norm - 0.5) * 2.0), 3.0) + 1.0) / 2.081;
Chris@536 224 }
Chris@536 225 // now as for Sunset
Chris@902 226 r = (norm - 0.24) * 2.38;
Chris@902 227 if (r > 1.0) r = 1.0;
Chris@902 228 if (r < 0.0) r = 0.0;
Chris@902 229 g = (norm - 0.64) * 2.777;
Chris@902 230 if (g > 1.0) g = 1.0;
Chris@902 231 if (g < 0.0) g = 0.0;
Chris@536 232 b = (3.6f * norm);
Chris@902 233 if (norm > 0.277) b = 2.0 - b;
Chris@902 234 if (b > 1.0) b = 1.0;
Chris@902 235 if (b < 0.0) b = 0.0;
Chris@536 236 hsv = false;
Chris@536 237 /*
Chris@902 238 if (r > 1.0) r = 1.0;
Chris@902 239 r = g = b = 1.0 - r;
Chris@536 240 hsv = false;
Chris@536 241 */
Chris@536 242 break;
Chris@1012 243
Chris@1013 244 case XRay:
Chris@1012 245 hsv = false;
Chris@1013 246 mapDiscrete(norm, xRay, r, g, b);
Chris@376 247 }
Chris@376 248
Chris@376 249 if (hsv) {
Chris@376 250 return QColor::fromHsvF(h, s, v);
Chris@376 251 } else {
Chris@376 252 return QColor::fromRgbF(r, g, b);
Chris@376 253 }
Chris@376 254 }
Chris@376 255
Chris@376 256 QColor
Chris@376 257 ColourMapper::getContrastingColour() const
Chris@376 258 {
Chris@376 259 if (m_map >= getColourMapCount()) return Qt::white;
Chris@376 260 StandardMap map = (StandardMap)m_map;
Chris@376 261
Chris@376 262 switch (map) {
Chris@376 263
Chris@376 264 case DefaultColours:
Chris@376 265 return QColor(255, 150, 50);
Chris@376 266
Chris@376 267 case WhiteOnBlack:
Chris@376 268 return Qt::red;
Chris@376 269
Chris@376 270 case BlackOnWhite:
Chris@376 271 return Qt::darkGreen;
Chris@376 272
Chris@376 273 case RedOnBlue:
Chris@376 274 return Qt::green;
Chris@376 275
Chris@376 276 case YellowOnBlack:
Chris@376 277 return QColor::fromHsv(240, 255, 255);
Chris@376 278
Chris@376 279 case BlueOnBlack:
Chris@376 280 return Qt::red;
Chris@376 281
Chris@376 282 case Sunset:
Chris@376 283 return Qt::white;
Chris@376 284
Chris@376 285 case FruitSalad:
Chris@376 286 return Qt::white;
Chris@376 287
Chris@376 288 case Banded:
Chris@376 289 return Qt::cyan;
Chris@376 290
Chris@376 291 case Highlight:
Chris@376 292 return Qt::red;
Chris@376 293
Chris@376 294 case Printer:
Chris@376 295 return Qt::red;
Chris@536 296
Chris@536 297 case HighGain:
Chris@536 298 return Qt::red;
Chris@376 299 }
Chris@376 300
Chris@376 301 return Qt::white;
Chris@376 302 }
Chris@376 303
Chris@376 304 bool
Chris@376 305 ColourMapper::hasLightBackground() const
Chris@376 306 {
Chris@376 307 if (m_map >= getColourMapCount()) return false;
Chris@376 308 StandardMap map = (StandardMap)m_map;
Chris@376 309
Chris@376 310 switch (map) {
Chris@376 311
Chris@376 312 case BlackOnWhite:
Chris@376 313 case Printer:
Chris@536 314 case HighGain:
Chris@376 315 return true;
Chris@376 316
Chris@805 317 case DefaultColours:
Chris@805 318 case Sunset:
Chris@805 319 case WhiteOnBlack:
Chris@805 320 case RedOnBlue:
Chris@805 321 case YellowOnBlack:
Chris@805 322 case BlueOnBlack:
Chris@805 323 case FruitSalad:
Chris@805 324 case Banded:
Chris@805 325 case Highlight:
Chris@805 326
Chris@376 327 default:
Chris@376 328 return false;
Chris@376 329 }
Chris@376 330 }
Chris@376 331
Chris@376 332