svgui
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006-2007 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "ColourMapper.h" 00017 00018 #include <iostream> 00019 00020 #include <cmath> 00021 00022 #include "base/Debug.h" 00023 00024 ColourMapper::ColourMapper(int map, float min, float max) : 00025 QObject(), 00026 m_map(map), 00027 m_min(min), 00028 m_max(max) 00029 { 00030 if (m_min == m_max) { 00031 cerr << "WARNING: ColourMapper: min == max (== " << m_min 00032 << "), adjusting" << endl; 00033 m_max = m_min + 1; 00034 } 00035 } 00036 00037 ColourMapper::~ColourMapper() 00038 { 00039 } 00040 00041 int 00042 ColourMapper::getColourMapCount() 00043 { 00044 return 12; 00045 } 00046 00047 QString 00048 ColourMapper::getColourMapName(int n) 00049 { 00050 if (n >= getColourMapCount()) return tr("<unknown>"); 00051 StandardMap map = (StandardMap)n; 00052 00053 switch (map) { 00054 case DefaultColours: return tr("Default"); 00055 case WhiteOnBlack: return tr("White on Black"); 00056 case BlackOnWhite: return tr("Black on White"); 00057 case RedOnBlue: return tr("Red on Blue"); 00058 case YellowOnBlack: return tr("Yellow on Black"); 00059 case BlueOnBlack: return tr("Blue on Black"); 00060 case Sunset: return tr("Sunset"); 00061 case FruitSalad: return tr("Fruit Salad"); 00062 case Banded: return tr("Banded"); 00063 case Highlight: return tr("Highlight"); 00064 case Printer: return tr("Printer"); 00065 case HighGain: return tr("High Gain"); 00066 } 00067 00068 return tr("<unknown>"); 00069 } 00070 00071 QColor 00072 ColourMapper::map(float value) const 00073 { 00074 float norm = (value - m_min) / (m_max - m_min); 00075 if (norm < 0.f) norm = 0.f; 00076 if (norm > 1.f) norm = 1.f; 00077 00078 float h = 0.f, s = 0.f, v = 0.f, r = 0.f, g = 0.f, b = 0.f; 00079 bool hsv = true; 00080 00081 // float red = 0.f, green = 0.3333f; 00082 float blue = 0.6666f, pieslice = 0.3333f; 00083 00084 if (m_map >= getColourMapCount()) return Qt::black; 00085 StandardMap map = (StandardMap)m_map; 00086 00087 switch (map) { 00088 00089 case DefaultColours: 00090 h = blue - norm * 2.f * pieslice; 00091 s = 0.5f + norm/2.f; 00092 v = norm; 00093 break; 00094 00095 case WhiteOnBlack: 00096 r = g = b = norm; 00097 hsv = false; 00098 break; 00099 00100 case BlackOnWhite: 00101 r = g = b = 1.f - norm; 00102 hsv = false; 00103 break; 00104 00105 case RedOnBlue: 00106 h = blue - pieslice/4.f + norm * (pieslice + pieslice/4.f); 00107 s = 1.f; 00108 v = norm; 00109 break; 00110 00111 case YellowOnBlack: 00112 h = 0.15f; 00113 s = 1.f; 00114 v = norm; 00115 break; 00116 00117 case BlueOnBlack: 00118 h = blue; 00119 s = 1.f; 00120 v = norm * 2.f; 00121 if (v > 1.f) { 00122 v = 1.f; 00123 s = 1.f - (sqrtf(norm) - 0.707f) * 3.413f; 00124 if (s < 0.f) s = 0.f; 00125 if (s > 1.f) s = 1.f; 00126 } 00127 break; 00128 00129 case Sunset: 00130 r = (norm - 0.24f) * 2.38f; 00131 if (r > 1.f) r = 1.f; 00132 if (r < 0.f) r = 0.f; 00133 g = (norm - 0.64f) * 2.777f; 00134 if (g > 1.f) g = 1.f; 00135 if (g < 0.f) g = 0.f; 00136 b = (3.6f * norm); 00137 if (norm > 0.277f) b = 2.f - b; 00138 if (b > 1.f) b = 1.f; 00139 if (b < 0.f) b = 0.f; 00140 hsv = false; 00141 break; 00142 00143 case FruitSalad: 00144 h = blue + (pieslice/6.f) - norm; 00145 if (h < 0.f) h += 1.f; 00146 s = 1.f; 00147 v = 1.f; 00148 break; 00149 00150 case Banded: 00151 if (norm < 0.125) return Qt::darkGreen; 00152 else if (norm < 0.25) return Qt::green; 00153 else if (norm < 0.375) return Qt::darkBlue; 00154 else if (norm < 0.5) return Qt::blue; 00155 else if (norm < 0.625) return Qt::darkYellow; 00156 else if (norm < 0.75) return Qt::yellow; 00157 else if (norm < 0.875) return Qt::darkRed; 00158 else return Qt::red; 00159 break; 00160 00161 case Highlight: 00162 if (norm > 0.99) return Qt::white; 00163 else return Qt::darkBlue; 00164 00165 case Printer: 00166 if (norm > 0.8) { 00167 r = 1.f; 00168 } else if (norm > 0.7) { 00169 r = 0.9f; 00170 } else if (norm > 0.6) { 00171 r = 0.8f; 00172 } else if (norm > 0.5) { 00173 r = 0.7f; 00174 } else if (norm > 0.4) { 00175 r = 0.6f; 00176 } else if (norm > 0.3) { 00177 r = 0.5f; 00178 } else if (norm > 0.2) { 00179 r = 0.4f; 00180 } else { 00181 r = 0.f; 00182 } 00183 r = g = b = 1.f - r; 00184 hsv = false; 00185 break; 00186 00187 case HighGain: 00188 if (norm <= 1.f / 256.f) { 00189 norm = 0.f; 00190 } else { 00191 norm = 0.1f + (powf(((norm - 0.5f) * 2.f), 3.f) + 1.f) / 2.081f; 00192 } 00193 // now as for Sunset 00194 r = (norm - 0.24f) * 2.38f; 00195 if (r > 1.f) r = 1.f; 00196 if (r < 0.f) r = 0.f; 00197 g = (norm - 0.64f) * 2.777f; 00198 if (g > 1.f) g = 1.f; 00199 if (g < 0.f) g = 0.f; 00200 b = (3.6f * norm); 00201 if (norm > 0.277f) b = 2.f - b; 00202 if (b > 1.f) b = 1.f; 00203 if (b < 0.f) b = 0.f; 00204 hsv = false; 00205 /* 00206 if (r > 1.f) r = 1.f; 00207 r = g = b = 1.f - r; 00208 hsv = false; 00209 */ 00210 break; 00211 } 00212 00213 if (hsv) { 00214 return QColor::fromHsvF(h, s, v); 00215 } else { 00216 return QColor::fromRgbF(r, g, b); 00217 } 00218 } 00219 00220 QColor 00221 ColourMapper::getContrastingColour() const 00222 { 00223 if (m_map >= getColourMapCount()) return Qt::white; 00224 StandardMap map = (StandardMap)m_map; 00225 00226 switch (map) { 00227 00228 case DefaultColours: 00229 return QColor(255, 150, 50); 00230 00231 case WhiteOnBlack: 00232 return Qt::red; 00233 00234 case BlackOnWhite: 00235 return Qt::darkGreen; 00236 00237 case RedOnBlue: 00238 return Qt::green; 00239 00240 case YellowOnBlack: 00241 return QColor::fromHsv(240, 255, 255); 00242 00243 case BlueOnBlack: 00244 return Qt::red; 00245 00246 case Sunset: 00247 return Qt::white; 00248 00249 case FruitSalad: 00250 return Qt::white; 00251 00252 case Banded: 00253 return Qt::cyan; 00254 00255 case Highlight: 00256 return Qt::red; 00257 00258 case Printer: 00259 return Qt::red; 00260 00261 case HighGain: 00262 return Qt::red; 00263 } 00264 00265 return Qt::white; 00266 } 00267 00268 bool 00269 ColourMapper::hasLightBackground() const 00270 { 00271 if (m_map >= getColourMapCount()) return false; 00272 StandardMap map = (StandardMap)m_map; 00273 00274 switch (map) { 00275 00276 case BlackOnWhite: 00277 case Printer: 00278 case HighGain: 00279 return true; 00280 00281 case DefaultColours: 00282 case Sunset: 00283 case WhiteOnBlack: 00284 case RedOnBlue: 00285 case YellowOnBlack: 00286 case BlueOnBlack: 00287 case FruitSalad: 00288 case Banded: 00289 case Highlight: 00290 00291 default: 00292 return false; 00293 } 00294 } 00295 00296