mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-20 18:40:57 +00:00
Add support for HSV color space in Adjust Hue/Saturation (fix #1559)
This commit is contained in:
parent
c3a0c00a62
commit
166cb55c97
@ -93,6 +93,10 @@
|
||||
<value id="LEFT" value="1" />
|
||||
<value id="RIGHT" value="2" />
|
||||
</enum>
|
||||
<enum id="HueSaturationMode">
|
||||
<value id="HSV" value="0" />
|
||||
<value id="HSL" value="1" />
|
||||
</enum>
|
||||
</types>
|
||||
|
||||
<global>
|
||||
@ -261,6 +265,9 @@
|
||||
<option id="show_alert" type="bool" default="true" />
|
||||
<option id="quality" type="double" default="1.0" migrate="JPEG.Quality" />
|
||||
</section>
|
||||
<section id="hue_saturation">
|
||||
<option id="mode" type="HueSaturationMode" default="HueSaturationMode::HSL" />
|
||||
</section>
|
||||
</global>
|
||||
|
||||
<tool>
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "app/context.h"
|
||||
#include "app/ini_file.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/pref/preferences.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/color_button.h"
|
||||
#include "app/ui/color_sliders.h"
|
||||
#include "base/bind.h"
|
||||
@ -40,25 +42,70 @@ public:
|
||||
WithChannelsSelector,
|
||||
WithoutTiledCheckBox)
|
||||
, m_filter(filter)
|
||||
, m_colorType(2)
|
||||
{
|
||||
getContainer()->addChild(&m_colorType);
|
||||
getContainer()->addChild(&m_sliders);
|
||||
|
||||
auto mode = Preferences::instance().hueSaturation.mode();
|
||||
m_colorType.addItem("HSV")->setFocusStop(false);
|
||||
m_colorType.addItem("HSL")->setFocusStop(false);
|
||||
if (mode == gen::HueSaturationMode::HSV)
|
||||
m_colorType.setSelectedItem(0);
|
||||
else
|
||||
m_colorType.setSelectedItem(1);
|
||||
m_colorType.ItemChange.connect(base::Bind<void>(&HueSaturationWindow::onChangeMode, this));
|
||||
|
||||
m_sliders.setColorType(app::Color::HslType);
|
||||
m_sliders.setMode(ColorSliders::Mode::Relative);
|
||||
m_sliders.ColorChange.connect(base::Bind<void>(&HueSaturationWindow::onChangeControls, this));
|
||||
|
||||
onChangeMode();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool isHsl() const {
|
||||
return (m_colorType.selectedItem() == 1);
|
||||
}
|
||||
|
||||
void onChangeMode() {
|
||||
const int isHsl = this->isHsl();
|
||||
|
||||
Preferences::instance().hueSaturation.mode
|
||||
(isHsl ? gen::HueSaturationMode::HSL:
|
||||
gen::HueSaturationMode::HSV);
|
||||
|
||||
m_filter.setMode(isHsl ?
|
||||
HueSaturationFilter::Mode::HSL:
|
||||
HueSaturationFilter::Mode::HSV);
|
||||
|
||||
m_sliders.setColorType(isHsl ?
|
||||
app::Color::HslType:
|
||||
app::Color::HsvType);
|
||||
|
||||
onChangeControls();
|
||||
}
|
||||
|
||||
void onChangeControls() {
|
||||
m_filter.setHue(
|
||||
double(m_sliders.getRelSliderValue(ColorSliders::Channel::HslHue)));
|
||||
|
||||
m_filter.setSaturation(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::HslSaturation) / 100.0);
|
||||
|
||||
m_filter.setLightness(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::HslLightness) / 100.0);
|
||||
m_sliders.syncRelHsvHslSliders();
|
||||
|
||||
if (isHsl()) {
|
||||
m_filter.setHue(
|
||||
double(m_sliders.getRelSliderValue(ColorSliders::Channel::HslHue)));
|
||||
m_filter.setSaturation(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::HslSaturation) / 100.0);
|
||||
m_filter.setLightness(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::HslLightness) / 100.0);
|
||||
}
|
||||
else {
|
||||
m_filter.setHue(
|
||||
double(m_sliders.getRelSliderValue(ColorSliders::Channel::HsvHue)));
|
||||
m_filter.setSaturation(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::HsvSaturation) / 100.0);
|
||||
m_filter.setLightness(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::HsvValue) / 100.0);
|
||||
}
|
||||
m_filter.setAlpha(
|
||||
m_sliders.getRelSliderValue(ColorSliders::Channel::Alpha) / 100.0);
|
||||
|
||||
@ -66,6 +113,7 @@ private:
|
||||
}
|
||||
|
||||
HueSaturationFilter& m_filter;
|
||||
ButtonSet m_colorType;
|
||||
ColorSliders m_sliders;
|
||||
};
|
||||
|
||||
|
@ -393,6 +393,12 @@ void ColorSliders::setAbsSliderValue(const Channel i, int value)
|
||||
updateEntryText(i);
|
||||
}
|
||||
|
||||
void ColorSliders::setRelSliderValue(const Channel i, int value)
|
||||
{
|
||||
m_items[i].relSlider->setValue(value);
|
||||
updateEntryText(i);
|
||||
}
|
||||
|
||||
int ColorSliders::getAbsSliderValue(const Channel i) const
|
||||
{
|
||||
return m_items[i].absSlider->getValue();
|
||||
@ -403,6 +409,22 @@ int ColorSliders::getRelSliderValue(const Channel i) const
|
||||
return m_items[i].relSlider->getValue();
|
||||
}
|
||||
|
||||
void ColorSliders::syncRelHsvHslSliders()
|
||||
{
|
||||
// From HSV -> HSL
|
||||
if (m_items[Channel::HsvHue].show) {
|
||||
setRelSliderValue(Channel::HslHue, getRelSliderValue(Channel::HsvHue));
|
||||
setRelSliderValue(Channel::HslSaturation, getRelSliderValue(Channel::HsvSaturation));
|
||||
setRelSliderValue(Channel::HslLightness, getRelSliderValue(Channel::HsvValue));
|
||||
}
|
||||
// From HSL -> HSV
|
||||
else if (m_items[Channel::HslHue].show) {
|
||||
setRelSliderValue(Channel::HsvHue, getRelSliderValue(Channel::HslHue));
|
||||
setRelSliderValue(Channel::HsvSaturation, getRelSliderValue(Channel::HslSaturation));
|
||||
setRelSliderValue(Channel::HsvValue, getRelSliderValue(Channel::HslLightness));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSliders::onSliderChange(const Channel i)
|
||||
{
|
||||
updateEntryText(i);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -46,6 +46,7 @@ namespace app {
|
||||
|
||||
int getAbsSliderValue(const Channel i) const;
|
||||
int getRelSliderValue(const Channel i) const;
|
||||
void syncRelHsvHslSliders();
|
||||
|
||||
// Signals
|
||||
obs::signal<void(ColorSlidersChangeEvent&)> ColorChange;
|
||||
@ -59,6 +60,7 @@ namespace app {
|
||||
const int absMin, const int absMax,
|
||||
const int relMin, const int relMax);
|
||||
void setAbsSliderValue(const Channel i, int value);
|
||||
void setRelSliderValue(const Channel i, int value);
|
||||
|
||||
void updateSlidersVisibility();
|
||||
void onSetColor(const app::Color& color);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "gfx/hsl.h"
|
||||
#include "gfx/hsv.h"
|
||||
#include "gfx/rgb.h"
|
||||
|
||||
#include <cmath>
|
||||
@ -30,13 +31,19 @@ const char* HueSaturationFilter::getName()
|
||||
}
|
||||
|
||||
HueSaturationFilter::HueSaturationFilter()
|
||||
: m_h(0.0)
|
||||
: m_mode(Mode::HSL)
|
||||
, m_h(0.0)
|
||||
, m_s(0.0)
|
||||
, m_l(0.0)
|
||||
, m_a(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
void HueSaturationFilter::setMode(Mode mode)
|
||||
{
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
void HueSaturationFilter::setHue(double h)
|
||||
{
|
||||
m_h = h;
|
||||
@ -93,7 +100,7 @@ void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
||||
c = fid->getNewPalette()->getEntry(i);
|
||||
}
|
||||
else {
|
||||
applyHslFilterToRgb(target, c);
|
||||
applyFilterToRgb(target, c);
|
||||
}
|
||||
|
||||
*(dst_address++) = c;
|
||||
@ -172,7 +179,7 @@ void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
}
|
||||
|
||||
color_t c = pal->getEntry(*(src_address++));
|
||||
applyHslFilterToRgb(target, c);
|
||||
applyFilterToRgb(target, c);
|
||||
*(dst_address++) = rgbmap->mapColor(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c),
|
||||
@ -195,21 +202,23 @@ void HueSaturationFilter::applyToPalette(FilterManager* filterMgr)
|
||||
}
|
||||
|
||||
color_t c = pal->getEntry(i);
|
||||
applyHslFilterToRgb(target, c);
|
||||
applyFilterToRgb(target, c);
|
||||
newPal->setEntry(i, c);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void HueSaturationFilter::applyHslFilterToRgb(
|
||||
const Target target, doc::color_t& c)
|
||||
template<class T,
|
||||
double (T::*get_lightness)() const,
|
||||
void (T::*set_lightness)(double)>
|
||||
void HueSaturationFilter::applyFilterToRgbT(const Target target, doc::color_t& c)
|
||||
{
|
||||
int r = rgba_getr(c);
|
||||
int g = rgba_getg(c);
|
||||
int b = rgba_getb(c);
|
||||
int a = rgba_geta(c);
|
||||
|
||||
gfx::Hsl hsl(gfx::Rgb(r, g, b));
|
||||
T hsl(gfx::Rgb(r, g, b));
|
||||
|
||||
double h = hsl.hue() + m_h;
|
||||
while (h < 0.0) h += 360.0;
|
||||
@ -218,12 +227,12 @@ void HueSaturationFilter::applyHslFilterToRgb(
|
||||
double s = hsl.saturation()*(1.0+m_s);
|
||||
s = MID(0.0, s, 1.0);
|
||||
|
||||
double l = hsl.lightness()*(1.0+m_l);
|
||||
double l = (hsl.*get_lightness)()*(1.0+m_l);
|
||||
l = MID(0.0, l, 1.0);
|
||||
|
||||
hsl.hue(h);
|
||||
hsl.saturation(s);
|
||||
hsl.lightness(l);
|
||||
(hsl.*set_lightness)(l);
|
||||
gfx::Rgb rgb(hsl);
|
||||
|
||||
if (target & TARGET_RED_CHANNEL ) r = rgb.red();
|
||||
@ -237,4 +246,20 @@ void HueSaturationFilter::applyHslFilterToRgb(
|
||||
c = rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
void HueSaturationFilter::applyFilterToRgb(const Target target, doc::color_t& color)
|
||||
{
|
||||
switch (m_mode) {
|
||||
case Mode::HSL:
|
||||
applyFilterToRgbT<gfx::Hsl,
|
||||
&gfx::Hsl::lightness,
|
||||
&gfx::Hsl::lightness>(target, color);
|
||||
break;
|
||||
case Mode::HSV:
|
||||
applyFilterToRgbT<gfx::Hsv,
|
||||
&gfx::Hsv::value,
|
||||
&gfx::Hsv::value>(target, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace filters
|
||||
|
@ -17,8 +17,11 @@ namespace filters {
|
||||
|
||||
class HueSaturationFilter : public Filter {
|
||||
public:
|
||||
enum class Mode { HSL, HSV };
|
||||
|
||||
HueSaturationFilter();
|
||||
|
||||
void setMode(Mode mode);
|
||||
void setHue(double h);
|
||||
void setSaturation(double s);
|
||||
void setLightness(double v);
|
||||
@ -32,8 +35,13 @@ namespace filters {
|
||||
|
||||
private:
|
||||
void applyToPalette(FilterManager* filterMgr);
|
||||
void applyHslFilterToRgb(const Target target, doc::color_t& color);
|
||||
template<class T,
|
||||
double (T::*get_lightness)() const,
|
||||
void (T::*set_lightness)(double)>
|
||||
void applyFilterToRgbT(const Target target, doc::color_t& color);
|
||||
void applyFilterToRgb(const Target target, doc::color_t& color);
|
||||
|
||||
Mode m_mode;
|
||||
double m_h, m_s, m_l, m_a;
|
||||
doc::PalettePicks m_picks;
|
||||
bool m_usePalette;
|
||||
|
Loading…
x
Reference in New Issue
Block a user