annotate layer/ColourMapper.cpp @ 959:2633a1d73e39

Address #1214, layer import produces wrong layer type. We needed a more principled approach to making sure the format gets updated properly and the dialog elements are consistent (basically separating making the dialog elements consistent from subsequently updating the format). This change should provide that, though there may be gotchas still.
author Chris Cannam
date Tue, 12 May 2015 12:31:37 +0100
parents 6e2a034f7117
children 2a85ab180d08
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@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