changeset 1445:ad86aa712d11 single-point

Add getNearbyColourIndex to ColourDatabase; tweak getContrastingColour for bright colours; add comments
author Chris Cannam
date Tue, 30 Apr 2019 14:02:03 +0100
parents 8e6a24110996
children 1ed6d666ec9e
files layer/ColourDatabase.cpp layer/ColourDatabase.h
diffstat 2 files changed, 135 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/layer/ColourDatabase.cpp	Thu Apr 25 17:07:04 2019 +0100
+++ b/layer/ColourDatabase.cpp	Tue Apr 30 14:02:03 2019 +0100
@@ -18,6 +18,8 @@
 
 #include <QPainter>
 
+//#define DEBUG_COLOUR_DATABASE 1
+
 ColourDatabase
 ColourDatabase::m_instance;
 
@@ -85,24 +87,70 @@
     return -1;
 }
 
+int
+ColourDatabase::getNearbyColourIndex(QColor col) const
+{
+    int index = 0;
+    int closestIndex = -1;
+    int closestDistance = 0;
+
+    for (auto &c: m_colours) {
+        int distance =
+            std::abs(col.red() - c.colour.red()) +
+            std::abs(col.green() - c.colour.green()) +
+            std::abs(col.blue() - c.colour.blue());
+#ifdef DEBUG_COLOUR_DATABASE
+        SVDEBUG << "getNearbyColourIndex: comparing " << c.colour.name()
+                << " to " << col.name() << ": distance = " << distance << endl;
+#endif
+        if (closestIndex < 0 || distance < closestDistance) {
+            closestIndex = index;
+            closestDistance = distance;
+#ifdef DEBUG_COLOUR_DATABASE
+            SVDEBUG << "(this is the best so far)" << endl;
+#endif
+        }
+        ++index;
+    }
+
+#ifdef DEBUG_COLOUR_DATABASE
+    SVDEBUG << "returning " << closestIndex << endl;
+#endif
+    return closestIndex;
+}
+
 QColor
 ColourDatabase::getContrastingColour(int c) const
 {
     QColor col = getColour(c);
-    if (col.red() > col.blue()) {
-        if (col.green() > col.blue()) {
-            return Qt::blue;
+    QColor contrasting = Qt::red;
+    bool dark = (col.red() < 240 && col.green() < 240 && col.blue() < 240);
+    if (dark) {
+        if (col.red() > col.blue()) {
+            if (col.green() > col.blue()) {
+                contrasting = Qt::blue;
+            } else {
+                contrasting = Qt::yellow;
+            }
         } else {
-            return Qt::yellow;
+            if (col.green() > col.blue()) {
+                contrasting = Qt::yellow;
+            } else {
+                contrasting = Qt::red;
+            }
         }
     } else {
-        if (col.green() > col.blue()) {
-            return Qt::yellow;
+        if (col.red() > 230 && col.green() > 230 && col.blue() > 230) {
+            contrasting = QColor(30, 150, 255);
         } else {
-            return Qt::red;
+            contrasting = QColor(255, 188, 80);
         }
     }
-    return Qt::red;
+#ifdef DEBUG_COLOUR_DATABASE
+    SVDEBUG << "getContrastingColour(" << col.name() << "): dark = " << dark
+            << ", returning " << contrasting.name() << endl;
+#endif
+    return contrasting;
 }
 
 bool
--- a/layer/ColourDatabase.h	Thu Apr 25 17:07:04 2019 +0100
+++ b/layer/ColourDatabase.h	Tue Apr 30 14:02:03 2019 +0100
@@ -30,21 +30,90 @@
 public:
     static ColourDatabase *getInstance();
 
+    /**
+     * Return the number of colours in the database.
+     */
     int getColourCount() const;
+
+    /**
+     * Return the name of the colour at index c.
+     */
     QString getColourName(int c) const;
+
+    /**
+     * Return the colour at index c.
+     */
     QColor getColour(int c) const;
+
+    /**
+     * Return the colour with the given name, if found in the
+     * database. If not found, return Qt::black.
+     */
     QColor getColour(QString name) const;
-    int getColourIndex(QString name) const; // -1 -> not found
-    int getColourIndex(QColor c) const; // returns first index of possibly many
+
+    /**
+     * Return the index of the colour with the given name, if found in
+     * the database. If not found, return -1.
+     */
+    int getColourIndex(QString name) const;
+
+    /**
+     * Return the index of the given colour, if found in the
+     * database. If not found, return -1. Note that it is possible for
+     * a colour to appear more than once in the database: names have
+     * to be unique in the database, but colours don't. This always
+     * returns the first match.
+     */
+    int getColourIndex(QColor c) const;
+
+    /**
+     * Return true if the given colour exists in the database.
+     */
     bool haveColour(QColor c) const;
 
+    /**
+     * Return the index of the colour in the database that is closest
+     * to the given one, by some simplistic measure (Manhattan
+     * distance in RGB space). This always returns some valid index,
+     * unless the database is empty, in which case it returns -1.
+     */
+    int getNearbyColourIndex(QColor c) const;
+
+    /**
+     * Add a colour to the database, with the associated name. Return
+     * the index of the colour in the database. Names are unique
+     * within the database: if another colour exists already with the
+     * given name, its colour value is replaced with the given
+     * one. Colours may appear more than once under different names.
+     */
+    int addColour(QColor c, QString name);
+
+    /** 
+     * Remove the colour with the given name from the database.
+     */
+    void removeColour(QString);
+
+    /**
+     * Return true if the colour at index c is marked as using a dark
+     * background. Such colours are presumably "bright" ones, but all
+     * this reports is whether the colour has been marked with
+     * setUseDarkBackground, not any intrinsic property of the colour.
+     */
     bool useDarkBackground(int c) const;
+    
+    /**
+     * Mark the colour at index c as using a dark
+     * background. Generally this should be called for "bright"
+     * colours.
+     */
     void setUseDarkBackground(int c, bool dark);
 
-    int addColour(QColor, QString); // returns index
-    void removeColour(QString);
-
-    // returned colour is not necessarily in database
+    /**
+     * Return a colour that contrasts with the one at index c,
+     * according to some simplistic algorithm. The returned colour is
+     * not necessarily in the database; pass it to
+     * getNearbyColourIndex if you need one that is.
+     */
     QColor getContrastingColour(int c) const;
 
     // for use in XML export
@@ -61,7 +130,10 @@
     // for use by PropertyContainer getPropertyRangeAndValue methods
     void getColourPropertyRange(int *min, int *max) const;
 
-    QPixmap getExamplePixmap(int index, QSize size) const;
+    /**
+     * Generate a swatch pixmap illustrating the colour at index c.
+     */
+    QPixmap getExamplePixmap(int c, QSize size) const;
     
 signals:
     void colourDatabaseChanged();