111 lines
2.9 KiB
C++
111 lines
2.9 KiB
C++
#ifndef KANIMAJI_RGB_HPP
|
|
#define KANIMAJI_RGB_HPP
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
namespace Kanimaji
|
|
{
|
|
namespace Implementation
|
|
{
|
|
constexpr std::uint8_t HexToDec(char ch)
|
|
{
|
|
if (ch >= '0' && ch <= '9') {
|
|
return std::uint8_t(ch - '0');
|
|
}
|
|
|
|
if (ch >= 'A' && ch <= 'F') {
|
|
return std::uint8_t(ch - 'A' + 10);
|
|
}
|
|
|
|
if (ch >= 'a' && ch <= 'f') {
|
|
return std::uint8_t(ch - 'a' + 10);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
constexpr char DecToHex(std::uint8_t val)
|
|
{
|
|
if (val < 10) {
|
|
return char(val + '0');
|
|
}
|
|
|
|
if (val < 16) {
|
|
return char(val - 10 + 'A');
|
|
}
|
|
|
|
return '0';
|
|
}
|
|
|
|
constexpr std::uint8_t ToDec(char upper, char lower)
|
|
{
|
|
return HexToDec(upper) << 4 | HexToDec(lower);
|
|
}
|
|
|
|
constexpr std::uint8_t ToDec(char ch)
|
|
{
|
|
return ToDec(ch, ch);
|
|
}
|
|
|
|
constexpr void ChannelToHex(std::uint8_t val, char& ch1, char& ch2)
|
|
{
|
|
ch1 = DecToHex(15 & (val >> 4));
|
|
ch2 = DecToHex(15 & (val));
|
|
}
|
|
}
|
|
|
|
struct RGB
|
|
{
|
|
std::uint8_t Red;
|
|
std::uint8_t Green;
|
|
std::uint8_t Blue;
|
|
|
|
static constexpr RGB FromHex(std::string_view hex)
|
|
{
|
|
if (hex.empty()) {
|
|
return RGB { .Red = 0, .Green = 0, .Blue = 0 };
|
|
}
|
|
|
|
if (hex[0] == '#') {
|
|
hex = std::string_view(hex.data() + 1, hex.length() - 1);
|
|
}
|
|
|
|
for (char ch : hex) {
|
|
if ((ch < '0' || ch > '9') && (ch < 'A' || ch > 'F') && (ch < 'a' && ch > 'f')) {
|
|
return RGB { .Red = 0, .Green = 0, .Blue = 0 };
|
|
}
|
|
}
|
|
|
|
if (hex.length() == 3) {
|
|
return RGB {
|
|
.Red = Implementation::ToDec(hex[0]),
|
|
.Green = Implementation::ToDec(hex[1]),
|
|
.Blue = Implementation::ToDec(hex[2]),
|
|
};
|
|
}
|
|
|
|
if (hex.length() == 6) {
|
|
return RGB {
|
|
.Red = Implementation::ToDec(hex[0], hex[1]),
|
|
.Green = Implementation::ToDec(hex[2], hex[3]),
|
|
.Blue = Implementation::ToDec(hex[4], hex[5]),
|
|
};
|
|
}
|
|
|
|
return RGB { .Red = 0, .Green = 0, .Blue = 0 };
|
|
}
|
|
|
|
constexpr std::string ToHex() const
|
|
{
|
|
std::string result(7, '#');
|
|
Implementation::ChannelToHex(Red, result[1], result[2]);
|
|
Implementation::ChannelToHex(Green, result[3], result[4]);
|
|
Implementation::ChannelToHex(Blue, result[5], result[6]);
|
|
return result;
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif // KANIMAJI_RGB_HPP
|