243 lines
7.8 KiB
C++
243 lines
7.8 KiB
C++
/* +-------------------------------------------------------+
|
|
____/ \____ /| Open source game framework licensed to freely use, |
|
|
\ / / | copy, and modify, created for dank.game |
|
|
+--\ ^__^ /--+ | |
|
|
| ~/ \~ | | Download at https://open.shampoo.ooo/shampoo/spacebox |
|
|
| ~~~~~~~~~~~~ | +-------------------------------------------------------+
|
|
| SPACE ~~~~~ | /
|
|
| ~~~~~~~ BOX |/
|
|
+-------------*/
|
|
|
|
#include "Color.hpp"
|
|
|
|
sb::Color::Color() : sb::Color(0, 0, 0, 0) {}
|
|
|
|
sb::Color::Color(const SDL_Color& color) : sb::Color(color.r, color.g, color.b, color.a) {};
|
|
|
|
void sb::Color::percent(float red, float green, float blue)
|
|
{
|
|
r = std::round(255.0f * red);
|
|
g = std::round(255.0f * green);
|
|
b = std::round(255.0f * blue);
|
|
}
|
|
|
|
void sb::Color::percent(float red, float green, float blue, float alpha)
|
|
{
|
|
a = std::round(255.0f * alpha);
|
|
sb::Color::percent(red, green, blue);
|
|
}
|
|
|
|
void sb::Color::hsv(float hue, float saturation, float value)
|
|
{
|
|
float red_percent, green_percent, blue_percent;
|
|
HSVtoRGB(red_percent, green_percent, blue_percent, hue, saturation, value);
|
|
sb::Color::percent(red_percent, green_percent, blue_percent);
|
|
}
|
|
|
|
float sb::Color::hue() const
|
|
{
|
|
float hue, saturation, value;
|
|
float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f;
|
|
RGBtoHSV(red_percent, green_percent, blue_percent, hue, saturation, value);
|
|
return hue;
|
|
}
|
|
|
|
void sb::Color::shift_hue(float offset)
|
|
{
|
|
float hue, saturation, value;
|
|
float red_percent = r / 255.0f, green_percent = g / 255.0f, blue_percent = b / 255.0f;
|
|
RGBtoHSV(red_percent, green_percent, blue_percent, hue, saturation, value);
|
|
hue = std::fmod(hue + offset, 360.0f);
|
|
HSVtoRGB(red_percent, green_percent, blue_percent, hue, saturation, value);
|
|
percent(red_percent, green_percent, blue_percent);
|
|
}
|
|
|
|
sb::Color::operator std::uint32_t() const
|
|
{
|
|
SDL_PixelFormat* format = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA32);
|
|
std::uint32_t pixel = SDL_MapRGBA(format, r, g, b, a);
|
|
SDL_FreeFormat(format);
|
|
return pixel;
|
|
}
|
|
|
|
sb::Color::operator std::uint16_t() const
|
|
{
|
|
SDL_PixelFormat* format = SDL_AllocFormat(SDL_PIXELFORMAT_RGBA4444);
|
|
std::uint16_t pixel = SDL_MapRGBA(format, r, g, b, a);
|
|
SDL_FreeFormat(format);
|
|
return pixel;
|
|
}
|
|
|
|
sb::Color::operator std::uint8_t() const
|
|
{
|
|
SDL_PixelFormat* format = SDL_AllocFormat(SDL_PIXELFORMAT_RGB332);
|
|
std::uint8_t pixel = SDL_MapRGBA(format, r, g, b, a);
|
|
SDL_FreeFormat(format);
|
|
return pixel;
|
|
}
|
|
|
|
bool sb::Color::operator==(const sb::Color& color) const
|
|
{
|
|
return r == color.r && g == color.g && b == color.b && a == color.a;
|
|
}
|
|
|
|
bool sb::Color::operator!=(const sb::Color& color) const
|
|
{
|
|
return !(*this == color);
|
|
}
|
|
|
|
bool sb::Color::operator<(const sb::Color& color) const
|
|
{
|
|
return r < color.r || g < color.g || b < color.b || a < color.a;
|
|
}
|
|
|
|
glm::vec4 sb::Color::normal() const
|
|
{
|
|
return glm::vec4{r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f};
|
|
}
|
|
|
|
std::ostream& std::operator<<(std::ostream& out, const sb::Color& color)
|
|
{
|
|
float h, s, v;
|
|
RGBtoHSV(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, h, s, v);
|
|
out << "{r=" << static_cast<int>(color.r) << ", g=" << static_cast<int>(color.g) << ", b=" <<
|
|
static_cast<int>(color.b) << ", a= " << static_cast<int>(color.a) << ", h=" << h <<
|
|
", s=" << s << ", v=" << v << "}";
|
|
return out;
|
|
}
|
|
|
|
/*
|
|
The following copyright applies to RGBtoHSV and HSVtoRGB:
|
|
*/
|
|
|
|
//
|
|
// Copyright (c) 2014, Jan Winkler <winkler@cs.uni-bremen.de>
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of Universität Bremen nor the names of its
|
|
// contributors may be used to endorse or promote products derived from
|
|
// this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
/*! \brief Convert RGB to HSV color space
|
|
|
|
Converts a given set of RGB values `r', `g', `b' into HSV
|
|
coordinates. The input RGB values are in the range [0, 1], and the
|
|
output HSV values are in the ranges h = [0, 360], and s, v = [0,
|
|
1], respectively.
|
|
|
|
\param fR Red component, used as input, range: [0, 1]
|
|
\param fG Green component, used as input, range: [0, 1]
|
|
\param fB Blue component, used as input, range: [0, 1]
|
|
\param fH Hue component, used as output, range: [0, 360]
|
|
\param fS Hue component, used as output, range: [0, 1]
|
|
\param fV Hue component, used as output, range: [0, 1]
|
|
|
|
*/
|
|
void RGBtoHSV(const float& fR, const float& fG, const float& fB, float& fH, float& fS, float& fV) {
|
|
float fCMax = std::max(std::max(fR, fG), fB);
|
|
float fCMin = std::min(std::min(fR, fG), fB);
|
|
float fDelta = fCMax - fCMin;
|
|
|
|
if(fDelta > 0) {
|
|
if(fCMax == fR) {
|
|
fH = 60 * (std::fmod(((fG - fB) / fDelta), 6));
|
|
} else if(fCMax == fG) {
|
|
fH = 60 * (((fB - fR) / fDelta) + 2);
|
|
} else if(fCMax == fB) {
|
|
fH = 60 * (((fR - fG) / fDelta) + 4);
|
|
}
|
|
|
|
if(fCMax > 0) {
|
|
fS = fDelta / fCMax;
|
|
} else {
|
|
fS = 0;
|
|
}
|
|
|
|
fV = fCMax;
|
|
} else {
|
|
fH = 0;
|
|
fS = 0;
|
|
fV = fCMax;
|
|
}
|
|
|
|
if(fH < 0) {
|
|
fH = 360 + fH;
|
|
}
|
|
}
|
|
|
|
/*! \brief Convert HSV to RGB color space
|
|
|
|
Converts a given set of HSV values `h', `s', `v' into RGB
|
|
coordinates. The output RGB values are in the range [0, 1], and
|
|
the input HSV values are in the ranges h = [0, 360], and s, v =
|
|
[0, 1], respectively.
|
|
|
|
\param fR Red component, used as output, range: [0, 1]
|
|
\param fG Green component, used as output, range: [0, 1]
|
|
\param fB Blue component, used as output, range: [0, 1]
|
|
\param fH Hue component, used as input, range: [0, 360]
|
|
\param fS Hue component, used as input, range: [0, 1]
|
|
\param fV Hue component, used as input, range: [0, 1]
|
|
|
|
*/
|
|
void HSVtoRGB(float& fR, float& fG, float& fB, const float& fH, const float& fS, const float& fV) {
|
|
float fC = fV * fS; // Chroma
|
|
float fHPrime = std::fmod(fH / 60.0, 6);
|
|
float fX = fC * (1 - std::fabs(std::fmod(fHPrime, 2) - 1));
|
|
float fM = fV - fC;
|
|
|
|
if(0 <= fHPrime && fHPrime < 1) {
|
|
fR = fC;
|
|
fG = fX;
|
|
fB = 0;
|
|
} else if(1 <= fHPrime && fHPrime < 2) {
|
|
fR = fX;
|
|
fG = fC;
|
|
fB = 0;
|
|
} else if(2 <= fHPrime && fHPrime < 3) {
|
|
fR = 0;
|
|
fG = fC;
|
|
fB = fX;
|
|
} else if(3 <= fHPrime && fHPrime < 4) {
|
|
fR = 0;
|
|
fG = fX;
|
|
fB = fC;
|
|
} else if(4 <= fHPrime && fHPrime < 5) {
|
|
fR = fX;
|
|
fG = 0;
|
|
fB = fC;
|
|
} else if(5 <= fHPrime && fHPrime < 6) {
|
|
fR = fC;
|
|
fG = 0;
|
|
fB = fX;
|
|
} else {
|
|
fR = 0;
|
|
fG = 0;
|
|
fB = 0;
|
|
}
|
|
|
|
fR += fM;
|
|
fG += fM;
|
|
fB += fM;
|
|
}
|