Use HSV color space for colorizing.

This commit is contained in:
John Preston 2019-08-27 17:44:51 +03:00
parent 117d6192fa
commit 66d0d6e8fe
2 changed files with 41 additions and 25 deletions

View File

@ -94,9 +94,9 @@ Colorizer::Color cColor(str_const hex) {
const auto q = qColor(hex); const auto q = qColor(hex);
auto hue = int(); auto hue = int();
auto saturation = int(); auto saturation = int();
auto lightness = int(); auto value = int();
q.getHsl(&hue, &saturation, &lightness); q.getHsv(&hue, &saturation, &value);
return Colorizer::Color{ hue, saturation, lightness }; return Colorizer::Color{ hue, saturation, value };
} }
} // namespace } // namespace
@ -108,14 +108,14 @@ Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
auto result = Colorizer(); auto result = Colorizer();
result.ignoreKeys = kColorizeIgnoredKeys; result.ignoreKeys = kColorizeIgnoredKeys;
result.hueThreshold = 15; result.hueThreshold = 15;
scheme.accentColor.getHsl( scheme.accentColor.getHsv(
&result.was.hue, &result.was.hue,
&result.was.saturation, &result.was.saturation,
&result.was.lightness); &result.was.value);
color.getHsl( color.getHsv(
&result.now.hue, &result.now.hue,
&result.now.saturation, &result.now.saturation,
&result.now.lightness); &result.now.value);
switch (scheme.type) { switch (scheme.type) {
case EmbeddedType::DayBlue: case EmbeddedType::DayBlue:
result.lightnessMax = 160; result.lightnessMax = 160;
@ -148,10 +148,20 @@ Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
result.lightnessMin = 96; result.lightnessMin = 96;
break; break;
} }
result.now.lightness = std::clamp( const auto nowLightness = color.lightness();
result.now.lightness, const auto limitedLightness = std::clamp(
nowLightness,
result.lightnessMin, result.lightnessMin,
result.lightnessMax); result.lightnessMax);
if (limitedLightness != nowLightness) {
QColor::fromHsl(
color.hslHue(),
color.hslSaturation(),
limitedLightness).getHsv(
&result.now.hue,
&result.now.saturation,
&result.now.value);
}
return result; return result;
} }
@ -194,19 +204,19 @@ Colorizer ColorizerForTheme(const QString &absolutePath) {
? ((color.saturation * colorizer.now.saturation) ? ((color.saturation * colorizer.now.saturation)
/ colorizer.was.saturation) / colorizer.was.saturation)
: colorizer.now.saturation; : colorizer.now.saturation;
const auto nowLightness = (color.lightness > colorizer.was.lightness) const auto nowValue = (color.value > colorizer.was.value)
? (((colorizer.now.lightness * (255 - colorizer.was.lightness)) ? (((colorizer.now.value * (255 - colorizer.was.value))
+ ((color.lightness - colorizer.was.lightness) + ((color.value - colorizer.was.value)
* (255 - colorizer.now.lightness))) * (255 - colorizer.now.value)))
/ (255 - colorizer.was.lightness)) / (255 - colorizer.was.value))
: (color.lightness < colorizer.was.lightness) : (color.value < colorizer.was.value)
? ((color.lightness * colorizer.now.lightness) ? ((color.value * colorizer.now.value)
/ colorizer.was.lightness) / colorizer.was.value)
: colorizer.now.lightness; : colorizer.now.value;
return Colorizer::Color{ return Colorizer::Color{
((nowHue + 360) % 360), ((nowHue + 360) % 360),
nowSaturation, nowSaturation,
nowLightness nowValue
}; };
} }
@ -216,7 +226,7 @@ Colorizer ColorizerForTheme(const QString &absolutePath) {
auto hue = 0; auto hue = 0;
auto saturation = 0; auto saturation = 0;
auto lightness = 0; auto lightness = 0;
color.getHsl(&hue, &saturation, &lightness); color.getHsv(&hue, &saturation, &lightness);
const auto result = Colorize( const auto result = Colorize(
Colorizer::Color{ hue, saturation, lightness }, Colorizer::Color{ hue, saturation, lightness },
colorizer); colorizer);
@ -224,7 +234,7 @@ Colorizer ColorizerForTheme(const QString &absolutePath) {
return std::nullopt; return std::nullopt;
} }
const auto &fields = *result; const auto &fields = *result;
return QColor::fromHsl(fields.hue, fields.saturation, fields.lightness); return QColor::fromHsv(fields.hue, fields.saturation, fields.value);
} }
void FillColorizeResult(uchar &r, uchar &g, uchar &b, const QColor &color) { void FillColorizeResult(uchar &r, uchar &g, uchar &b, const QColor &color) {
@ -263,7 +273,13 @@ void Colorize(
const auto rgb = QColor(int(r), int(g), int(b)); const auto rgb = QColor(int(r), int(g), int(b));
const auto changed = Colorize(rgb, colorizer); const auto changed = Colorize(rgb, colorizer);
const auto checked = Colorize(check, colorizer).value_or(check); const auto checked = Colorize(check, colorizer).value_or(check);
const auto delta = std::abs(changed.value_or(rgb).lightness() - checked.lightness); const auto lightness = [](QColor hsv) {
return hsv.value() - (hsv.value() * hsv.saturation()) / 511;
};
const auto changedLightness = lightness(changed.value_or(rgb).toHsv());
const auto checkedLightness = lightness(
QColor::fromHsv(checked.hue, checked.saturation, checked.value));
const auto delta = std::abs(changedLightness - checkedLightness);
if (delta >= kEnoughLightnessForContrast) { if (delta >= kEnoughLightnessForContrast) {
if (changed) { if (changed) {
FillColorizeResult(r, g, b, *changed); FillColorizeResult(r, g, b, *changed);
@ -276,7 +292,7 @@ void Colorize(
r, r,
g, g,
b, b,
QColor::fromHsl(result.hue, result.saturation, result.lightness)); QColor::fromHsv(result.hue, result.saturation, result.value));
} }
void Colorize(uint32 &pixel, const Colorizer &colorizer) { void Colorize(uint32 &pixel, const Colorizer &colorizer) {
@ -392,7 +408,7 @@ std::vector<EmbeddedScheme> EmbeddedThemes() {
qColor("75bfb5"), qColor("75bfb5"),
tr::lng_settings_theme_matrix, tr::lng_settings_theme_matrix,
":/gui/night-green.tdesktop-theme", ":/gui/night-green.tdesktop-theme",
qColor("01ffdd") qColor("3fc1b0")
}, },
}; };
} }

View File

@ -51,7 +51,7 @@ struct Colorizer {
struct Color { struct Color {
int hue = 0; int hue = 0;
int saturation = 0; int saturation = 0;
int lightness = 0; int value = 0;
}; };
int hueThreshold = 0; int hueThreshold = 0;
int lightnessMin = 0; int lightnessMin = 0;