mirror of
https://github.com/aseprite/aseprite.git
synced 2024-09-01 12:39:23 +00:00
Add HSL color selection (related to #707)
This commit is contained in:
parent
c297031152
commit
29a49ad7fa
@ -50,9 +50,11 @@
|
||||
<value id="RGB" value="4" />
|
||||
<value id="HSVA" value="5" />
|
||||
<value id="HSV" value="6" />
|
||||
<value id="GRAYA" value="7" />
|
||||
<value id="GRAY" value="8" />
|
||||
<value id="INDEX" value="9" />
|
||||
<value id="HSLA" value="7" />
|
||||
<value id="HSL" value="8" />
|
||||
<value id="GRAYA" value="9" />
|
||||
<value id="GRAY" value="10" />
|
||||
<value id="INDEX" value="11" />
|
||||
</enum>
|
||||
<enum id="EyedropperSample">
|
||||
<value id="ALL_LAYERS" value="0" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -12,11 +12,12 @@
|
||||
|
||||
#include "app/color_utils.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "gfx/hsv.h"
|
||||
#include "gfx/rgb.h"
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "gfx/hsl.h"
|
||||
#include "gfx/hsv.h"
|
||||
#include "gfx/rgb.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
@ -56,6 +57,17 @@ Color Color::fromHsv(double h, double s, double v, int a)
|
||||
return color;
|
||||
}
|
||||
|
||||
// static
|
||||
Color Color::fromHsl(double h, double s, double l, int a)
|
||||
{
|
||||
Color color(Color::HslType);
|
||||
color.m_value.hsl.h = h;
|
||||
color.m_value.hsl.s = s;
|
||||
color.m_value.hsl.l = l;
|
||||
color.m_value.hsl.a = a;
|
||||
return color;
|
||||
}
|
||||
|
||||
// static
|
||||
Color Color::fromGray(int g, int a)
|
||||
{
|
||||
@ -123,6 +135,7 @@ Color Color::fromString(const std::string& str)
|
||||
if (str != "mask") {
|
||||
if (str.find("rgb{") == 0 ||
|
||||
str.find("hsv{") == 0 ||
|
||||
str.find("hsl{") == 0 ||
|
||||
str.find("gray{") == 0) {
|
||||
int c = 0;
|
||||
double table[4] = { 0.0, 0.0, 0.0, 255.0 };
|
||||
@ -139,8 +152,16 @@ Color Color::fromString(const std::string& str)
|
||||
|
||||
if (str[0] == 'r')
|
||||
color = Color::fromRgb(int(table[0]), int(table[1]), int(table[2]), int(table[3]));
|
||||
else if (str[0] == 'h')
|
||||
color = Color::fromHsv(table[0], table[1], table[2], int(table[3]));
|
||||
else if (str[0] == 'h' && str[1] == 's' && str[2] == 'v')
|
||||
color = Color::fromHsv(table[0],
|
||||
table[1] / 100.0,
|
||||
table[2] / 100.0,
|
||||
int(table[3]));
|
||||
else if (str[0] == 'h' && str[1] == 's' && str[2] == 'l')
|
||||
color = Color::fromHsl(table[0],
|
||||
table[1] / 100.0,
|
||||
table[2] / 100.0,
|
||||
int(table[3]));
|
||||
else if (str[0] == 'g')
|
||||
color = Color::fromGray(int(table[0]), (c >= 2 ? int(table[1]): 255));
|
||||
}
|
||||
@ -175,11 +196,21 @@ std::string Color::toString() const
|
||||
<< std::setprecision(2)
|
||||
<< std::fixed
|
||||
<< m_value.hsv.h << ","
|
||||
<< m_value.hsv.s << ","
|
||||
<< m_value.hsv.v << ","
|
||||
<< MID(0.0, m_value.hsv.s*100.0, 100.0) << ","
|
||||
<< MID(0.0, m_value.hsv.v*100.0, 100.0) << ","
|
||||
<< m_value.hsv.a << "}";
|
||||
break;
|
||||
|
||||
case Color::HslType:
|
||||
result << "hsl{"
|
||||
<< std::setprecision(2)
|
||||
<< std::fixed
|
||||
<< m_value.hsl.h << ","
|
||||
<< MID(0.0, m_value.hsl.s*100.0, 100.0) << ","
|
||||
<< MID(0.0, m_value.hsl.l*100.0, 100.0) << ","
|
||||
<< m_value.hsl.a << "}";
|
||||
break;
|
||||
|
||||
case Color::GrayType:
|
||||
result << "gray{"
|
||||
<< m_value.gray.g << ","
|
||||
@ -227,10 +258,30 @@ std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableS
|
||||
result << "Gray " << getGray();
|
||||
}
|
||||
else {
|
||||
result << "HSB "
|
||||
result << "HSV "
|
||||
<< int(m_value.hsv.h) << "\xc2\xb0 "
|
||||
<< int(m_value.hsv.s) << "% "
|
||||
<< int(m_value.hsv.v) << "%";
|
||||
<< MID(0, int(m_value.hsv.s*100.0), 100) << "% "
|
||||
<< MID(0, int(m_value.hsv.v*100.0), 100) << "%";
|
||||
|
||||
if (pixelFormat == IMAGE_INDEXED)
|
||||
result << " Index " << color_utils::color_for_image(*this, pixelFormat);
|
||||
|
||||
result << " (RGB "
|
||||
<< getRed() << " "
|
||||
<< getGreen() << " "
|
||||
<< getBlue() << ")";
|
||||
}
|
||||
break;
|
||||
|
||||
case Color::HslType:
|
||||
if (pixelFormat == IMAGE_GRAYSCALE) {
|
||||
result << "Gray " << getGray();
|
||||
}
|
||||
else {
|
||||
result << "HSL "
|
||||
<< int(m_value.hsl.h) << "\xc2\xb0 "
|
||||
<< MID(0, int(m_value.hsl.s*100.0), 100) << "% "
|
||||
<< MID(0, int(m_value.hsl.l*100.0), 100) << "%";
|
||||
|
||||
if (pixelFormat == IMAGE_INDEXED)
|
||||
result << " Index " << color_utils::color_for_image(*this, pixelFormat);
|
||||
@ -299,8 +350,19 @@ std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableS
|
||||
}
|
||||
else {
|
||||
result << int(m_value.hsv.h) << "\xc2\xb0"
|
||||
<< int(m_value.hsv.s) << ","
|
||||
<< int(m_value.hsv.v);
|
||||
<< MID(0, int(m_value.hsv.s*100.0), 100) << ","
|
||||
<< MID(0, int(m_value.hsv.v*100.0), 100);
|
||||
}
|
||||
break;
|
||||
|
||||
case Color::HslType:
|
||||
if (pixelFormat == IMAGE_GRAYSCALE) {
|
||||
result << "Gry-" << getGray();
|
||||
}
|
||||
else {
|
||||
result << int(m_value.hsl.h) << "\xc2\xb0"
|
||||
<< MID(0, int(m_value.hsl.s*100.0), 100) << ","
|
||||
<< MID(0, int(m_value.hsl.l*100.0), 100);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -341,10 +403,17 @@ bool Color::operator==(const Color& other) const
|
||||
case Color::HsvType:
|
||||
return
|
||||
(std::fabs(m_value.hsv.h - other.m_value.hsv.h) < 0.001) &&
|
||||
(std::fabs(m_value.hsv.s - other.m_value.hsv.s) < 0.001) &&
|
||||
(std::fabs(m_value.hsv.v - other.m_value.hsv.v) < 0.001) &&
|
||||
(std::fabs(m_value.hsv.s - other.m_value.hsv.s) < 0.00001) &&
|
||||
(std::fabs(m_value.hsv.v - other.m_value.hsv.v) < 0.00001) &&
|
||||
(m_value.hsv.a == other.m_value.hsv.a);
|
||||
|
||||
case Color::HslType:
|
||||
return
|
||||
(std::fabs(m_value.hsl.h - other.m_value.hsl.h) < 0.001) &&
|
||||
(std::fabs(m_value.hsl.s - other.m_value.hsl.s) < 0.00001) &&
|
||||
(std::fabs(m_value.hsl.l - other.m_value.hsl.l) < 0.00001) &&
|
||||
(m_value.hsl.a == other.m_value.hsl.a);
|
||||
|
||||
case Color::GrayType:
|
||||
return
|
||||
m_value.gray.g == other.m_value.gray.g &&
|
||||
@ -387,8 +456,13 @@ int Color::getRed() const
|
||||
|
||||
case Color::HsvType:
|
||||
return Rgb(Hsv(m_value.hsv.h,
|
||||
m_value.hsv.s / 100.0,
|
||||
m_value.hsv.v / 100.0)).red();
|
||||
m_value.hsv.s,
|
||||
m_value.hsv.v)).red();
|
||||
|
||||
case Color::HslType:
|
||||
return Rgb(Hsl(m_value.hsl.h,
|
||||
m_value.hsl.s,
|
||||
m_value.hsl.l)).red();
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray.g;
|
||||
@ -419,8 +493,13 @@ int Color::getGreen() const
|
||||
|
||||
case Color::HsvType:
|
||||
return Rgb(Hsv(m_value.hsv.h,
|
||||
m_value.hsv.s / 100.0,
|
||||
m_value.hsv.v / 100.0)).green();
|
||||
m_value.hsv.s,
|
||||
m_value.hsv.v)).green();
|
||||
|
||||
case Color::HslType:
|
||||
return Rgb(Hsl(m_value.hsl.h,
|
||||
m_value.hsl.s,
|
||||
m_value.hsl.l)).green();
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray.g;
|
||||
@ -451,8 +530,13 @@ int Color::getBlue() const
|
||||
|
||||
case Color::HsvType:
|
||||
return Rgb(Hsv(m_value.hsv.h,
|
||||
m_value.hsv.s / 100.0,
|
||||
m_value.hsv.v / 100.0)).blue();
|
||||
m_value.hsv.s,
|
||||
m_value.hsv.v)).blue();
|
||||
|
||||
case Color::HslType:
|
||||
return Rgb(Hsl(m_value.hsl.h,
|
||||
m_value.hsl.s,
|
||||
m_value.hsl.l)).blue();
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray.g;
|
||||
@ -471,7 +555,7 @@ int Color::getBlue() const
|
||||
return -1;
|
||||
}
|
||||
|
||||
double Color::getHue() const
|
||||
double Color::getHsvHue() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
@ -486,6 +570,9 @@ double Color::getHue() const
|
||||
case Color::HsvType:
|
||||
return m_value.hsv.h;
|
||||
|
||||
case Color::HslType:
|
||||
return m_value.hsl.h;
|
||||
|
||||
case Color::GrayType:
|
||||
return 0.0;
|
||||
|
||||
@ -507,7 +594,7 @@ double Color::getHue() const
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double Color::getSaturation() const
|
||||
double Color::getHsvSaturation() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
@ -517,11 +604,16 @@ double Color::getSaturation() const
|
||||
case Color::RgbType:
|
||||
return Hsv(Rgb(m_value.rgb.r,
|
||||
m_value.rgb.g,
|
||||
m_value.rgb.b)).saturation() * 100.0;
|
||||
m_value.rgb.b)).saturation();
|
||||
|
||||
case Color::HsvType:
|
||||
return m_value.hsv.s;
|
||||
|
||||
case Color::HslType:
|
||||
return Hsv(Rgb(getRed(),
|
||||
getGreen(),
|
||||
getBlue())).saturation();
|
||||
|
||||
case Color::GrayType:
|
||||
return 0;
|
||||
|
||||
@ -531,7 +623,7 @@ double Color::getSaturation() const
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
return Hsv(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).saturation() * 100.0;
|
||||
rgba_getb(c))).saturation();
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
@ -543,7 +635,7 @@ double Color::getSaturation() const
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double Color::getValue() const
|
||||
double Color::getHsvValue() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
@ -553,13 +645,18 @@ double Color::getValue() const
|
||||
case Color::RgbType:
|
||||
return Hsv(Rgb(m_value.rgb.r,
|
||||
m_value.rgb.g,
|
||||
m_value.rgb.b)).value() * 100.0;
|
||||
m_value.rgb.b)).value();
|
||||
|
||||
case Color::HsvType:
|
||||
return m_value.hsv.v;
|
||||
|
||||
case Color::HslType:
|
||||
return Hsv(Rgb(getRed(),
|
||||
getGreen(),
|
||||
getBlue())).value();
|
||||
|
||||
case Color::GrayType:
|
||||
return 100.0 * m_value.gray.g / 255.0;
|
||||
return m_value.gray.g / 255.0;
|
||||
|
||||
case Color::IndexType: {
|
||||
int i = m_value.index;
|
||||
@ -567,7 +664,128 @@ double Color::getValue() const
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
return Hsv(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).value() * 100.0;
|
||||
rgba_getb(c))).value();
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double Color::getHslHue() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
case Color::MaskType:
|
||||
return 0.0;
|
||||
|
||||
case Color::RgbType:
|
||||
return Hsl(Rgb(m_value.rgb.r,
|
||||
m_value.rgb.g,
|
||||
m_value.rgb.b)).hue();
|
||||
|
||||
case Color::HsvType:
|
||||
return m_value.hsv.h;
|
||||
|
||||
case Color::HslType:
|
||||
return m_value.hsl.h;
|
||||
|
||||
case Color::GrayType:
|
||||
return 0.0;
|
||||
|
||||
case Color::IndexType: {
|
||||
int i = m_value.index;
|
||||
if (i >= 0 && i < get_current_palette()->size()) {
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
return Hsl(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).hue();
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double Color::getHslSaturation() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
case Color::MaskType:
|
||||
return 0;
|
||||
|
||||
case Color::RgbType:
|
||||
return Hsl(Rgb(m_value.rgb.r,
|
||||
m_value.rgb.g,
|
||||
m_value.rgb.b)).saturation();
|
||||
|
||||
case Color::HsvType:
|
||||
return Hsl(Rgb(getRed(),
|
||||
getGreen(),
|
||||
getBlue())).saturation();
|
||||
|
||||
case Color::HslType:
|
||||
return m_value.hsl.s;
|
||||
|
||||
case Color::GrayType:
|
||||
return 0;
|
||||
|
||||
case Color::IndexType: {
|
||||
int i = m_value.index;
|
||||
if (i >= 0 && i < get_current_palette()->size()) {
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
return Hsl(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).saturation();
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
double Color::getHslLightness() const
|
||||
{
|
||||
switch (getType()) {
|
||||
|
||||
case Color::MaskType:
|
||||
return 0.0;
|
||||
|
||||
case Color::RgbType:
|
||||
return Hsl(Rgb(m_value.rgb.r,
|
||||
m_value.rgb.g,
|
||||
m_value.rgb.b)).lightness();
|
||||
|
||||
case Color::HsvType:
|
||||
return Hsl(Rgb(getRed(),
|
||||
getGreen(),
|
||||
getBlue())).lightness();
|
||||
|
||||
case Color::HslType:
|
||||
return m_value.hsl.l;
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray.g / 255.0;
|
||||
|
||||
case Color::IndexType: {
|
||||
int i = m_value.index;
|
||||
if (i >= 0 && i < get_current_palette()->size()) {
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
return Hsl(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).lightness();
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
@ -587,12 +805,17 @@ int Color::getGray() const
|
||||
return 0;
|
||||
|
||||
case Color::RgbType:
|
||||
return int(255.0 * Hsv(Rgb(m_value.rgb.r,
|
||||
return int(255.0 * Hsl(Rgb(m_value.rgb.r,
|
||||
m_value.rgb.g,
|
||||
m_value.rgb.b)).value());
|
||||
m_value.rgb.b)).lightness());
|
||||
|
||||
case Color::HsvType:
|
||||
return int(255.0 * m_value.hsv.v / 100.0);
|
||||
return int(255.0 * Hsl(Rgb(getRed(),
|
||||
getGreen(),
|
||||
getBlue())).lightness());
|
||||
|
||||
case Color::HslType:
|
||||
return int(255.0 * m_value.hsl.l);
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray.g;
|
||||
@ -601,9 +824,9 @@ int Color::getGray() const
|
||||
int i = m_value.index;
|
||||
if (i >= 0 && i < get_current_palette()->size()) {
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
return int(255.0 * Hsv(Rgb(rgba_getr(c),
|
||||
return int(255.0 * Hsl(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).value());
|
||||
rgba_getb(c))).lightness());
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
@ -624,6 +847,7 @@ int Color::getIndex() const
|
||||
|
||||
case Color::RgbType:
|
||||
case Color::HsvType:
|
||||
case Color::HslType:
|
||||
case Color::GrayType: {
|
||||
int i = get_current_palette()->findExactMatch(getRed(), getGreen(), getBlue(), getAlpha(), -1);
|
||||
if (i >= 0)
|
||||
@ -654,6 +878,9 @@ int Color::getAlpha() const
|
||||
case Color::HsvType:
|
||||
return m_value.hsv.a;
|
||||
|
||||
case Color::HslType:
|
||||
return m_value.hsl.a;
|
||||
|
||||
case Color::GrayType:
|
||||
return m_value.gray.a;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -28,6 +28,7 @@ namespace app {
|
||||
MaskType,
|
||||
RgbType,
|
||||
HsvType,
|
||||
HslType,
|
||||
GrayType,
|
||||
IndexType,
|
||||
};
|
||||
@ -42,7 +43,8 @@ namespace app {
|
||||
|
||||
static Color fromMask();
|
||||
static Color fromRgb(int r, int g, int b, int a = 255);
|
||||
static Color fromHsv(double h, double s, double v, int a = 255); // h=[0,360], s=[0,100], v=[0,100]
|
||||
static Color fromHsv(double h, double s, double v, int a = 255); // h=[0,360], s=[0,1], v=[0,1]
|
||||
static Color fromHsl(double h, double s, double l, int a = 255); // h=[0,360], s=[0,1], v=[0,1]
|
||||
static Color fromGray(int g, int a = 255);
|
||||
static Color fromIndex(int index);
|
||||
|
||||
@ -68,9 +70,12 @@ namespace app {
|
||||
int getRed() const;
|
||||
int getGreen() const;
|
||||
int getBlue() const;
|
||||
double getHue() const;
|
||||
double getSaturation() const;
|
||||
double getValue() const;
|
||||
double getHsvHue() const;
|
||||
double getHsvSaturation() const;
|
||||
double getHsvValue() const;
|
||||
double getHslHue() const;
|
||||
double getHslSaturation() const;
|
||||
double getHslLightness() const;
|
||||
int getGray() const;
|
||||
int getIndex() const;
|
||||
int getAlpha() const;
|
||||
@ -90,6 +95,10 @@ namespace app {
|
||||
double h, s, v;
|
||||
int a;
|
||||
} hsv;
|
||||
struct {
|
||||
double h, s, l;
|
||||
int a;
|
||||
} hsl;
|
||||
struct {
|
||||
int g, a;
|
||||
} gray;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -20,28 +20,37 @@ namespace app {
|
||||
|
||||
TEST(Color, fromRgb)
|
||||
{
|
||||
EXPECT_EQ(32, Color::fromRgb(32, 16, 255).getRed());
|
||||
EXPECT_EQ(16, Color::fromRgb(32, 16, 255).getGreen());
|
||||
EXPECT_EQ( 32, Color::fromRgb(32, 16, 255).getRed());
|
||||
EXPECT_EQ( 16, Color::fromRgb(32, 16, 255).getGreen());
|
||||
EXPECT_EQ(255, Color::fromRgb(32, 16, 255).getBlue());
|
||||
}
|
||||
|
||||
TEST(Color, fromHsv)
|
||||
{
|
||||
EXPECT_EQ(60, Color::fromHsv(60, 5, 100).getHue());
|
||||
EXPECT_EQ(5, Color::fromHsv(60, 5, 100).getSaturation());
|
||||
EXPECT_EQ(100, Color::fromHsv(60, 5, 100).getValue());
|
||||
EXPECT_EQ(60.0, Color::fromHsv(60, 0.05, 1.0).getHsvHue());
|
||||
EXPECT_EQ(0.05, Color::fromHsv(60, 0.05, 1.0).getHsvSaturation());
|
||||
EXPECT_EQ(1.00, Color::fromHsv(60, 0.05, 1.0).getHsvValue());
|
||||
}
|
||||
|
||||
TEST(Color, fromHsl)
|
||||
{
|
||||
EXPECT_EQ(60.0, Color::fromHsl(60, 0.05, 1.0).getHslHue());
|
||||
EXPECT_EQ(0.05, Color::fromHsl(60, 0.05, 1.0).getHslSaturation());
|
||||
EXPECT_EQ(1.00, Color::fromHsl(60, 0.05, 1.0).getHslLightness());
|
||||
}
|
||||
|
||||
TEST(Color, fromString)
|
||||
{
|
||||
EXPECT_EQ(Color::fromRgb(0, 0, 0), Color::fromString("rgb{0,0.0,0}"));
|
||||
EXPECT_EQ(Color::fromRgb(32, 16, 255), Color::fromString("rgb{32,16,255}"));
|
||||
EXPECT_EQ(Color::fromHsv(32, 64, 99), Color::fromString("hsv{32,64,99}"));
|
||||
EXPECT_EQ(Color::fromHsv(32, 0.64, 0.99), Color::fromString("hsv{32,64,99}"));
|
||||
EXPECT_EQ(Color::fromHsl(32, 0.64, 0.99), Color::fromString("hsl{32,64,99}"));
|
||||
}
|
||||
|
||||
TEST(Color, toString)
|
||||
{
|
||||
EXPECT_EQ("rgb{0,0,0,255}", Color::fromRgb(0, 0, 0).toString());
|
||||
EXPECT_EQ("rgb{32,16,255,255}", Color::fromRgb(32, 16, 255).toString());
|
||||
EXPECT_EQ("hsv{32.00,64.00,99.00,255}", Color::fromHsv(32, 64, 99).toString());
|
||||
EXPECT_EQ("hsv{32.00,64.00,99.00,255}", Color::fromHsv(32, 64/100.0, 99/100.0).toString());
|
||||
EXPECT_EQ("hsl{32.00,64.00,99.00,255}", Color::fromHsl(32, 64/100.0, 99/100.0).toString());
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2015 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -48,6 +48,7 @@ gfx::Color color_utils::color_for_ui(const app::Color& color)
|
||||
|
||||
case app::Color::RgbType:
|
||||
case app::Color::HsvType:
|
||||
case app::Color::HslType:
|
||||
c = gfx::rgba(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -90,9 +90,16 @@ void EyedropperCommand::pickSample(const doc::Site& site,
|
||||
break;
|
||||
|
||||
case app::Color::HsvType:
|
||||
color = app::Color::fromHsv(color.getHue(),
|
||||
color.getSaturation(),
|
||||
color.getValue(),
|
||||
color = app::Color::fromHsv(color.getHsvHue(),
|
||||
color.getHsvSaturation(),
|
||||
color.getHsvValue(),
|
||||
picked.getAlpha());
|
||||
break;
|
||||
|
||||
case app::Color::HslType:
|
||||
color = app::Color::fromHsl(color.getHslHue(),
|
||||
color.getHslSaturation(),
|
||||
color.getHslLightness(),
|
||||
picked.getAlpha());
|
||||
break;
|
||||
|
||||
@ -123,16 +130,32 @@ void EyedropperCommand::pickSample(const doc::Site& site,
|
||||
if (picked.getType() == app::Color::HsvType)
|
||||
color = picked;
|
||||
else
|
||||
color = app::Color::fromHsv(picked.getHue(),
|
||||
picked.getSaturation(),
|
||||
picked.getValue(),
|
||||
color = app::Color::fromHsv(picked.getHsvHue(),
|
||||
picked.getHsvSaturation(),
|
||||
picked.getHsvValue(),
|
||||
picked.getAlpha());
|
||||
break;
|
||||
case app::gen::EyedropperChannel::HSV:
|
||||
if (picked.getAlpha() > 0)
|
||||
color = app::Color::fromHsv(picked.getHue(),
|
||||
picked.getSaturation(),
|
||||
picked.getValue(),
|
||||
color = app::Color::fromHsv(picked.getHsvHue(),
|
||||
picked.getHsvSaturation(),
|
||||
picked.getHsvValue(),
|
||||
color.getAlpha());
|
||||
break;
|
||||
case app::gen::EyedropperChannel::HSLA:
|
||||
if (picked.getType() == app::Color::HslType)
|
||||
color = picked;
|
||||
else
|
||||
color = app::Color::fromHsl(picked.getHslHue(),
|
||||
picked.getHslSaturation(),
|
||||
picked.getHslLightness(),
|
||||
picked.getAlpha());
|
||||
break;
|
||||
case app::gen::EyedropperChannel::HSL:
|
||||
if (picked.getAlpha() > 0)
|
||||
color = app::Color::fromHsl(picked.getHslHue(),
|
||||
picked.getHslSaturation(),
|
||||
picked.getHslLightness(),
|
||||
color.getAlpha());
|
||||
break;
|
||||
case app::gen::EyedropperChannel::GRAYA:
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2001-2016 David Capello
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -39,6 +39,7 @@
|
||||
#include "doc/image.h"
|
||||
#include "doc/palette.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "gfx/hsl.h"
|
||||
#include "gfx/hsv.h"
|
||||
#include "gfx/rgb.h"
|
||||
#include "gfx/size.h"
|
||||
@ -54,7 +55,7 @@ namespace app {
|
||||
using namespace gfx;
|
||||
using namespace ui;
|
||||
|
||||
enum { RGB_MODE, HSV_MODE };
|
||||
enum { RGB_MODE, HSV_MODE, HSL_MODE };
|
||||
enum { ABS_MODE, REL_MODE };
|
||||
|
||||
class PaletteEntryEditor : public Window {
|
||||
@ -97,6 +98,7 @@ private:
|
||||
Label m_entryLabel;
|
||||
RgbSliders m_rgbSliders;
|
||||
HsvSliders m_hsvSliders;
|
||||
HslSliders m_hslSliders;
|
||||
|
||||
// This variable is used to avoid updating the m_hexColorEntry text
|
||||
// when the color change is generated from a
|
||||
@ -241,7 +243,7 @@ PaletteEntryEditor::PaletteEntryEditor()
|
||||
, m_vbox(VERTICAL)
|
||||
, m_topBox(HORIZONTAL)
|
||||
, m_bottomBox(HORIZONTAL)
|
||||
, m_colorType(2)
|
||||
, m_colorType(3)
|
||||
, m_changeMode(2)
|
||||
, m_entryLabel("")
|
||||
, m_disableHexUpdate(false)
|
||||
@ -252,7 +254,8 @@ PaletteEntryEditor::PaletteEntryEditor()
|
||||
, m_fromPalette(0, 0)
|
||||
{
|
||||
m_colorType.addItem("RGB")->setFocusStop(false);
|
||||
m_colorType.addItem("HSB")->setFocusStop(false);
|
||||
m_colorType.addItem("HSV")->setFocusStop(false);
|
||||
m_colorType.addItem("HSL")->setFocusStop(false);
|
||||
m_changeMode.addItem("Abs")->setFocusStop(false);
|
||||
m_changeMode.addItem("Rel")->setFocusStop(false);
|
||||
|
||||
@ -273,6 +276,7 @@ PaletteEntryEditor::PaletteEntryEditor()
|
||||
m_vbox.addChild(&m_topBox);
|
||||
m_vbox.addChild(&m_rgbSliders);
|
||||
m_vbox.addChild(&m_hsvSliders);
|
||||
m_vbox.addChild(&m_hslSliders);
|
||||
m_vbox.addChild(&m_bottomBox);
|
||||
addChild(&m_vbox);
|
||||
|
||||
@ -281,6 +285,7 @@ PaletteEntryEditor::PaletteEntryEditor()
|
||||
|
||||
m_rgbSliders.ColorChange.connect(&PaletteEntryEditor::onColorSlidersChange, this);
|
||||
m_hsvSliders.ColorChange.connect(&PaletteEntryEditor::onColorSlidersChange, this);
|
||||
m_hslSliders.ColorChange.connect(&PaletteEntryEditor::onColorSlidersChange, this);
|
||||
m_hexColorEntry.ColorChange.connect(&PaletteEntryEditor::onColorHexEntryChange, this);
|
||||
|
||||
m_changeMode.setSelectedItem(ABS_MODE);
|
||||
@ -309,6 +314,7 @@ void PaletteEntryEditor::setColor(const app::Color& color)
|
||||
{
|
||||
m_rgbSliders.setColor(color);
|
||||
m_hsvSliders.setColor(color);
|
||||
m_hslSliders.setColor(color);
|
||||
if (!m_disableHexUpdate)
|
||||
m_hexColorEntry.setColor(color);
|
||||
|
||||
@ -455,6 +461,9 @@ void PaletteEntryEditor::onColorTypeClick()
|
||||
case HSV_MODE:
|
||||
selectColorType(app::Color::HsvType);
|
||||
break;
|
||||
case HSL_MODE:
|
||||
selectColorType(app::Color::HslType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,10 +473,12 @@ void PaletteEntryEditor::onChangeModeClick()
|
||||
case ABS_MODE:
|
||||
m_rgbSliders.setMode(ColorSliders::Absolute);
|
||||
m_hsvSliders.setMode(ColorSliders::Absolute);
|
||||
m_hslSliders.setMode(ColorSliders::Absolute);
|
||||
break;
|
||||
case REL_MODE:
|
||||
m_rgbSliders.setMode(ColorSliders::Relative);
|
||||
m_hsvSliders.setMode(ColorSliders::Relative);
|
||||
m_hslSliders.setMode(ColorSliders::Relative);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -541,46 +552,86 @@ void PaletteEntryEditor::setAbsolutePaletteEntryChannel(ColorSliders::Channel ch
|
||||
}
|
||||
break;
|
||||
|
||||
case app::Color::HsvType:
|
||||
{
|
||||
Hsv hsv;
|
||||
case app::Color::HsvType: {
|
||||
Hsv hsv;
|
||||
|
||||
// Modify one entry
|
||||
if (picksCount == 1) {
|
||||
hsv.hue(color.getHue());
|
||||
hsv.saturation(double(color.getSaturation()) / 100.0);
|
||||
hsv.value(double(color.getValue()) / 100.0);
|
||||
a = color.getAlpha();
|
||||
}
|
||||
// Modify one channel a set of entries
|
||||
else {
|
||||
// Convert RGB to HSV
|
||||
hsv = Hsv(Rgb(r, g, b));
|
||||
|
||||
// Only modify the desired HSV channel
|
||||
switch (channel) {
|
||||
case ColorSliders::Hue:
|
||||
hsv.hue(color.getHue());
|
||||
break;
|
||||
case ColorSliders::Saturation:
|
||||
hsv.saturation(double(color.getSaturation()) / 100.0);
|
||||
break;
|
||||
case ColorSliders::Value:
|
||||
hsv.value(double(color.getValue()) / 100.0);
|
||||
break;
|
||||
case ColorSliders::Alpha:
|
||||
a = color.getAlpha();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert HSV back to RGB
|
||||
Rgb rgb(hsv);
|
||||
r = rgb.red();
|
||||
g = rgb.green();
|
||||
b = rgb.blue();
|
||||
// Modify one entry
|
||||
if (picksCount == 1) {
|
||||
hsv.hue(color.getHsvHue());
|
||||
hsv.saturation(color.getHsvSaturation());
|
||||
hsv.value(color.getHsvValue());
|
||||
a = color.getAlpha();
|
||||
}
|
||||
// Modify one channel a set of entries
|
||||
else {
|
||||
// Convert RGB to HSV
|
||||
hsv = Hsv(Rgb(r, g, b));
|
||||
|
||||
// Only modify the desired HSV channel
|
||||
switch (channel) {
|
||||
case ColorSliders::HsvHue:
|
||||
hsv.hue(color.getHsvHue());
|
||||
break;
|
||||
case ColorSliders::HsvSaturation:
|
||||
hsv.saturation(color.getHsvSaturation());
|
||||
break;
|
||||
case ColorSliders::HsvValue:
|
||||
hsv.value(color.getHsvValue());
|
||||
break;
|
||||
case ColorSliders::Alpha:
|
||||
a = color.getAlpha();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert HSV back to RGB
|
||||
Rgb rgb(hsv);
|
||||
r = rgb.red();
|
||||
g = rgb.green();
|
||||
b = rgb.blue();
|
||||
break;
|
||||
}
|
||||
|
||||
case app::Color::HslType: {
|
||||
Hsl hsl;
|
||||
|
||||
// Modify one entry
|
||||
if (picksCount == 1) {
|
||||
hsl.hue(color.getHslHue());
|
||||
hsl.saturation(color.getHslSaturation());
|
||||
hsl.lightness(color.getHslLightness());
|
||||
a = color.getAlpha();
|
||||
}
|
||||
// Modify one channel a set of entries
|
||||
else {
|
||||
// Convert RGB to HSL
|
||||
hsl = Hsl(Rgb(r, g, b));
|
||||
|
||||
// Only modify the desired HSL channel
|
||||
switch (channel) {
|
||||
case ColorSliders::HslHue:
|
||||
hsl.hue(color.getHslHue());
|
||||
break;
|
||||
case ColorSliders::HslSaturation:
|
||||
hsl.saturation(color.getHslSaturation());
|
||||
break;
|
||||
case ColorSliders::HslLightness:
|
||||
hsl.lightness(color.getHslLightness());
|
||||
break;
|
||||
case ColorSliders::Alpha:
|
||||
a = color.getAlpha();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert HSL back to RGB
|
||||
Rgb rgb(hsl);
|
||||
r = rgb.red();
|
||||
g = rgb.green();
|
||||
b = rgb.blue();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
palette->setEntry(c, doc::rgba(r, g, b, a));
|
||||
@ -613,9 +664,9 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
|
||||
switch (m_type) {
|
||||
|
||||
case app::Color::RgbType:
|
||||
r = MID(0, r+m_relDeltas[ColorSliders::Red], 255);
|
||||
r = MID(0, r+m_relDeltas[ColorSliders::Red], 255);
|
||||
g = MID(0, g+m_relDeltas[ColorSliders::Green], 255);
|
||||
b = MID(0, b+m_relDeltas[ColorSliders::Blue], 255);
|
||||
b = MID(0, b+m_relDeltas[ColorSliders::Blue], 255);
|
||||
a = MID(0, a+m_relDeltas[ColorSliders::Alpha], 255);
|
||||
break;
|
||||
|
||||
@ -623,16 +674,16 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
|
||||
// Convert RGB to HSV
|
||||
Hsv hsv(Rgb(r, g, b));
|
||||
|
||||
double h = hsv.hue()+m_relDeltas[ColorSliders::Hue];
|
||||
double s = 100.0*hsv.saturation()+m_relDeltas[ColorSliders::Saturation];
|
||||
double v = 100.0*hsv.value()+m_relDeltas[ColorSliders::Value];
|
||||
double h = hsv.hue() +m_relDeltas[ColorSliders::HsvHue];
|
||||
double s = hsv.saturation()+m_relDeltas[ColorSliders::HsvSaturation]/100.0;
|
||||
double v = hsv.value() +m_relDeltas[ColorSliders::HsvValue] /100.0;
|
||||
|
||||
if (h < 0.0) h += 360.0;
|
||||
else if (h > 360.0) h -= 360.0;
|
||||
|
||||
hsv.hue (MID(0.0, h, 360.0));
|
||||
hsv.saturation(MID(0.0, s, 100.0) / 100.0);
|
||||
hsv.value (MID(0.0, v, 100.0) / 100.0);
|
||||
hsv.saturation(MID(0.0, s, 1.0));
|
||||
hsv.value (MID(0.0, v, 1.0));
|
||||
|
||||
// Convert HSV back to RGB
|
||||
Rgb rgb(hsv);
|
||||
@ -643,6 +694,30 @@ void PaletteEntryEditor::setRelativePaletteEntryChannel(ColorSliders::Channel ch
|
||||
break;
|
||||
}
|
||||
|
||||
case app::Color::HslType: {
|
||||
// Convert RGB to HSL
|
||||
Hsl hsl(Rgb(r, g, b));
|
||||
|
||||
double h = hsl.hue() +m_relDeltas[ColorSliders::HslHue];
|
||||
double s = hsl.saturation()+m_relDeltas[ColorSliders::HslSaturation]/100.0;
|
||||
double l = hsl.lightness() +m_relDeltas[ColorSliders::HslLightness] /100.0;
|
||||
|
||||
if (h < 0.0) h += 360.0;
|
||||
else if (h > 360.0) h -= 360.0;
|
||||
|
||||
hsl.hue (h);
|
||||
hsl.saturation(MID(0.0, s, 1.0));
|
||||
hsl.lightness (MID(0.0, l, 1.0));
|
||||
|
||||
// Convert HSL back to RGB
|
||||
Rgb rgb(hsl);
|
||||
r = rgb.red();
|
||||
g = rgb.green();
|
||||
b = rgb.blue();
|
||||
a = MID(0, a+m_relDeltas[ColorSliders::Alpha], 255);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
palette->setEntry(c, doc::rgba(r, g, b, a));
|
||||
@ -654,12 +729,14 @@ void PaletteEntryEditor::selectColorType(app::Color::Type type)
|
||||
m_type = type;
|
||||
m_rgbSliders.setVisible(type == app::Color::RgbType);
|
||||
m_hsvSliders.setVisible(type == app::Color::HsvType);
|
||||
m_hslSliders.setVisible(type == app::Color::HslType);
|
||||
|
||||
resetRelativeInfo();
|
||||
|
||||
switch (type) {
|
||||
case app::Color::RgbType: m_colorType.setSelectedItem(RGB_MODE); break;
|
||||
case app::Color::HsvType: m_colorType.setSelectedItem(HSV_MODE); break;
|
||||
case app::Color::HslType: m_colorType.setSelectedItem(HSL_MODE); break;
|
||||
}
|
||||
|
||||
m_vbox.layout();
|
||||
@ -747,6 +824,7 @@ void PaletteEntryEditor::resetRelativeInfo()
|
||||
{
|
||||
m_rgbSliders.resetRelativeSliders();
|
||||
m_hsvSliders.resetRelativeSliders();
|
||||
m_hslSliders.resetRelativeSliders();
|
||||
get_current_palette()->copyColorsTo(&m_fromPalette);
|
||||
m_relDeltas.clear();
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ private:
|
||||
m_filter.setHue(double(m_sliders.getRelSliderValue(0)));
|
||||
m_filter.setSaturation(m_sliders.getRelSliderValue(1) / 100.0);
|
||||
m_filter.setLightness(m_sliders.getRelSliderValue(2) / 100.0);
|
||||
m_filter.setAlpha(m_sliders.getRelSliderValue(3));
|
||||
|
||||
restartPreview();
|
||||
}
|
||||
@ -90,7 +91,8 @@ void HueSaturationCommand::onExecute(Context* context)
|
||||
filterMgr.setTarget(TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_GRAY_CHANNEL);
|
||||
TARGET_GRAY_CHANNEL |
|
||||
TARGET_ALPHA_CHANNEL);
|
||||
|
||||
HueSaturationWindow window(filter, filterMgr);
|
||||
window.doModal();
|
||||
|
@ -44,9 +44,11 @@ using namespace doc;
|
||||
enum {
|
||||
INDEX_MODE,
|
||||
RGB_MODE,
|
||||
HSB_MODE,
|
||||
HSV_MODE,
|
||||
HSL_MODE,
|
||||
GRAY_MODE,
|
||||
MASK_MODE
|
||||
MASK_MODE,
|
||||
COLOR_MODES
|
||||
};
|
||||
|
||||
static base::UniquePtr<doc::Palette> g_simplePal(nullptr);
|
||||
@ -124,7 +126,7 @@ ColorPopup::ColorPopup(const bool canPin,
|
||||
, m_color(app::Color::fromMask())
|
||||
, m_colorPalette(false, PaletteView::SelectOneColor, this, 7*guiscale())
|
||||
, m_simpleColors(nullptr)
|
||||
, m_colorType(5)
|
||||
, m_colorType(COLOR_MODES)
|
||||
, m_maskLabel("Transparent Color Selected")
|
||||
, m_canPin(canPin)
|
||||
, m_disableHexUpdate(false)
|
||||
@ -145,7 +147,8 @@ ColorPopup::ColorPopup(const bool canPin,
|
||||
|
||||
m_colorType.addItem("Index")->setFocusStop(false);
|
||||
m_colorType.addItem("RGB")->setFocusStop(false);
|
||||
m_colorType.addItem("HSB")->setFocusStop(false);
|
||||
m_colorType.addItem("HSV")->setFocusStop(false);
|
||||
m_colorType.addItem("HSL")->setFocusStop(false);
|
||||
m_colorType.addItem("Gray")->setFocusStop(false);
|
||||
m_colorType.addItem("Mask")->setFocusStop(false);
|
||||
|
||||
@ -156,6 +159,7 @@ ColorPopup::ColorPopup(const bool canPin,
|
||||
m_colorPaletteContainer.setExpansive(true);
|
||||
m_rgbSliders.setExpansive(true);
|
||||
m_hsvSliders.setExpansive(true);
|
||||
m_hslSliders.setExpansive(true);
|
||||
m_graySlider.setExpansive(true);
|
||||
|
||||
m_topBox.addChild(&m_colorType);
|
||||
@ -190,6 +194,7 @@ ColorPopup::ColorPopup(const bool canPin,
|
||||
m_vbox.addChild(&m_colorPaletteContainer);
|
||||
m_vbox.addChild(&m_rgbSliders);
|
||||
m_vbox.addChild(&m_hsvSliders);
|
||||
m_vbox.addChild(&m_hslSliders);
|
||||
m_vbox.addChild(&m_graySlider);
|
||||
m_vbox.addChild(&m_maskLabel);
|
||||
addChild(&m_vbox);
|
||||
@ -198,6 +203,7 @@ ColorPopup::ColorPopup(const bool canPin,
|
||||
|
||||
m_rgbSliders.ColorChange.connect(&ColorPopup::onColorSlidersChange, this);
|
||||
m_hsvSliders.ColorChange.connect(&ColorPopup::onColorSlidersChange, this);
|
||||
m_hslSliders.ColorChange.connect(&ColorPopup::onColorSlidersChange, this);
|
||||
m_graySlider.ColorChange.connect(&ColorPopup::onColorSlidersChange, this);
|
||||
m_hexColorEntry.ColorChange.connect(&ColorPopup::onColorHexEntryChange, this);
|
||||
|
||||
@ -240,6 +246,7 @@ void ColorPopup::setColor(const app::Color& color, SetColorOptions options)
|
||||
|
||||
m_rgbSliders.setColor(m_color);
|
||||
m_hsvSliders.setColor(m_color);
|
||||
m_hslSliders.setColor(m_color);
|
||||
m_graySlider.setColor(m_color);
|
||||
if (!m_disableHexUpdate)
|
||||
m_hexColorEntry.setColor(m_color);
|
||||
@ -340,10 +347,16 @@ void ColorPopup::onColorTypeClick()
|
||||
newColor.getBlue(),
|
||||
newColor.getAlpha());
|
||||
break;
|
||||
case HSB_MODE:
|
||||
newColor = app::Color::fromHsv(newColor.getHue(),
|
||||
newColor.getSaturation(),
|
||||
newColor.getValue(),
|
||||
case HSV_MODE:
|
||||
newColor = app::Color::fromHsv(newColor.getHsvHue(),
|
||||
newColor.getHsvSaturation(),
|
||||
newColor.getHsvValue(),
|
||||
newColor.getAlpha());
|
||||
break;
|
||||
case HSL_MODE:
|
||||
newColor = app::Color::fromHsl(newColor.getHslHue(),
|
||||
newColor.getHslSaturation(),
|
||||
newColor.getHslLightness(),
|
||||
newColor.getAlpha());
|
||||
break;
|
||||
case GRAY_MODE:
|
||||
@ -393,18 +406,20 @@ void ColorPopup::selectColorType(app::Color::Type type)
|
||||
m_colorPaletteContainer.setVisible(type == app::Color::IndexType);
|
||||
m_rgbSliders.setVisible(type == app::Color::RgbType);
|
||||
m_hsvSliders.setVisible(type == app::Color::HsvType);
|
||||
m_hslSliders.setVisible(type == app::Color::HslType);
|
||||
m_graySlider.setVisible(type == app::Color::GrayType);
|
||||
m_maskLabel.setVisible(type == app::Color::MaskType);
|
||||
|
||||
switch (type) {
|
||||
case app::Color::IndexType: m_colorType.setSelectedItem(INDEX_MODE); break;
|
||||
case app::Color::RgbType: m_colorType.setSelectedItem(RGB_MODE); break;
|
||||
case app::Color::HsvType: m_colorType.setSelectedItem(HSB_MODE); break;
|
||||
case app::Color::HsvType: m_colorType.setSelectedItem(HSV_MODE); break;
|
||||
case app::Color::HslType: m_colorType.setSelectedItem(HSL_MODE); break;
|
||||
case app::Color::GrayType: m_colorType.setSelectedItem(GRAY_MODE); break;
|
||||
case app::Color::MaskType: m_colorType.setSelectedItem(MASK_MODE); break;
|
||||
}
|
||||
|
||||
// Remove focus from hidden RGB/HSB text entries
|
||||
// Remove focus from hidden RGB/HSV/HSL text entries
|
||||
auto widget = manager()->getFocus();
|
||||
if (widget && !widget->isVisible()) {
|
||||
auto window = widget->window();
|
||||
|
@ -71,6 +71,7 @@ namespace app {
|
||||
HexColorEntry m_hexColorEntry;
|
||||
RgbSliders m_rgbSliders;
|
||||
HsvSliders m_hsvSliders;
|
||||
HslSliders m_hslSliders;
|
||||
GraySlider m_graySlider;
|
||||
ui::Label m_maskLabel;
|
||||
obs::scoped_connection m_onPaletteChangeConn;
|
||||
|
@ -53,7 +53,7 @@ bool ColorSelector::onProcessMessage(ui::Message* msg)
|
||||
scale = 15.0;
|
||||
}
|
||||
|
||||
double newHue = m_color.getHue()
|
||||
double newHue = m_color.getHsvHue()
|
||||
+ scale*(+ static_cast<MouseMessage*>(msg)->wheelDelta().x
|
||||
- static_cast<MouseMessage*>(msg)->wheelDelta().y);
|
||||
|
||||
@ -61,12 +61,12 @@ bool ColorSelector::onProcessMessage(ui::Message* msg)
|
||||
newHue += 360.0;
|
||||
newHue = std::fmod(newHue, 360.0);
|
||||
|
||||
if (newHue != m_color.getHue()) {
|
||||
if (newHue != m_color.getHsvHue()) {
|
||||
app::Color newColor =
|
||||
app::Color::fromHsv(
|
||||
newHue,
|
||||
m_color.getSaturation(),
|
||||
m_color.getValue());
|
||||
m_color.getHsvSaturation(),
|
||||
m_color.getHsvValue());
|
||||
|
||||
ColorChange(newColor, kButtonNone);
|
||||
}
|
||||
|
@ -62,18 +62,49 @@ namespace {
|
||||
case ColorSliders::Blue:
|
||||
color = gfx::rgba(m_color.getRed(), m_color.getGreen(), 255 * x / w);
|
||||
break;
|
||||
case ColorSliders::Hue:
|
||||
color = color_utils::color_for_ui(app::Color::fromHsv(360 * x / w, m_color.getSaturation(), m_color.getValue()));
|
||||
|
||||
case ColorSliders::HsvHue:
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(360.0 * x / w,
|
||||
m_color.getHsvSaturation(),
|
||||
m_color.getHsvValue()));
|
||||
break;
|
||||
case ColorSliders::Saturation:
|
||||
color = color_utils::color_for_ui(app::Color::fromHsv(m_color.getHue(), 100 * x / w, m_color.getValue()));
|
||||
case ColorSliders::HsvSaturation:
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(m_color.getHsvHue(),
|
||||
double(x) / double(w),
|
||||
m_color.getHsvValue()));
|
||||
break;
|
||||
case ColorSliders::Value:
|
||||
color = color_utils::color_for_ui(app::Color::fromHsv(m_color.getHue(), m_color.getSaturation(), 100 * x / w));
|
||||
case ColorSliders::HsvValue:
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(m_color.getHsvHue(),
|
||||
m_color.getHsvSaturation(),
|
||||
double(x) / double(w)));
|
||||
break;
|
||||
|
||||
case ColorSliders::HslHue:
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(360.0 * x / w,
|
||||
m_color.getHslSaturation(),
|
||||
m_color.getHslLightness()));
|
||||
break;
|
||||
case ColorSliders::HslSaturation:
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(m_color.getHslHue(),
|
||||
double(x) / double(w),
|
||||
m_color.getHslLightness()));
|
||||
break;
|
||||
case ColorSliders::HslLightness:
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromHsl(m_color.getHslHue(),
|
||||
m_color.getHslSaturation(),
|
||||
double(x) / double(w)));
|
||||
break;
|
||||
|
||||
case ColorSliders::Gray:
|
||||
case ColorSliders::Alpha:
|
||||
color = color_utils::color_for_ui(app::Color::fromGray(255 * x / w));
|
||||
color = color_utils::color_for_ui(
|
||||
app::Color::fromGray(255 * x / w));
|
||||
break;
|
||||
}
|
||||
g->drawVLine(color, rc.x+x, rc.y, rc.h);
|
||||
@ -390,25 +421,25 @@ app::Color RgbSliders::getColorFromSliders()
|
||||
HsvSliders::HsvSliders()
|
||||
: ColorSliders()
|
||||
{
|
||||
addSlider(Hue, "H", 0, 360, -180, 180);
|
||||
addSlider(Saturation, "S", 0, 100, -100, 100);
|
||||
addSlider(Value, "B", 0, 100, -100, 100);
|
||||
addSlider(Alpha, "A", 0, 255, -255, 255);
|
||||
addSlider(HsvHue, "H", 0, 360, -180, 180);
|
||||
addSlider(HsvSaturation, "S", 0, 100, -100, 100);
|
||||
addSlider(HsvValue, "V", 0, 100, -100, 100);
|
||||
addSlider(Alpha, "A", 0, 255, -255, 255);
|
||||
}
|
||||
|
||||
void HsvSliders::onSetColor(const app::Color& color)
|
||||
{
|
||||
setAbsSliderValue(0, int(color.getHue()));
|
||||
setAbsSliderValue(1, int(color.getSaturation()));
|
||||
setAbsSliderValue(2, int(color.getValue()));
|
||||
setAbsSliderValue(0, int(color.getHsvHue()));
|
||||
setAbsSliderValue(1, int(color.getHsvSaturation() * 100.0));
|
||||
setAbsSliderValue(2, int(color.getHsvValue() * 100.0));
|
||||
setAbsSliderValue(3, color.getAlpha());
|
||||
}
|
||||
|
||||
app::Color HsvSliders::getColorFromSliders()
|
||||
{
|
||||
return app::Color::fromHsv(getAbsSliderValue(0),
|
||||
getAbsSliderValue(1),
|
||||
getAbsSliderValue(2),
|
||||
getAbsSliderValue(1) / 100.0,
|
||||
getAbsSliderValue(2) / 100.0,
|
||||
getAbsSliderValue(3));
|
||||
}
|
||||
|
||||
@ -418,31 +449,26 @@ app::Color HsvSliders::getColorFromSliders()
|
||||
HslSliders::HslSliders()
|
||||
: ColorSliders()
|
||||
{
|
||||
addSlider(Hue, "H", 0, 360, -180, 180);
|
||||
addSlider(Saturation, "S", 0, 100, -100, 100);
|
||||
addSlider(Value, "L", 0, 100, -100, 100);
|
||||
addSlider(HslHue, "H", 0, 360, -180, 180);
|
||||
addSlider(HslSaturation, "S", 0, 100, -100, 100);
|
||||
addSlider(HslLightness, "L", 0, 100, -100, 100);
|
||||
addSlider(Alpha, "A", 0, 255, -255, 255);
|
||||
}
|
||||
|
||||
void HslSliders::onSetColor(const app::Color& color)
|
||||
{
|
||||
gfx::Hsl hsl(gfx::Rgb(color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue()));
|
||||
|
||||
setAbsSliderValue(0, hsl.hue());
|
||||
setAbsSliderValue(1, hsl.saturation() * 100.0);
|
||||
setAbsSliderValue(2, hsl.lightness() * 100.0);
|
||||
setAbsSliderValue(0, int(color.getHslHue()));
|
||||
setAbsSliderValue(1, int(color.getHslSaturation() * 100.0));
|
||||
setAbsSliderValue(2, int(color.getHslLightness() * 100.0));
|
||||
setAbsSliderValue(3, color.getAlpha());
|
||||
}
|
||||
|
||||
app::Color HslSliders::getColorFromSliders()
|
||||
{
|
||||
gfx::Hsl hsl(getAbsSliderValue(0),
|
||||
getAbsSliderValue(1) / 100.0,
|
||||
getAbsSliderValue(2) / 100.0);
|
||||
gfx::Rgb rgb(hsl);
|
||||
return app::Color::fromRgb(rgb.red(),
|
||||
rgb.green(),
|
||||
rgb.blue(), 255);
|
||||
return app::Color::fromHsl(getAbsSliderValue(0),
|
||||
getAbsSliderValue(1) / 100.0,
|
||||
getAbsSliderValue(2) / 100.0,
|
||||
getAbsSliderValue(3));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -29,9 +29,9 @@ namespace app {
|
||||
class ColorSliders : public ui::Widget {
|
||||
public:
|
||||
enum Channel { Red, Green, Blue,
|
||||
Hue, Saturation, Value,
|
||||
Gray,
|
||||
Alpha };
|
||||
HsvHue, HsvSaturation, HsvValue,
|
||||
HslHue, HslSaturation, HslLightness,
|
||||
Gray, Alpha };
|
||||
enum Mode { Absolute, Relative };
|
||||
|
||||
ColorSliders();
|
||||
|
@ -55,13 +55,13 @@ app::Color ColorSpectrum::getColorByPosition(const gfx::Point& pos)
|
||||
}
|
||||
|
||||
double hue = 360.0 * u / umax;
|
||||
double sat = (v < vmid ? 100.0 * v / vmid : 100.0);
|
||||
double val = (v < vmid ? 100.0 : 100.0-(100.0 * (v-vmid) / vmid));
|
||||
double sat = (v < vmid ? double(v) / double(vmid) : 1.0);
|
||||
double val = (v < vmid ? 1.0 : 1.0-(double(v-vmid) / double(vmid)));
|
||||
|
||||
return app::Color::fromHsv(
|
||||
MID(0.0, hue, 360.0),
|
||||
MID(0.0, sat, 100.0),
|
||||
MID(0.0, val, 100.0));
|
||||
MID(0.0, sat, 1.0),
|
||||
MID(0.0, val, 1.0));
|
||||
}
|
||||
|
||||
void ColorSpectrum::onPaint(ui::PaintEvent& ev)
|
||||
@ -95,31 +95,31 @@ void ColorSpectrum::onPaint(ui::PaintEvent& ev)
|
||||
}
|
||||
|
||||
double hue = 360.0 * u / umax;
|
||||
double sat = (v < vmid ? 100.0 * v / vmid : 100.0);
|
||||
double val = (v < vmid ? 100.0 : 100.0-(100.0 * (v-vmid) / vmid));
|
||||
double sat = (v < vmid ? double(v) / double(vmid) : 1.0);
|
||||
double val = (v < vmid ? 1.0 : 1.0-(double(v-vmid) / double(vmid)));
|
||||
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
MID(0.0, hue, 360.0),
|
||||
MID(0.0, sat, 100.0),
|
||||
MID(0.0, val, 100.0)));
|
||||
MID(0.0, sat, 1.0),
|
||||
MID(0.0, val, 1.0)));
|
||||
|
||||
g->putPixel(color, rc.x+x, rc.y+y);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double hue = m_color.getHue();
|
||||
double sat = m_color.getSaturation();
|
||||
double val = m_color.getValue();
|
||||
double lit = (200.0 - sat) * val / 200.0;
|
||||
double hue = m_color.getHsvHue();
|
||||
double sat = m_color.getHsvSaturation();
|
||||
double val = m_color.getHsvValue();
|
||||
double lit = (2.0 - sat) * val / 2.0;
|
||||
gfx::Point pos(rc.x + int(hue * rc.w / 360.0),
|
||||
rc.y + rc.h - int(lit * rc.h / 100.0));
|
||||
rc.y + rc.h - int(lit * rc.h));
|
||||
|
||||
she::Surface* icon = theme->parts.colorWheelIndicator()->bitmap(0);
|
||||
g->drawColoredRgbaSurface(
|
||||
icon,
|
||||
lit > 50.0 ? gfx::rgba(0, 0, 0): gfx::rgba(255, 255, 255),
|
||||
lit > 0.5 ? gfx::rgba(0, 0, 0): gfx::rgba(255, 255, 255),
|
||||
pos.x-icon->width()/2,
|
||||
pos.y-icon->height()/2);
|
||||
}
|
||||
|
@ -54,19 +54,19 @@ app::Color ColorTintShadeTone::getColorByPosition(const gfx::Point& pos)
|
||||
|
||||
if (inHue) {
|
||||
hue = (360.0 * u / umax);
|
||||
sat = m_color.getSaturation();
|
||||
val = m_color.getValue();
|
||||
sat = m_color.getHsvSaturation();
|
||||
val = m_color.getHsvValue();
|
||||
}
|
||||
else {
|
||||
hue = m_color.getHue();
|
||||
sat = (100.0 * u / umax);
|
||||
val = (100.0 - 100.0 * v / vmax);
|
||||
hue = m_color.getHsvHue();
|
||||
sat = (1.0 * u / umax);
|
||||
val = (1.0 - double(v) / double(vmax));
|
||||
}
|
||||
|
||||
return app::Color::fromHsv(
|
||||
MID(0.0, hue, 360.0),
|
||||
MID(0.0, sat, 100.0),
|
||||
MID(0.0, val, 100.0));
|
||||
MID(0.0, sat, 1.0),
|
||||
MID(0.0, val, 1.0));
|
||||
}
|
||||
|
||||
void ColorTintShadeTone::onPaint(ui::PaintEvent& ev)
|
||||
@ -82,7 +82,7 @@ void ColorTintShadeTone::onPaint(ui::PaintEvent& ev)
|
||||
if (rc.isEmpty())
|
||||
return;
|
||||
|
||||
double hue = m_color.getHue();
|
||||
double hue = m_color.getHsvHue();
|
||||
int umax, vmax;
|
||||
int huebar = getHueBarSize();
|
||||
umax = MAX(1, rc.w-1);
|
||||
@ -90,14 +90,14 @@ void ColorTintShadeTone::onPaint(ui::PaintEvent& ev)
|
||||
|
||||
for (int y=0; y<rc.h-huebar; ++y) {
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
double sat = (100.0 * x / umax);
|
||||
double val = (100.0 - 100.0 * y / vmax);
|
||||
double sat = double(x) / double(umax);
|
||||
double val = 1.0 - double(y) / double(vmax);
|
||||
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
hue,
|
||||
MID(0.0, sat, 100.0),
|
||||
MID(0.0, val, 100.0)));
|
||||
MID(0.0, sat, 1.0),
|
||||
MID(0.0, val, 1.0)));
|
||||
|
||||
g->putPixel(color, rc.x+x, rc.y+y);
|
||||
}
|
||||
@ -108,7 +108,7 @@ void ColorTintShadeTone::onPaint(ui::PaintEvent& ev)
|
||||
for (int x=0; x<rc.w; ++x) {
|
||||
gfx::Color color = color_utils::color_for_ui(
|
||||
app::Color::fromHsv(
|
||||
(360.0 * x / rc.w), 100.0, 100.0));
|
||||
(360.0 * x / rc.w), 1.0, 1.0));
|
||||
|
||||
g->putPixel(color, rc.x+x, rc.y+y);
|
||||
}
|
||||
@ -116,15 +116,15 @@ void ColorTintShadeTone::onPaint(ui::PaintEvent& ev)
|
||||
}
|
||||
|
||||
if (m_color.getType() != app::Color::MaskType) {
|
||||
double sat = m_color.getSaturation();
|
||||
double val = m_color.getValue();
|
||||
gfx::Point pos(rc.x + int(sat * rc.w / 100.0),
|
||||
rc.y + int((100.0-val) * (rc.h-huebar) / 100.0));
|
||||
double sat = m_color.getHsvSaturation();
|
||||
double val = m_color.getHsvValue();
|
||||
gfx::Point pos(rc.x + int(sat * rc.w),
|
||||
rc.y + int((1.0-val) * (rc.h-huebar)));
|
||||
|
||||
she::Surface* icon = theme->parts.colorWheelIndicator()->bitmap(0);
|
||||
g->drawColoredRgbaSurface(
|
||||
icon,
|
||||
val > 50.0 ? gfx::rgba(0, 0, 0): gfx::rgba(255, 255, 255),
|
||||
val > 0.5 ? gfx::rgba(0, 0, 0): gfx::rgba(255, 255, 255),
|
||||
pos.x-icon->width()/2,
|
||||
pos.y-icon->height()/2);
|
||||
|
||||
|
@ -105,8 +105,8 @@ app::Color ColorWheel::getColorInClientPos(const gfx::Point& pos)
|
||||
|
||||
return app::Color::fromHsv(
|
||||
MID(0, hue, 360),
|
||||
MID(0, sat, 100),
|
||||
100);
|
||||
MID(0, sat / 100.0, 1.0),
|
||||
1.0);
|
||||
}
|
||||
|
||||
// Pick harmonies
|
||||
@ -123,9 +123,9 @@ app::Color ColorWheel::getColorInClientPos(const gfx::Point& pos)
|
||||
boxsize, boxsize).contains(pos)) {
|
||||
m_harmonyPicked = true;
|
||||
|
||||
color = app::Color::fromHsv(convertHueAngle(int(color.getHue()), 1),
|
||||
color.getSaturation(),
|
||||
color.getValue());
|
||||
color = app::Color::fromHsv(convertHueAngle(int(color.getHsvHue()), 1),
|
||||
color.getHsvSaturation(),
|
||||
color.getHsvValue());
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@ -168,11 +168,11 @@ app::Color ColorWheel::getColorInHarmony(int j) const
|
||||
{
|
||||
int i = MID(0, (int)m_harmony, (int)Harmony::LAST);
|
||||
j = MID(0, j, harmonies[i].n-1);
|
||||
double hue = convertHueAngle(int(m_color.getHue()), -1) + harmonies[i].hues[j];
|
||||
double sat = m_color.getSaturation() * harmonies[i].sats[j] / 100.0;
|
||||
double hue = convertHueAngle(int(m_color.getHsvHue()), -1) + harmonies[i].hues[j];
|
||||
double sat = m_color.getHsvSaturation() * harmonies[i].sats[j] / 100.0;
|
||||
return app::Color::fromHsv(std::fmod(hue, 360),
|
||||
MID(0.0, sat, 100.0),
|
||||
m_color.getValue());
|
||||
MID(0.0, sat, 1.0),
|
||||
m_color.getHsvValue());
|
||||
}
|
||||
|
||||
void ColorWheel::onResize(ui::ResizeEvent& ev)
|
||||
@ -230,17 +230,17 @@ void ColorWheel::onPaint(ui::PaintEvent& ev)
|
||||
|
||||
for (int i=0; i<n; ++i) {
|
||||
app::Color color = getColorInHarmony(i);
|
||||
double angle = color.getHue()-30.0;
|
||||
double dist = color.getSaturation();
|
||||
double angle = color.getHsvHue()-30.0;
|
||||
double dist = color.getHsvSaturation();
|
||||
|
||||
color = app::Color::fromHsv(convertHueAngle(int(color.getHue()), 1),
|
||||
color.getSaturation(),
|
||||
color.getValue());
|
||||
color = app::Color::fromHsv(convertHueAngle(int(color.getHsvHue()), 1),
|
||||
color.getHsvSaturation(),
|
||||
color.getHsvValue());
|
||||
|
||||
gfx::Point pos =
|
||||
m_wheelBounds.center() +
|
||||
gfx::Point(int(+std::cos(PI*angle/180.0)*double(m_wheelRadius)*dist/100.0),
|
||||
int(-std::sin(PI*angle/180.0)*double(m_wheelRadius)*dist/100.0));
|
||||
gfx::Point(int(+std::cos(PI*angle/180.0)*double(m_wheelRadius)*dist),
|
||||
int(-std::sin(PI*angle/180.0)*double(m_wheelRadius)*dist));
|
||||
|
||||
she::Surface* icon = theme->parts.colorWheelIndicator()->bitmap(0);
|
||||
g->drawRgbaSurface(icon,
|
||||
|
@ -1249,8 +1249,10 @@ public:
|
||||
m_channel.addItem("Alpha");
|
||||
m_channel.addItem("RGB+Alpha");
|
||||
m_channel.addItem("RGB");
|
||||
m_channel.addItem("HSB+Alpha");
|
||||
m_channel.addItem("HSB");
|
||||
m_channel.addItem("HSV+Alpha");
|
||||
m_channel.addItem("HSV");
|
||||
m_channel.addItem("HSL+Alpha");
|
||||
m_channel.addItem("HSL");
|
||||
m_channel.addItem("Gray+Alpha");
|
||||
m_channel.addItem("Gray");
|
||||
m_channel.addItem("Best fit Index");
|
||||
|
@ -951,6 +951,7 @@ int PaletteView::findExactIndex(const app::Color& color) const
|
||||
|
||||
case Color::RgbType:
|
||||
case Color::HsvType:
|
||||
case Color::HslType:
|
||||
case Color::GrayType:
|
||||
return currentPalette()->findExactMatch(
|
||||
color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha(), -1);
|
||||
|
@ -33,6 +33,7 @@ HueSaturationFilter::HueSaturationFilter()
|
||||
: m_h(0.0)
|
||||
, m_s(0.0)
|
||||
, m_l(0.0)
|
||||
, m_a(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -51,6 +52,11 @@ void HueSaturationFilter::setLightness(double l)
|
||||
m_l = l;
|
||||
}
|
||||
|
||||
void HueSaturationFilter::setAlpha(int a)
|
||||
{
|
||||
m_a = a;
|
||||
}
|
||||
|
||||
void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
|
||||
@ -95,6 +101,9 @@ void HueSaturationFilter::applyToRgba(FilterManager* filterMgr)
|
||||
if (target & TARGET_RED_CHANNEL ) r = rgb.red();
|
||||
if (target & TARGET_GREEN_CHANNEL) g = rgb.green();
|
||||
if (target & TARGET_BLUE_CHANNEL ) b = rgb.blue();
|
||||
|
||||
if (a && (target & TARGET_ALPHA_CHANNEL))
|
||||
a = MID(0, a+m_a, 255);
|
||||
}
|
||||
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
@ -131,6 +140,9 @@ void HueSaturationFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
gfx::Rgb rgb(hsl);
|
||||
|
||||
if (target & TARGET_GRAY_CHANNEL) k = rgb.red();
|
||||
|
||||
if (a && (target & TARGET_ALPHA_CHANNEL))
|
||||
a = MID(0, a+m_a, 255);
|
||||
}
|
||||
|
||||
*(dst_address++) = graya(k, a);
|
||||
@ -182,6 +194,9 @@ void HueSaturationFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
if (target & TARGET_RED_CHANNEL ) r = rgb.red();
|
||||
if (target & TARGET_GREEN_CHANNEL) g = rgb.green();
|
||||
if (target & TARGET_BLUE_CHANNEL ) b = rgb.blue();
|
||||
|
||||
if (a && (target & TARGET_ALPHA_CHANNEL))
|
||||
a = MID(0, a+m_a, 255);
|
||||
}
|
||||
|
||||
c = rgbmap->mapColor(r, g, b, a);
|
||||
|
@ -19,6 +19,7 @@ namespace filters {
|
||||
void setHue(double h);
|
||||
void setSaturation(double s);
|
||||
void setLightness(double v);
|
||||
void setAlpha(int a);
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
@ -28,6 +29,7 @@ namespace filters {
|
||||
|
||||
private:
|
||||
double m_h, m_s, m_l;
|
||||
int m_a;
|
||||
};
|
||||
|
||||
} // namespace filters
|
||||
|
@ -18,16 +18,12 @@ using namespace std;
|
||||
|
||||
Hsl::Hsl(double hue, double saturation, double lightness)
|
||||
: m_hue(hue)
|
||||
, m_saturation(saturation)
|
||||
, m_lightness(lightness)
|
||||
, m_saturation(MID(0.0, saturation, 1.0))
|
||||
, m_lightness(MID(0.0, lightness, 1.0))
|
||||
{
|
||||
while (m_hue < 0.0)
|
||||
m_hue += 360.0;
|
||||
m_hue = std::fmod(m_hue, 360.0);
|
||||
|
||||
assert(hue >= 0.0 && hue <= 360.0);
|
||||
assert(saturation >= 0.0 && saturation <= 1.0);
|
||||
assert(lightness >= 0.0 && lightness <= 1.0);
|
||||
}
|
||||
|
||||
Hsl::Hsl(const Rgb& rgb)
|
||||
@ -76,17 +72,17 @@ Hsl::Hsl(const Rgb& rgb)
|
||||
|
||||
int Hsl::hueInt() const
|
||||
{
|
||||
return int(floor(m_hue + 0.5));
|
||||
return int(std::floor(m_hue + 0.5));
|
||||
}
|
||||
|
||||
int Hsl::saturationInt() const
|
||||
{
|
||||
return int(floor(m_saturation*100.0 + 0.5));
|
||||
return int(std::floor(m_saturation*100.0 + 0.5));
|
||||
}
|
||||
|
||||
int Hsl::lightnessInt() const
|
||||
{
|
||||
return int(floor(m_lightness*100.0 + 0.5));
|
||||
return int(std::floor(m_lightness*100.0 + 0.5));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define GFX_HSL_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include "base/base.h" // MID
|
||||
|
||||
namespace gfx {
|
||||
|
||||
@ -48,18 +48,15 @@ public:
|
||||
int lightnessInt() const;
|
||||
|
||||
void hue(double hue) {
|
||||
assert(hue >= 0.0 && hue <= 360.0);
|
||||
m_hue = hue;
|
||||
m_hue = MID(0.0, hue, 360.0);
|
||||
}
|
||||
|
||||
void saturation(double saturation) {
|
||||
assert(saturation >= 0.0 && saturation <= 1.0);
|
||||
m_saturation = saturation;
|
||||
m_saturation = MID(0.0, saturation, 1.0);
|
||||
}
|
||||
|
||||
void lightness(double lightness) {
|
||||
assert(lightness >= 0.0 && lightness <= 1.0);
|
||||
m_lightness = lightness;
|
||||
m_lightness = MID(0.0, lightness, 1.0);
|
||||
}
|
||||
|
||||
// The comparison is done through the integer value of each component.
|
||||
|
@ -18,16 +18,12 @@ using namespace std;
|
||||
|
||||
Hsv::Hsv(double hue, double saturation, double value)
|
||||
: m_hue(hue)
|
||||
, m_saturation(saturation)
|
||||
, m_value(value)
|
||||
, m_saturation(MID(0.0, saturation, 1.0))
|
||||
, m_value(MID(0.0, value, 1.0))
|
||||
{
|
||||
while (m_hue < 0.0)
|
||||
m_hue += 360.0;
|
||||
m_hue = std::fmod(m_hue, 360.0);
|
||||
|
||||
assert(hue >= 0.0 && hue <= 360.0);
|
||||
assert(saturation >= 0.0 && saturation <= 1.0);
|
||||
assert(value >= 0.0 && value <= 1.0);
|
||||
}
|
||||
|
||||
// Reference: http://en.wikipedia.org/wiki/HSL_and_HSV
|
||||
@ -77,17 +73,17 @@ Hsv::Hsv(const Rgb& rgb)
|
||||
|
||||
int Hsv::hueInt() const
|
||||
{
|
||||
return int(floor(m_hue + 0.5));
|
||||
return int(std::floor(m_hue + 0.5));
|
||||
}
|
||||
|
||||
int Hsv::saturationInt() const
|
||||
{
|
||||
return int(floor(m_saturation*100.0 + 0.5));
|
||||
return int(std::floor(m_saturation*100.0 + 0.5));
|
||||
}
|
||||
|
||||
int Hsv::valueInt() const
|
||||
{
|
||||
return int(floor(m_value*100.0 + 0.5));
|
||||
return int(std::floor(m_value*100.0 + 0.5));
|
||||
}
|
||||
|
||||
} // namespace gfx
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define GFX_HSV_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include "base/base.h" // MID
|
||||
|
||||
namespace gfx {
|
||||
|
||||
@ -48,18 +48,15 @@ public:
|
||||
int valueInt() const;
|
||||
|
||||
void hue(double hue) {
|
||||
assert(hue >= 0.0 && hue <= 360.0);
|
||||
m_hue = hue;
|
||||
m_hue = MID(0.0, hue, 360.0);
|
||||
}
|
||||
|
||||
void saturation(double saturation) {
|
||||
assert(saturation >= 0.0 && saturation <= 1.0);
|
||||
m_saturation = saturation;
|
||||
m_saturation = MID(0.0, saturation, 1.0);
|
||||
}
|
||||
|
||||
void value(double value) {
|
||||
assert(value >= 0.0 && value <= 1.0);
|
||||
m_value = value;
|
||||
m_value = MID(0.0, value, 1.0);
|
||||
}
|
||||
|
||||
// The comparison is done through the integer value of each component.
|
||||
|
Loading…
Reference in New Issue
Block a user