feat(color_util): Utility functions for color handling

This commit is contained in:
Michael Carlberg 2016-10-31 01:21:24 +01:00
parent e62b545d1c
commit 26c308cc19
3 changed files with 127 additions and 0 deletions

97
include/utils/color.hpp Normal file
View File

@ -0,0 +1,97 @@
#pragma once
#include <iomanip>
#include "common.hpp"
#include "utils/string.hpp"
LEMONBUDDY_NS
namespace color_util {
template <typename ChannelType = uint8_t, typename ValueType = uint32_t>
struct color {
using type = color<ChannelType, ValueType>;
union {
struct {
ChannelType red;
ChannelType green;
ChannelType blue;
ChannelType alpha;
} bits;
ValueType value = 0U;
} colorspace;
explicit color(ValueType v) {
colorspace.value = v;
}
};
template <typename T>
auto make_24bit(T&& value) {
return color<uint8_t, uint32_t>(forward<T>(value));
}
template <typename T>
auto make_32bit(T&& value) {
return color<uint16_t, uint32_t>(forward<T>(value));
}
template <typename ValueType = uint32_t>
uint8_t alpha(const color<ValueType> c) {
return ((c.colorspace.value >> 24) << 8) | ((c.colorspace.value >> 24));
}
template <typename T = uint8_t, typename ValueType = uint32_t>
T red(const color<ValueType> c) {
uint8_t r = c.colorspace.value >> 16;
if (std::is_same<T, uint8_t>::value)
return r << 8 / 0xFF;
if (std::is_same<T, uint16_t>::value)
return r << 8 | r << 8 / 0xFF;
}
template <typename T = uint8_t, typename ValueType = uint32_t>
T green(const color<ValueType> c) {
uint8_t g = c.colorspace.value >> 8;
if (std::is_same<T, uint8_t>::value)
return g << 8 / 0xFF;
if (std::is_same<T, uint16_t>::value)
return g << 8 | g << 8 / 0xFF;
}
template <typename T = uint8_t, typename ValueType = uint32_t>
T blue(const color<ValueType> c) {
uint8_t b = c.colorspace.value;
if (std::is_same<T, uint8_t>::value)
return b << 8 / 0xFF;
if (std::is_same<T, uint16_t>::value)
return b << 8 | b << 8 / 0xFF;
}
string hex(const color<uint8_t, uint32_t> value) {
// clang-format off
return string_util::from_stream(stringstream()
<< "#"
<< std::setw(6)
<< std::setfill('0')
<< std::hex
<< std::uppercase
<< (value.colorspace.value & 0x00FFFFFF));
// clang-format on
}
string hex(const color<uint16_t, uint32_t> value) {
// clang-format off
return string_util::from_stream(stringstream()
<< "#"
<< std::setw(8)
<< std::setfill('0')
<< std::hex
<< std::uppercase
<< value.colorspace.value);
// clang-format on
}
}
LEMONBUDDY_NS_END

View File

@ -12,6 +12,7 @@ function(unit_test file)
add_test(unit_test.${testname} unit_test.${testname})
endfunction()
unit_test("utils/color")
unit_test("utils/math")
unit_test("utils/memory")
unit_test("utils/string")

View File

@ -0,0 +1,29 @@
#include "common/test.hpp"
#include "utils/color.hpp"
int main() {
using namespace lemonbuddy;
"rgb"_test = []{
auto color = color_util::make_24bit(0x123456);
expect(color_util::alpha(color) == 0);
expect(color_util::red<uint8_t>(color) == 0x12);
expect(color_util::green<uint8_t>(color) == 0x34);
expect(color_util::blue<uint8_t>(color) == 0x56);
};
"rgba"_test = []{
auto color = color_util::make_32bit(0xCC123456);
expect(color_util::alpha(color) == 0xCC);
expect(color_util::red<uint16_t>(color) == 0x1212);
expect(color_util::green<uint16_t>(color) == 0x3434);
expect(color_util::blue<uint16_t>(color) == 0x5656);
};
"hex"_test = [] {
auto colorA = color_util::make_24bit(0x123456);
expect(color_util::hex(colorA) == "#123456");
auto colorB = color_util::make_32bit(0xCC123456);
expect(color_util::hex(colorB) == "#CC123456");
};
}