annotate layer/ColourMapper.cpp @ 561:aced8ec09bc8

* Complete the overhaul of CSV file import; now you can pick the purpose for each column in the file, and SV should do the rest. The most significant practical improvement here is that we can now handle files in which time and duration do not necessarily appear in known columns.
author Chris Cannam
date Mon, 19 Jul 2010 17:08:56 +0000
parents aca01b3af29f
children 1a0dfcbffaf1
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@376 22 ColourMapper::ColourMapper(int map, float min, float max) :
Chris@376 23 QObject(),
Chris@376 24 m_map(map),
Chris@376 25 m_min(min),
Chris@376 26 m_max(max)
Chris@376 27 {
Chris@376 28 if (m_min == m_max) {
Chris@376 29 std::cerr << "WARNING: ColourMapper: min == max (== " << m_min
Chris@376 30 << "), adjusting" << std::endl;
Chris@376 31 m_max = m_min + 1;
Chris@376 32 }
Chris@376 33 }
Chris@376 34
Chris@376 35 ColourMapper::~ColourMapper()
Chris@376 36 {
Chris@376 37 }
Chris@376 38
Chris@376 39 int
Chris@376 40 ColourMapper::getColourMapCount()
Chris@376 41 {
Chris@536 42 return 12;
Chris@376 43 }
Chris@376 44
Chris@376 45 QString
Chris@376 46 ColourMapper::getColourMapName(int n)
Chris@376 47 {
Chris@376 48 if (n >= getColourMapCount()) return tr("<unknown>");
Chris@376 49 StandardMap map = (StandardMap)n;
Chris@376 50
Chris@376 51 switch (map) {
Chris@376 52 case DefaultColours: return tr("Default");
Chris@376 53 case WhiteOnBlack: return tr("White on Black");
Chris@376 54 case BlackOnWhite: return tr("Black on White");
Chris@376 55 case RedOnBlue: return tr("Red on Blue");
Chris@376 56 case YellowOnBlack: return tr("Yellow on Black");
Chris@376 57 case BlueOnBlack: return tr("Blue on Black");
Chris@376 58 case Sunset: return tr("Sunset");
Chris@376 59 case FruitSalad: return tr("Fruit Salad");
Chris@376 60 case Banded: return tr("Banded");
Chris@376 61 case Highlight: return tr("Highlight");
Chris@376 62 case Printer: return tr("Printer");
Chris@536 63 case HighGain: return tr("High Gain");
Chris@376 64 }
Chris@376 65
Chris@376 66 return tr("<unknown>");
Chris@376 67 }
Chris@376 68
Chris@376 69 QColor
Chris@376 70 ColourMapper::map(float value) const
Chris@376 71 {
Chris@376 72 float norm = (value - m_min) / (m_max - m_min);
Chris@376 73 if (norm < 0.f) norm = 0.f;
Chris@376 74 if (norm > 1.f) norm = 1.f;
Chris@376 75
Chris@376 76 float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f;
Chris@376 77 bool hsv = true;
Chris@376 78
Chris@376 79 // float red = 0.f, green = 0.3333f;
Chris@376 80 float blue = 0.6666f, pieslice = 0.3333f;
Chris@376 81
Chris@376 82 if (m_map >= getColourMapCount()) return Qt::black;
Chris@376 83 StandardMap map = (StandardMap)m_map;
Chris@376 84
Chris@376 85 switch (map) {
Chris@376 86
Chris@376 87 case DefaultColours:
Chris@376 88 h = blue - norm * 2.f * pieslice;
Chris@376 89 s = 0.5f + norm/2.f;
Chris@376 90 v = norm;
Chris@376 91 break;
Chris@376 92
Chris@376 93 case WhiteOnBlack:
Chris@376 94 r = g = b = norm;
Chris@376 95 hsv = false;
Chris@376 96 break;
Chris@376 97
Chris@376 98 case BlackOnWhite:
Chris@376 99 r = g = b = 1.f - norm;
Chris@376 100 hsv = false;
Chris@376 101 break;
Chris@376 102
Chris@376 103 case RedOnBlue:
Chris@376 104 h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f);
Chris@376 105 s = 1.f;
Chris@376 106 v = norm;
Chris@376 107 break;
Chris@376 108
Chris@376 109 case YellowOnBlack:
Chris@376 110 h = 0.15f;
Chris@376 111 s = 1.f;
Chris@376 112 v = norm;
Chris@376 113 break;
Chris@376 114
Chris@376 115 case BlueOnBlack:
Chris@376 116 h = blue;
Chris@376 117 s = 1.f;
Chris@376 118 v = norm * 2.f;
Chris@376 119 if (v > 1.f) {
Chris@376 120 v = 1.f;
Chris@376 121 s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f;
Chris@376 122 if (s < 0.f) s = 0.f;
Chris@376 123 if (s > 1.f) s = 1.f;
Chris@376 124 }
Chris@376 125 break;
Chris@376 126
Chris@376 127 case Sunset:
Chris@376 128 r = (norm - 0.24f) * 2.38f;
Chris@376 129 if (r > 1.f) r = 1.f;
Chris@376 130 if (r < 0.f) r = 0.f;
Chris@376 131 g = (norm - 0.64f) * 2.777f;
Chris@376 132 if (g > 1.f) g = 1.f;
Chris@376 133 if (g < 0.f) g = 0.f;
Chris@376 134 b = (3.6f * norm);
Chris@376 135 if (norm > 0.277f) b = 2.f - b;
Chris@376 136 if (b > 1.f) b = 1.f;
Chris@376 137 if (b < 0.f) b = 0.f;
Chris@376 138 hsv = false;
Chris@376 139 break;
Chris@376 140
Chris@376 141 case FruitSalad:
Chris@376 142 h = blue + (pieslice/6.f) - norm;
Chris@376 143 if (h < 0.f) h += 1.f;
Chris@376 144 s = 1.f;
Chris@376 145 v = 1.f;
Chris@376 146 break;
Chris@376 147
Chris@376 148 case Banded:
Chris@376 149 if (norm < 0.125) return Qt::darkGreen;
Chris@376 150 else if (norm < 0.25) return Qt::green;
Chris@376 151 else if (norm < 0.375) return Qt::darkBlue;
Chris@376 152 else if (norm < 0.5) return Qt::blue;
Chris@376 153 else if (norm < 0.625) return Qt::darkYellow;
Chris@376 154 else if (norm < 0.75) return Qt::yellow;
Chris@376 155 else if (norm < 0.875) return Qt::darkRed;
Chris@376 156 else return Qt::red;
Chris@376 157 break;
Chris@376 158
Chris@376 159 case Highlight:
Chris@376 160 if (norm > 0.99) return Qt::white;
Chris@376 161 else return Qt::darkBlue;
Chris@376 162
Chris@376 163 case Printer:
Chris@376 164 if (norm > 0.8) {
Chris@376 165 r = 1.f;
Chris@376 166 } else if (norm > 0.7) {
Chris@376 167 r = 0.9f;
Chris@376 168 } else if (norm > 0.6) {
Chris@376 169 r = 0.8f;
Chris@376 170 } else if (norm > 0.5) {
Chris@376 171 r = 0.7f;
Chris@376 172 } else if (norm > 0.4) {
Chris@376 173 r = 0.6f;
Chris@376 174 } else if (norm > 0.3) {
Chris@376 175 r = 0.5f;
Chris@376 176 } else if (norm > 0.2) {
Chris@376 177 r = 0.4f;
Chris@376 178 } else {
Chris@376 179 r = 0.f;
Chris@376 180 }
Chris@376 181 r = g = b = 1.f - r;
Chris@376 182 hsv = false;
Chris@376 183 break;
Chris@536 184
Chris@536 185 case HighGain:
Chris@536 186 if (norm <= 1.f / 256.f) {
Chris@536 187 norm = 0.f;
Chris@536 188 } else {
Chris@536 189 norm = 0.1f + (powf(((norm - 0.5f) * 2.f), 3.f) + 1.f) / 2.081f;
Chris@536 190 }
Chris@536 191 // now as for Sunset
Chris@536 192 r = (norm - 0.24f) * 2.38f;
Chris@536 193 if (r > 1.f) r = 1.f;
Chris@536 194 if (r < 0.f) r = 0.f;
Chris@536 195 g = (norm - 0.64f) * 2.777f;
Chris@536 196 if (g > 1.f) g = 1.f;
Chris@536 197 if (g < 0.f) g = 0.f;
Chris@536 198 b = (3.6f * norm);
Chris@536 199 if (norm > 0.277f) b = 2.f - b;
Chris@536 200 if (b > 1.f) b = 1.f;
Chris@536 201 if (b < 0.f) b = 0.f;
Chris@536 202 hsv = false;
Chris@536 203 /*
Chris@536 204 if (r > 1.f) r = 1.f;
Chris@536 205 r = g = b = 1.f - r;
Chris@536 206 hsv = false;
Chris@536 207 */
Chris@536 208 break;
Chris@376 209 }
Chris@376 210
Chris@376 211 if (hsv) {
Chris@376 212 return QColor::fromHsvF(h, s, v);
Chris@376 213 } else {
Chris@376 214 return QColor::fromRgbF(r, g, b);
Chris@376 215 }
Chris@376 216 }
Chris@376 217
Chris@376 218 QColor
Chris@376 219 ColourMapper::getContrastingColour() const
Chris@376 220 {
Chris@376 221 if (m_map >= getColourMapCount()) return Qt::white;
Chris@376 222 StandardMap map = (StandardMap)m_map;
Chris@376 223
Chris@376 224 switch (map) {
Chris@376 225
Chris@376 226 case DefaultColours:
Chris@376 227 return QColor(255, 150, 50);
Chris@376 228
Chris@376 229 case WhiteOnBlack:
Chris@376 230 return Qt::red;
Chris@376 231
Chris@376 232 case BlackOnWhite:
Chris@376 233 return Qt::darkGreen;
Chris@376 234
Chris@376 235 case RedOnBlue:
Chris@376 236 return Qt::green;
Chris@376 237
Chris@376 238 case YellowOnBlack:
Chris@376 239 return QColor::fromHsv(240, 255, 255);
Chris@376 240
Chris@376 241 case BlueOnBlack:
Chris@376 242 return Qt::red;
Chris@376 243
Chris@376 244 case Sunset:
Chris@376 245 return Qt::white;
Chris@376 246
Chris@376 247 case FruitSalad:
Chris@376 248 return Qt::white;
Chris@376 249
Chris@376 250 case Banded:
Chris@376 251 return Qt::cyan;
Chris@376 252
Chris@376 253 case Highlight:
Chris@376 254 return Qt::red;
Chris@376 255
Chris@376 256 case Printer:
Chris@376 257 return Qt::red;
Chris@536 258
Chris@536 259 case HighGain:
Chris@536 260 return Qt::red;
Chris@376 261 }
Chris@376 262
Chris@376 263 return Qt::white;
Chris@376 264 }
Chris@376 265
Chris@376 266 bool
Chris@376 267 ColourMapper::hasLightBackground() const
Chris@376 268 {
Chris@376 269 if (m_map >= getColourMapCount()) return false;
Chris@376 270 StandardMap map = (StandardMap)m_map;
Chris@376 271
Chris@376 272 switch (map) {
Chris@376 273
Chris@376 274 case BlackOnWhite:
Chris@376 275 case Printer:
Chris@536 276 case HighGain:
Chris@376 277 return true;
Chris@376 278
Chris@376 279 default:
Chris@376 280 return false;
Chris@376 281 }
Chris@376 282 }
Chris@376 283
Chris@376 284