annotate layer/ColourMapper.cpp @ 518:fe134ec37a2a

* fix unsigned overflow causing spectrogram to "disappear" in some resolution and scroll combinations
author Chris Cannam
date Fri, 06 Mar 2009 10:23:30 +0000
parents e1a9e478b7f2
children aca01b3af29f
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@376 42 return 11;
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@376 63 }
Chris@376 64
Chris@376 65 return tr("<unknown>");
Chris@376 66 }
Chris@376 67
Chris@376 68 QColor
Chris@376 69 ColourMapper::map(float value) const
Chris@376 70 {
Chris@376 71 float norm = (value - m_min) / (m_max - m_min);
Chris@376 72 if (norm < 0.f) norm = 0.f;
Chris@376 73 if (norm > 1.f) norm = 1.f;
Chris@376 74
Chris@376 75 float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f;
Chris@376 76 bool hsv = true;
Chris@376 77
Chris@376 78 // float red = 0.f, green = 0.3333f;
Chris@376 79 float blue = 0.6666f, pieslice = 0.3333f;
Chris@376 80
Chris@376 81 if (m_map >= getColourMapCount()) return Qt::black;
Chris@376 82 StandardMap map = (StandardMap)m_map;
Chris@376 83
Chris@376 84 switch (map) {
Chris@376 85
Chris@376 86 case DefaultColours:
Chris@376 87 h = blue - norm * 2.f * pieslice;
Chris@376 88 s = 0.5f + norm/2.f;
Chris@376 89 v = norm;
Chris@376 90 break;
Chris@376 91
Chris@376 92 case WhiteOnBlack:
Chris@376 93 r = g = b = norm;
Chris@376 94 hsv = false;
Chris@376 95 break;
Chris@376 96
Chris@376 97 case BlackOnWhite:
Chris@376 98 r = g = b = 1.f - norm;
Chris@376 99 hsv = false;
Chris@376 100 break;
Chris@376 101
Chris@376 102 case RedOnBlue:
Chris@376 103 h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f);
Chris@376 104 s = 1.f;
Chris@376 105 v = norm;
Chris@376 106 break;
Chris@376 107
Chris@376 108 case YellowOnBlack:
Chris@376 109 h = 0.15f;
Chris@376 110 s = 1.f;
Chris@376 111 v = norm;
Chris@376 112 break;
Chris@376 113
Chris@376 114 case BlueOnBlack:
Chris@376 115 h = blue;
Chris@376 116 s = 1.f;
Chris@376 117 v = norm * 2.f;
Chris@376 118 if (v > 1.f) {
Chris@376 119 v = 1.f;
Chris@376 120 s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f;
Chris@376 121 if (s < 0.f) s = 0.f;
Chris@376 122 if (s > 1.f) s = 1.f;
Chris@376 123 }
Chris@376 124 break;
Chris@376 125
Chris@376 126 case Sunset:
Chris@376 127 r = (norm - 0.24f) * 2.38f;
Chris@376 128 if (r > 1.f) r = 1.f;
Chris@376 129 if (r < 0.f) r = 0.f;
Chris@376 130 g = (norm - 0.64f) * 2.777f;
Chris@376 131 if (g > 1.f) g = 1.f;
Chris@376 132 if (g < 0.f) g = 0.f;
Chris@376 133 b = (3.6f * norm);
Chris@376 134 if (norm > 0.277f) b = 2.f - b;
Chris@376 135 if (b > 1.f) b = 1.f;
Chris@376 136 if (b < 0.f) b = 0.f;
Chris@376 137 hsv = false;
Chris@376 138 break;
Chris@376 139
Chris@376 140 case FruitSalad:
Chris@376 141 h = blue + (pieslice/6.f) - norm;
Chris@376 142 if (h < 0.f) h += 1.f;
Chris@376 143 s = 1.f;
Chris@376 144 v = 1.f;
Chris@376 145 break;
Chris@376 146
Chris@376 147 case Banded:
Chris@376 148 if (norm < 0.125) return Qt::darkGreen;
Chris@376 149 else if (norm < 0.25) return Qt::green;
Chris@376 150 else if (norm < 0.375) return Qt::darkBlue;
Chris@376 151 else if (norm < 0.5) return Qt::blue;
Chris@376 152 else if (norm < 0.625) return Qt::darkYellow;
Chris@376 153 else if (norm < 0.75) return Qt::yellow;
Chris@376 154 else if (norm < 0.875) return Qt::darkRed;
Chris@376 155 else return Qt::red;
Chris@376 156 break;
Chris@376 157
Chris@376 158 case Highlight:
Chris@376 159 if (norm > 0.99) return Qt::white;
Chris@376 160 else return Qt::darkBlue;
Chris@376 161
Chris@376 162 case Printer:
Chris@376 163 if (norm > 0.8) {
Chris@376 164 r = 1.f;
Chris@376 165 } else if (norm > 0.7) {
Chris@376 166 r = 0.9f;
Chris@376 167 } else if (norm > 0.6) {
Chris@376 168 r = 0.8f;
Chris@376 169 } else if (norm > 0.5) {
Chris@376 170 r = 0.7f;
Chris@376 171 } else if (norm > 0.4) {
Chris@376 172 r = 0.6f;
Chris@376 173 } else if (norm > 0.3) {
Chris@376 174 r = 0.5f;
Chris@376 175 } else if (norm > 0.2) {
Chris@376 176 r = 0.4f;
Chris@376 177 } else {
Chris@376 178 r = 0.f;
Chris@376 179 }
Chris@376 180 r = g = b = 1.f - r;
Chris@376 181 hsv = false;
Chris@376 182 break;
Chris@376 183 }
Chris@376 184
Chris@376 185 if (hsv) {
Chris@376 186 return QColor::fromHsvF(h, s, v);
Chris@376 187 } else {
Chris@376 188 return QColor::fromRgbF(r, g, b);
Chris@376 189 }
Chris@376 190 }
Chris@376 191
Chris@376 192 QColor
Chris@376 193 ColourMapper::getContrastingColour() const
Chris@376 194 {
Chris@376 195 if (m_map >= getColourMapCount()) return Qt::white;
Chris@376 196 StandardMap map = (StandardMap)m_map;
Chris@376 197
Chris@376 198 switch (map) {
Chris@376 199
Chris@376 200 case DefaultColours:
Chris@376 201 return QColor(255, 150, 50);
Chris@376 202
Chris@376 203 case WhiteOnBlack:
Chris@376 204 return Qt::red;
Chris@376 205
Chris@376 206 case BlackOnWhite:
Chris@376 207 return Qt::darkGreen;
Chris@376 208
Chris@376 209 case RedOnBlue:
Chris@376 210 return Qt::green;
Chris@376 211
Chris@376 212 case YellowOnBlack:
Chris@376 213 return QColor::fromHsv(240, 255, 255);
Chris@376 214
Chris@376 215 case BlueOnBlack:
Chris@376 216 return Qt::red;
Chris@376 217
Chris@376 218 case Sunset:
Chris@376 219 return Qt::white;
Chris@376 220
Chris@376 221 case FruitSalad:
Chris@376 222 return Qt::white;
Chris@376 223
Chris@376 224 case Banded:
Chris@376 225 return Qt::cyan;
Chris@376 226
Chris@376 227 case Highlight:
Chris@376 228 return Qt::red;
Chris@376 229
Chris@376 230 case Printer:
Chris@376 231 return Qt::red;
Chris@376 232 }
Chris@376 233
Chris@376 234 return Qt::white;
Chris@376 235 }
Chris@376 236
Chris@376 237 bool
Chris@376 238 ColourMapper::hasLightBackground() const
Chris@376 239 {
Chris@376 240 if (m_map >= getColourMapCount()) return false;
Chris@376 241 StandardMap map = (StandardMap)m_map;
Chris@376 242
Chris@376 243 switch (map) {
Chris@376 244
Chris@376 245 case BlackOnWhite:
Chris@376 246 case Printer:
Chris@376 247 return true;
Chris@376 248
Chris@376 249 default:
Chris@376 250 return false;
Chris@376 251 }
Chris@376 252 }
Chris@376 253
Chris@376 254