# HG changeset patch # User Chris Cannam # Date 1579869607 0 # Node ID 57a4ee52ad69c118ffa66ffdbf8783a34ec1502b # Parent 2c974337f3068de09df9b51531ce9da92514c908 Make nearby-colour matching a bit more sophisticated, with slightly better algorithm (we think?) and ability to insist on dark/light background diff -r 2c974337f306 -r 57a4ee52ad69 layer/ColourDatabase.cpp --- a/layer/ColourDatabase.cpp Thu Jan 23 15:43:51 2020 +0000 +++ b/layer/ColourDatabase.cpp Fri Jan 24 12:40:07 2020 +0000 @@ -88,17 +88,44 @@ } int -ColourDatabase::getNearbyColourIndex(QColor col) const +ColourDatabase::getNearbyColourIndex(QColor col, WithBackgroundMode mode) const { - int index = 0; + int index = -1; int closestIndex = -1; - int closestDistance = 0; + double 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()); + + ++index; + + if (mode == WithDarkBackground && !c.darkbg) { +#ifdef DEBUG_COLOUR_DATABASE + SVDEBUG << "getNearbyColourIndex: dark background requested, skipping " << c.colour.name() << endl; +#endif + continue; + } + if (mode == WithLightBackground && c.darkbg) { +#ifdef DEBUG_COLOUR_DATABASE + SVDEBUG << "getNearbyColourIndex: light background requested, skipping " << c.colour.name() << endl; +#endif + continue; + } + + // This distance formula is "one of the better low-cost + // approximations" according to + // https://en.wikipedia.org/w/index.php?title=Color_difference&oldid=936888327 + + double r1 = col.red(), r2 = c.colour.red(); + double g1 = col.green(), g2 = c.colour.green(); + double b1 = col.blue(), b2 = c.colour.blue(); + + double rav = (r1 + r2) / 2.0; + double rterm = (2.0 + rav / 256.0) * (r1 - r2) * (r1 - r2); + double gterm = 4.0 * (g1 - g2) * (g1 - g2); + double bterm = (2.0 + (255 - rav) / 256.0) * (b1 - b2) * (b1 - b2); + + double distance = sqrt(rterm + gterm + bterm); + #ifdef DEBUG_COLOUR_DATABASE SVDEBUG << "getNearbyColourIndex: comparing " << c.colour.name() << " to " << col.name() << ": distance = " << distance << endl; @@ -110,7 +137,6 @@ SVDEBUG << "(this is the best so far)" << endl; #endif } - ++index; } #ifdef DEBUG_COLOUR_DATABASE diff -r 2c974337f306 -r 57a4ee52ad69 layer/ColourDatabase.h --- a/layer/ColourDatabase.h Thu Jan 23 15:43:51 2020 +0000 +++ b/layer/ColourDatabase.h Fri Jan 24 12:40:07 2020 +0000 @@ -71,13 +71,20 @@ */ bool haveColour(QColor c) const; + enum WithBackgroundMode { + WithAnyBackground, + WithDarkBackground, + WithLightBackground + }; + /** * 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. + * to the given one, by some simple measure. This always returns + * some valid index, unless the database is empty, in which case + * it returns -1. */ - int getNearbyColourIndex(QColor c) const; + int getNearbyColourIndex(QColor c, + WithBackgroundMode mode = WithAnyBackground) const; /** * Add a colour to the database, with the associated name. Return @@ -110,9 +117,9 @@ /** * 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. + * according to some simple 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;