annotate layer/ColourMapper.cpp @ 253:1b1e6947c124

* FFT: fix invalid write of normalisation factor in compact mode of disc cache * FFT: fix range problem for normalisation factor in compact mode (it was stored as an unsigned scaled from an assumed float range of 0->1, which is not very plausible and not accurate enough even if true -- use a float instead) * Spectrogram: fix vertical zoom behaviour for log frequency spectrograms: make the thing in the middle of the display remain in the middle after zoom * Overview widget: don't update the detailed waveform if still decoding the audio file (too expensive to do all those redraws)
author Chris Cannam
date Fri, 08 Jun 2007 15:19:50 +0000
parents 28c8e8e3c537
children b9380f679f70
rev   line source
Chris@196 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@196 2
Chris@196 3 /*
Chris@196 4 Sonic Visualiser
Chris@196 5 An audio file viewer and annotation editor.
Chris@196 6 Centre for Digital Music, Queen Mary, University of London.
Chris@196 7 This file copyright 2006-2007 Chris Cannam and QMUL.
Chris@196 8
Chris@196 9 This program is free software; you can redistribute it and/or
Chris@196 10 modify it under the terms of the GNU General Public License as
Chris@196 11 published by the Free Software Foundation; either version 2 of the
Chris@196 12 License, or (at your option) any later version. See the file
Chris@196 13 COPYING included with this distribution for more information.
Chris@196 14 */
Chris@196 15
Chris@196 16 #include "ColourMapper.h"
Chris@196 17
Chris@197 18 #include <iostream>
Chris@197 19
Chris@201 20 #include <cmath>
Chris@201 21
Chris@196 22 ColourMapper::ColourMapper(int map, float min, float max) :
Chris@196 23 QObject(),
Chris@196 24 m_map(map),
Chris@196 25 m_min(min),
Chris@196 26 m_max(max)
Chris@196 27 {
Chris@197 28 if (m_min == m_max) {
Chris@197 29 std::cerr << "WARNING: ColourMapper: min == max (== " << m_min
Chris@197 30 << "), adjusting" << std::endl;
Chris@197 31 m_max = m_min + 1;
Chris@197 32 }
Chris@196 33 }
Chris@196 34
Chris@196 35 ColourMapper::~ColourMapper()
Chris@196 36 {
Chris@196 37 }
Chris@196 38
Chris@196 39 int
Chris@196 40 ColourMapper::getColourMapCount()
Chris@196 41 {
Chris@197 42 return 10;
Chris@196 43 }
Chris@196 44
Chris@196 45 QString
Chris@196 46 ColourMapper::getColourMapName(int n)
Chris@196 47 {
Chris@197 48 if (n >= getColourMapCount()) return tr("<unknown>");
Chris@196 49 StandardMap map = (StandardMap)n;
Chris@196 50
Chris@196 51 switch (map) {
Chris@196 52 case DefaultColours: return tr("Default");
Chris@196 53 case WhiteOnBlack: return tr("White on Black");
Chris@196 54 case BlackOnWhite: return tr("Black on White");
Chris@196 55 case RedOnBlue: return tr("Red on Blue");
Chris@196 56 case YellowOnBlack: return tr("Yellow on Black");
Chris@196 57 case BlueOnBlack: return tr("Blue on Black");
Chris@196 58 case Sunset: return tr("Sunset");
Chris@196 59 case FruitSalad: return tr("Fruit Salad");
Chris@197 60 case Banded: return tr("Banded");
Chris@197 61 case Highlight: return tr("Highlight");
Chris@196 62 }
Chris@196 63
Chris@196 64 return tr("<unknown>");
Chris@196 65 }
Chris@196 66
Chris@196 67 QColor
Chris@196 68 ColourMapper::map(float value) const
Chris@196 69 {
Chris@196 70 float norm = (value - m_min) / (m_max - m_min);
Chris@196 71 if (norm < 0.f) norm = 0.f;
Chris@196 72 if (norm > 1.f) norm = 1.f;
Chris@196 73
Chris@196 74 float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f;
Chris@196 75 bool hsv = true;
Chris@196 76
Chris@248 77 // float red = 0.f, green = 0.3333f;
Chris@248 78 float blue = 0.6666f, pieslice = 0.3333f;
Chris@196 79
Chris@197 80 if (m_map >= getColourMapCount()) return Qt::black;
Chris@196 81 StandardMap map = (StandardMap)m_map;
Chris@196 82
Chris@196 83 switch (map) {
Chris@196 84
Chris@196 85 case DefaultColours:
Chris@196 86 h = blue - norm * 2.f * pieslice;
Chris@196 87 s = 0.5f + norm/2.f;
Chris@196 88 v = norm;
Chris@196 89 break;
Chris@196 90
Chris@196 91 case WhiteOnBlack:
Chris@196 92 r = g = b = norm;
Chris@196 93 hsv = false;
Chris@196 94 break;
Chris@196 95
Chris@196 96 case BlackOnWhite:
Chris@196 97 r = g = b = 1.f - norm;
Chris@196 98 hsv = false;
Chris@196 99 break;
Chris@196 100
Chris@196 101 case RedOnBlue:
Chris@196 102 h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f);
Chris@196 103 s = 1.f;
Chris@196 104 v = norm;
Chris@196 105 break;
Chris@196 106
Chris@196 107 case YellowOnBlack:
Chris@196 108 h = 0.15f;
Chris@196 109 s = 1.f;
Chris@196 110 v = norm;
Chris@196 111 break;
Chris@196 112
Chris@196 113 case BlueOnBlack:
Chris@197 114 h = blue;
Chris@196 115 s = 1.f;
Chris@196 116 v = norm * 2.f;
Chris@197 117 if (v > 1.f) {
Chris@196 118 v = 1.f;
Chris@197 119 s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f;
Chris@197 120 if (s < 0.f) s = 0.f;
Chris@197 121 if (s > 1.f) s = 1.f;
Chris@196 122 }
Chris@196 123 break;
Chris@196 124
Chris@196 125 case Sunset:
Chris@196 126 r = (norm - 0.24f) * 2.38f;
Chris@196 127 if (r > 1.f) r = 1.f;
Chris@196 128 if (r < 0.f) r = 0.f;
Chris@196 129 g = (norm - 0.64f) * 2.777f;
Chris@196 130 if (g > 1.f) g = 1.f;
Chris@196 131 if (g < 0.f) g = 0.f;
Chris@196 132 b = (3.6f * norm);
Chris@196 133 if (norm > 0.277f) b = 2.f - b;
Chris@196 134 if (b > 1.f) b = 1.f;
Chris@196 135 if (b < 0.f) b = 0.f;
Chris@196 136 hsv = false;
Chris@196 137 break;
Chris@196 138
Chris@196 139 case FruitSalad:
Chris@197 140 h = blue + (pieslice/6.f) - norm;
Chris@196 141 if (h < 0.f) h += 1.f;
Chris@196 142 s = 1.f;
Chris@196 143 v = 1.f;
Chris@196 144 break;
Chris@197 145
Chris@197 146 case Banded:
Chris@197 147 if (norm < 0.125) return Qt::darkGreen;
Chris@197 148 else if (norm < 0.25) return Qt::green;
Chris@197 149 else if (norm < 0.375) return Qt::darkBlue;
Chris@197 150 else if (norm < 0.5) return Qt::blue;
Chris@197 151 else if (norm < 0.625) return Qt::darkYellow;
Chris@197 152 else if (norm < 0.75) return Qt::yellow;
Chris@197 153 else if (norm < 0.875) return Qt::darkRed;
Chris@197 154 else return Qt::red;
Chris@197 155 break;
Chris@197 156
Chris@197 157 case Highlight:
Chris@197 158 if (norm > 0.99) return Qt::white;
Chris@197 159 else return Qt::darkBlue;
Chris@196 160 }
Chris@196 161
Chris@196 162 if (hsv) {
Chris@196 163 return QColor::fromHsvF(h, s, v);
Chris@196 164 } else {
Chris@196 165 return QColor::fromRgbF(r, g, b);
Chris@196 166 }
Chris@196 167 }
Chris@196 168
Chris@196 169 QColor
Chris@196 170 ColourMapper::getContrastingColour() const
Chris@196 171 {
Chris@197 172 if (m_map >= getColourMapCount()) return Qt::white;
Chris@196 173 StandardMap map = (StandardMap)m_map;
Chris@196 174
Chris@196 175 switch (map) {
Chris@196 176
Chris@196 177 case DefaultColours:
Chris@196 178 return QColor(255, 150, 50);
Chris@196 179
Chris@196 180 case WhiteOnBlack:
Chris@196 181 return Qt::red;
Chris@196 182
Chris@196 183 case BlackOnWhite:
Chris@196 184 return Qt::darkGreen;
Chris@196 185
Chris@196 186 case RedOnBlue:
Chris@196 187 return Qt::green;
Chris@196 188
Chris@196 189 case YellowOnBlack:
Chris@196 190 return QColor::fromHsv(240, 255, 255);
Chris@196 191
Chris@196 192 case BlueOnBlack:
Chris@196 193 return Qt::red;
Chris@196 194
Chris@196 195 case Sunset:
Chris@196 196 return Qt::white;
Chris@196 197
Chris@196 198 case FruitSalad:
Chris@196 199 return Qt::white;
Chris@197 200
Chris@197 201 case Banded:
Chris@197 202 return Qt::cyan;
Chris@197 203
Chris@197 204 case Highlight:
Chris@197 205 return Qt::red;
Chris@196 206 }
Chris@196 207
Chris@196 208 return Qt::white;
Chris@196 209 }
Chris@196 210
Chris@196 211