annotate layer/ColourDatabase.cpp @ 1511:a473b73fb045 time-frequency-boxes

Introduce time-frequency box layer
author Chris Cannam
date Thu, 19 Sep 2019 15:18:28 +0100
parents ad86aa712d11
children 57a4ee52ad69
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 2007 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 "ColourDatabase.h"
Chris@376 17 #include "base/XmlExportable.h"
Chris@376 18
Chris@376 19 #include <QPainter>
Chris@376 20
Chris@1445 21 //#define DEBUG_COLOUR_DATABASE 1
Chris@1445 22
Chris@376 23 ColourDatabase
Chris@376 24 ColourDatabase::m_instance;
Chris@376 25
Chris@376 26 ColourDatabase *
Chris@376 27 ColourDatabase::getInstance()
Chris@376 28 {
Chris@376 29 return &m_instance;
Chris@376 30 }
Chris@376 31
Chris@376 32 ColourDatabase::ColourDatabase()
Chris@376 33 {
Chris@376 34 }
Chris@376 35
Chris@376 36 int
Chris@376 37 ColourDatabase::getColourCount() const
Chris@376 38 {
Chris@904 39 return int(m_colours.size());
Chris@376 40 }
Chris@376 41
Chris@376 42 QString
Chris@376 43 ColourDatabase::getColourName(int c) const
Chris@376 44 {
Chris@904 45 if (!in_range_for(m_colours, c)) return "";
Chris@376 46 return m_colours[c].name;
Chris@376 47 }
Chris@376 48
Chris@376 49 QColor
Chris@376 50 ColourDatabase::getColour(int c) const
Chris@376 51 {
Chris@904 52 if (!in_range_for(m_colours, c)) return Qt::black;
Chris@376 53 return m_colours[c].colour;
Chris@376 54 }
Chris@376 55
Chris@376 56 QColor
Chris@376 57 ColourDatabase::getColour(QString name) const
Chris@376 58 {
Chris@904 59 for (auto &c: m_colours) {
Chris@904 60 if (c.name == name) return c.colour;
Chris@376 61 }
Chris@376 62
Chris@376 63 return Qt::black;
Chris@376 64 }
Chris@376 65
Chris@376 66 int
Chris@376 67 ColourDatabase::getColourIndex(QString name) const
Chris@376 68 {
Chris@376 69 int index = 0;
Chris@904 70 for (auto &c: m_colours) {
Chris@904 71 if (c.name == name) return index;
Chris@376 72 ++index;
Chris@376 73 }
Chris@376 74
Chris@376 75 return -1;
Chris@376 76 }
Chris@376 77
Chris@376 78 int
Chris@904 79 ColourDatabase::getColourIndex(QColor col) const
Chris@376 80 {
Chris@376 81 int index = 0;
Chris@904 82 for (auto &c: m_colours) {
Chris@904 83 if (c.colour == col) return index;
Chris@376 84 ++index;
Chris@376 85 }
Chris@376 86
Chris@376 87 return -1;
Chris@376 88 }
Chris@376 89
Chris@1445 90 int
Chris@1445 91 ColourDatabase::getNearbyColourIndex(QColor col) const
Chris@1445 92 {
Chris@1445 93 int index = 0;
Chris@1445 94 int closestIndex = -1;
Chris@1445 95 int closestDistance = 0;
Chris@1445 96
Chris@1445 97 for (auto &c: m_colours) {
Chris@1445 98 int distance =
Chris@1445 99 std::abs(col.red() - c.colour.red()) +
Chris@1445 100 std::abs(col.green() - c.colour.green()) +
Chris@1445 101 std::abs(col.blue() - c.colour.blue());
Chris@1445 102 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 103 SVDEBUG << "getNearbyColourIndex: comparing " << c.colour.name()
Chris@1445 104 << " to " << col.name() << ": distance = " << distance << endl;
Chris@1445 105 #endif
Chris@1445 106 if (closestIndex < 0 || distance < closestDistance) {
Chris@1445 107 closestIndex = index;
Chris@1445 108 closestDistance = distance;
Chris@1445 109 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 110 SVDEBUG << "(this is the best so far)" << endl;
Chris@1445 111 #endif
Chris@1445 112 }
Chris@1445 113 ++index;
Chris@1445 114 }
Chris@1445 115
Chris@1445 116 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 117 SVDEBUG << "returning " << closestIndex << endl;
Chris@1445 118 #endif
Chris@1445 119 return closestIndex;
Chris@1445 120 }
Chris@1445 121
Chris@1367 122 QColor
Chris@1367 123 ColourDatabase::getContrastingColour(int c) const
Chris@1367 124 {
Chris@1367 125 QColor col = getColour(c);
Chris@1445 126 QColor contrasting = Qt::red;
Chris@1445 127 bool dark = (col.red() < 240 && col.green() < 240 && col.blue() < 240);
Chris@1445 128 if (dark) {
Chris@1445 129 if (col.red() > col.blue()) {
Chris@1445 130 if (col.green() > col.blue()) {
Chris@1445 131 contrasting = Qt::blue;
Chris@1445 132 } else {
Chris@1445 133 contrasting = Qt::yellow;
Chris@1445 134 }
Chris@1367 135 } else {
Chris@1445 136 if (col.green() > col.blue()) {
Chris@1445 137 contrasting = Qt::yellow;
Chris@1445 138 } else {
Chris@1445 139 contrasting = Qt::red;
Chris@1445 140 }
Chris@1367 141 }
Chris@1367 142 } else {
Chris@1445 143 if (col.red() > 230 && col.green() > 230 && col.blue() > 230) {
Chris@1445 144 contrasting = QColor(30, 150, 255);
Chris@1367 145 } else {
Chris@1445 146 contrasting = QColor(255, 188, 80);
Chris@1367 147 }
Chris@1367 148 }
Chris@1445 149 #ifdef DEBUG_COLOUR_DATABASE
Chris@1445 150 SVDEBUG << "getContrastingColour(" << col.name() << "): dark = " << dark
Chris@1445 151 << ", returning " << contrasting.name() << endl;
Chris@1445 152 #endif
Chris@1445 153 return contrasting;
Chris@1367 154 }
Chris@1367 155
Chris@376 156 bool
Chris@376 157 ColourDatabase::useDarkBackground(int c) const
Chris@376 158 {
Chris@904 159 if (!in_range_for(m_colours, c)) return false;
Chris@376 160 return m_colours[c].darkbg;
Chris@376 161 }
Chris@376 162
Chris@376 163 void
Chris@376 164 ColourDatabase::setUseDarkBackground(int c, bool dark)
Chris@376 165 {
Chris@904 166 if (!in_range_for(m_colours, c)) return;
Chris@376 167 if (m_colours[c].darkbg != dark) {
Chris@376 168 m_colours[c].darkbg = dark;
Chris@376 169 emit colourDatabaseChanged();
Chris@376 170 }
Chris@376 171 }
Chris@376 172
Chris@376 173 int
Chris@376 174 ColourDatabase::addColour(QColor c, QString name)
Chris@376 175 {
Chris@376 176 int index = 0;
Chris@904 177
Chris@376 178 for (ColourList::iterator i = m_colours.begin();
Chris@376 179 i != m_colours.end(); ++i) {
Chris@376 180 if (i->name == name) {
Chris@376 181 i->colour = c;
Chris@376 182 return index;
Chris@376 183 }
Chris@376 184 ++index;
Chris@376 185 }
Chris@376 186
Chris@376 187 ColourRec rec;
Chris@376 188 rec.colour = c;
Chris@376 189 rec.name = name;
Chris@376 190 rec.darkbg = false;
Chris@376 191 m_colours.push_back(rec);
Chris@376 192 emit colourDatabaseChanged();
Chris@376 193 return index;
Chris@376 194 }
Chris@376 195
Chris@376 196 void
Chris@376 197 ColourDatabase::removeColour(QString name)
Chris@376 198 {
Chris@376 199 for (ColourList::iterator i = m_colours.begin();
Chris@376 200 i != m_colours.end(); ++i) {
Chris@376 201 if (i->name == name) {
Chris@376 202 m_colours.erase(i);
Chris@376 203 return;
Chris@376 204 }
Chris@376 205 }
Chris@376 206 }
Chris@376 207
Chris@376 208 void
Chris@376 209 ColourDatabase::getStringValues(int index,
Chris@376 210 QString &colourName,
Chris@376 211 QString &colourSpec,
Chris@376 212 QString &darkbg) const
Chris@376 213 {
Chris@376 214 colourName = "";
Chris@376 215 colourSpec = "";
Chris@904 216 if (!in_range_for(m_colours, index)) return;
Chris@376 217
Chris@376 218 colourName = getColourName(index);
Chris@376 219 QColor c = getColour(index);
Chris@376 220 colourSpec = XmlExportable::encodeColour(c.red(), c.green(), c.blue());
Chris@376 221 darkbg = useDarkBackground(index) ? "true" : "false";
Chris@376 222 }
Chris@376 223
Chris@376 224 int
Chris@376 225 ColourDatabase::putStringValues(QString colourName,
Chris@376 226 QString colourSpec,
Chris@376 227 QString darkbg)
Chris@376 228 {
Chris@376 229 int index = -1;
Chris@376 230 if (colourSpec != "") {
Chris@1266 231 QColor colour(colourSpec);
Chris@376 232 index = getColourIndex(colour);
Chris@376 233 if (index < 0) {
Chris@376 234 index = addColour(colour,
Chris@376 235 colourName == "" ? colourSpec : colourName);
Chris@376 236 }
Chris@376 237 } else if (colourName != "") {
Chris@376 238 index = getColourIndex(colourName);
Chris@376 239 }
Chris@376 240 if (index >= 0) {
Chris@376 241 setUseDarkBackground(index, darkbg == "true");
Chris@376 242 }
Chris@376 243 return index;
Chris@376 244 }
Chris@376 245
Chris@376 246 void
Chris@376 247 ColourDatabase::getColourPropertyRange(int *min, int *max) const
Chris@376 248 {
Chris@376 249 ColourDatabase *db = getInstance();
Chris@376 250 if (min) *min = 0;
Chris@376 251 if (max) {
Chris@376 252 *max = 0;
Chris@376 253 if (db->getColourCount() > 0) *max = db->getColourCount()-1;
Chris@376 254 }
Chris@376 255 }
Chris@376 256
Chris@376 257 QPixmap
Chris@376 258 ColourDatabase::getExamplePixmap(int index, QSize size) const
Chris@376 259 {
Chris@376 260 QPixmap pmap(size);
Chris@376 261 pmap.fill(useDarkBackground(index) ? Qt::black : Qt::white);
Chris@376 262 QPainter paint(&pmap);
Chris@376 263 QColor colour(getColour(index));
Chris@376 264 paint.setPen(colour);
Chris@376 265 paint.setBrush(colour);
Chris@376 266 int margin = 2;
Chris@376 267 if (size.width() < 4 || size.height() < 4) margin = 0;
Chris@376 268 else if (size.width() < 8 || size.height() < 8) margin = 1;
Chris@376 269 paint.drawRect(margin, margin,
Chris@376 270 size.width() - margin*2 - 1, size.height() - margin*2 - 1);
Chris@376 271 return pmap;
Chris@376 272 }
Chris@376 273