mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-11 09:19:35 +00:00
Apply saturation and value in colorizer.
This commit is contained in:
parent
529ef64257
commit
7de28fc4bd
@ -43,6 +43,58 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
namespace Settings {
|
namespace Settings {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const auto kColorizeIgnoredKeys = base::flat_set<QLatin1String>{ {
|
||||||
|
qstr("boxTextFgGood"),
|
||||||
|
qstr("boxTextFgError"),
|
||||||
|
qstr("historyPeer1NameFg"),
|
||||||
|
qstr("historyPeer1NameFgSelected"),
|
||||||
|
qstr("historyPeer1UserpicBg"),
|
||||||
|
qstr("historyPeer2NameFg"),
|
||||||
|
qstr("historyPeer2NameFgSelected"),
|
||||||
|
qstr("historyPeer2UserpicBg"),
|
||||||
|
qstr("historyPeer3NameFg"),
|
||||||
|
qstr("historyPeer3NameFgSelected"),
|
||||||
|
qstr("historyPeer3UserpicBg"),
|
||||||
|
qstr("historyPeer4NameFg"),
|
||||||
|
qstr("historyPeer4NameFgSelected"),
|
||||||
|
qstr("historyPeer4UserpicBg"),
|
||||||
|
qstr("historyPeer5NameFg"),
|
||||||
|
qstr("historyPeer5NameFgSelected"),
|
||||||
|
qstr("historyPeer5UserpicBg"),
|
||||||
|
qstr("historyPeer6NameFg"),
|
||||||
|
qstr("historyPeer6NameFgSelected"),
|
||||||
|
qstr("historyPeer6UserpicBg"),
|
||||||
|
qstr("historyPeer7NameFg"),
|
||||||
|
qstr("historyPeer7NameFgSelected"),
|
||||||
|
qstr("historyPeer7UserpicBg"),
|
||||||
|
qstr("historyPeer8NameFg"),
|
||||||
|
qstr("historyPeer8NameFgSelected"),
|
||||||
|
qstr("historyPeer8UserpicBg"),
|
||||||
|
qstr("msgFile1Bg"),
|
||||||
|
qstr("msgFile1BgDark"),
|
||||||
|
qstr("msgFile1BgOver"),
|
||||||
|
qstr("msgFile1BgSelected"),
|
||||||
|
qstr("msgFile2Bg"),
|
||||||
|
qstr("msgFile2BgDark"),
|
||||||
|
qstr("msgFile2BgOver"),
|
||||||
|
qstr("msgFile2BgSelected"),
|
||||||
|
qstr("msgFile3Bg"),
|
||||||
|
qstr("msgFile3BgDark"),
|
||||||
|
qstr("msgFile3BgOver"),
|
||||||
|
qstr("msgFile3BgSelected"),
|
||||||
|
qstr("msgFile4Bg"),
|
||||||
|
qstr("msgFile4BgDark"),
|
||||||
|
qstr("msgFile4BgOver"),
|
||||||
|
qstr("msgFile4BgSelected"),
|
||||||
|
qstr("mediaviewFileRedCornerFg"),
|
||||||
|
qstr("mediaviewFileYellowCornerFg"),
|
||||||
|
qstr("mediaviewFileGreenCornerFg"),
|
||||||
|
qstr("mediaviewFileBlueCornerFg"),
|
||||||
|
} };
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class BackgroundRow : public Ui::RpWidget {
|
class BackgroundRow : public Ui::RpWidget {
|
||||||
public:
|
public:
|
||||||
@ -876,10 +928,16 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
|||||||
scheme.accentColor));
|
scheme.accentColor));
|
||||||
box->setSaveCallback([=](QColor result) {
|
box->setSaveCallback([=](QColor result) {
|
||||||
auto colorizer = Window::Theme::Colorizer();
|
auto colorizer = Window::Theme::Colorizer();
|
||||||
|
colorizer.ignoreKeys = kColorizeIgnoredKeys;
|
||||||
colorizer.hueThreshold = 10;
|
colorizer.hueThreshold = 10;
|
||||||
colorizer.saturationThreshold = 10;
|
scheme.accentColor.getHsv(
|
||||||
colorizer.wasHue = scheme.accentColor.hue();
|
&colorizer.wasHue,
|
||||||
colorizer.nowHue = result.hue();
|
&colorizer.wasSaturation,
|
||||||
|
&colorizer.wasValue);
|
||||||
|
result.getHsv(
|
||||||
|
&colorizer.nowHue,
|
||||||
|
&colorizer.nowSaturation,
|
||||||
|
&colorizer.nowValue);
|
||||||
apply(scheme, &colorizer);
|
apply(scheme, &colorizer);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -153,24 +153,65 @@ void Colorize(
|
|||||||
auto saturation = 0;
|
auto saturation = 0;
|
||||||
auto value = 0;
|
auto value = 0;
|
||||||
color.getHsv(&hue, &saturation, &value);
|
color.getHsv(&hue, &saturation, &value);
|
||||||
if ((saturation < colorizer->saturationThreshold)
|
const auto changeColor = std::abs(hue - colorizer->wasHue)
|
||||||
|| (std::abs(hue - colorizer->wasHue) > colorizer->hueThreshold)) {
|
<= colorizer->hueThreshold;
|
||||||
return;
|
const auto nowHue = hue + (colorizer->nowHue - colorizer->wasHue);
|
||||||
}
|
const auto nowSaturation = ((saturation > colorizer->wasSaturation)
|
||||||
const auto changed = hue + (colorizer->nowHue - colorizer->wasHue);
|
&& (colorizer->nowSaturation > colorizer->wasSaturation))
|
||||||
|
? (((colorizer->nowSaturation * (255 - colorizer->wasSaturation))
|
||||||
|
+ ((saturation - colorizer->wasSaturation)
|
||||||
|
* (255 - colorizer->nowSaturation)))
|
||||||
|
/ (255 - colorizer->wasSaturation))
|
||||||
|
: ((saturation != colorizer->wasSaturation)
|
||||||
|
&& (colorizer->wasSaturation != 0))
|
||||||
|
? ((saturation * colorizer->nowSaturation)
|
||||||
|
/ colorizer->wasSaturation)
|
||||||
|
: colorizer->nowSaturation;
|
||||||
|
const auto nowValue = (value > colorizer->wasValue)
|
||||||
|
? (((colorizer->nowValue * (255 - colorizer->wasValue))
|
||||||
|
+ ((value - colorizer->wasValue)
|
||||||
|
* (255 - colorizer->nowValue)))
|
||||||
|
/ (255 - colorizer->wasValue))
|
||||||
|
: (value < colorizer->wasValue)
|
||||||
|
? ((value * colorizer->nowValue)
|
||||||
|
/ colorizer->wasValue)
|
||||||
|
: colorizer->nowValue;
|
||||||
auto nowR = 0;
|
auto nowR = 0;
|
||||||
auto nowG = 0;
|
auto nowG = 0;
|
||||||
auto nowB = 0;
|
auto nowB = 0;
|
||||||
QColor::fromHsv(
|
QColor::fromHsv(
|
||||||
(changed + 360) % 360,
|
changeColor ? ((nowHue + 360) % 360) : hue,
|
||||||
saturation,
|
changeColor ? nowSaturation : saturation,
|
||||||
value
|
nowValue
|
||||||
).getRgb(&nowR, &nowG, &nowB);
|
).getRgb(&nowR, &nowG, &nowB);
|
||||||
r = uchar(nowR);
|
r = uchar(nowR);
|
||||||
g = uchar(nowG);
|
g = uchar(nowG);
|
||||||
b = uchar(nowB);
|
b = uchar(nowB);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Colorize(uint32 &pixel, not_null<const Colorizer*> colorizer) {
|
||||||
|
const auto chars = reinterpret_cast<uchar*>(&pixel);
|
||||||
|
Colorize(
|
||||||
|
chars[2],
|
||||||
|
chars[1],
|
||||||
|
chars[0],
|
||||||
|
colorizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Colorize(QImage &image, not_null<const Colorizer*> colorizer) {
|
||||||
|
image = std::move(image).convertToFormat(QImage::Format_ARGB32);
|
||||||
|
const auto bytes = image.bits();
|
||||||
|
const auto bytesPerLine = image.bytesPerLine();
|
||||||
|
for (auto line = 0; line != image.height(); ++line) {
|
||||||
|
const auto ints = reinterpret_cast<uint32*>(
|
||||||
|
bytes + line * bytesPerLine);
|
||||||
|
const auto end = ints + image.width();
|
||||||
|
for (auto p = ints; p != end; ++p) {
|
||||||
|
Colorize(*p, colorizer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class SetResult {
|
enum class SetResult {
|
||||||
Ok,
|
Ok,
|
||||||
Bad,
|
Bad,
|
||||||
@ -190,7 +231,7 @@ SetResult setColorSchemeValue(
|
|||||||
auto g = readHexUchar(data[3], data[4], error);
|
auto g = readHexUchar(data[3], data[4], error);
|
||||||
auto b = readHexUchar(data[5], data[6], error);
|
auto b = readHexUchar(data[5], data[6], error);
|
||||||
auto a = (size == 9) ? readHexUchar(data[7], data[8], error) : uchar(255);
|
auto a = (size == 9) ? readHexUchar(data[7], data[8], error) : uchar(255);
|
||||||
if (colorizer) {
|
if (colorizer && !colorizer->ignoreKeys.contains(name)) {
|
||||||
Colorize(r, g, b, colorizer);
|
Colorize(r, g, b, colorizer);
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -362,6 +403,9 @@ bool loadTheme(
|
|||||||
LOG(("Theme Error: could not read background image in the theme file."));
|
LOG(("Theme Error: could not read background image in the theme file."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (colorizer) {
|
||||||
|
Colorize(background, colorizer);
|
||||||
|
}
|
||||||
auto buffer = QBuffer(&cache.background);
|
auto buffer = QBuffer(&cache.background);
|
||||||
if (!background.save(&buffer, "BMP")) {
|
if (!background.save(&buffer, "BMP")) {
|
||||||
LOG(("Theme Error: could not write background image as a BMP to cache."));
|
LOG(("Theme Error: could not write background image as a BMP to cache."));
|
||||||
|
@ -51,9 +51,13 @@ struct Preview {
|
|||||||
|
|
||||||
struct Colorizer {
|
struct Colorizer {
|
||||||
int wasHue = 0;
|
int wasHue = 0;
|
||||||
|
int wasSaturation = 0;
|
||||||
|
int wasValue = 0;
|
||||||
int nowHue = 0;
|
int nowHue = 0;
|
||||||
|
int nowSaturation = 0;
|
||||||
|
int nowValue = 0;
|
||||||
int hueThreshold = 0;
|
int hueThreshold = 0;
|
||||||
int saturationThreshold = 0;
|
base::flat_set<QLatin1String> ignoreKeys;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Apply(const QString &filepath);
|
bool Apply(const QString &filepath);
|
||||||
|
Loading…
Reference in New Issue
Block a user