|
#ifndef LOLITA_PIXEL_HPP |
|
#define LOLITA_PIXEL_HPP |
|
|
|
#include <cstdint> |
|
#include <cstddef> |
|
#include <stdexcept> |
|
|
|
namespace lolita |
|
{ |
|
|
|
constexpr static inline size_t _stringLength(const char* str) |
|
{ |
|
return *str != 0 ? 1 + _stringLength(str + 1) : 0; |
|
} |
|
|
|
constexpr static inline size_t _stringFind(const char* str, char ch, size_t index=0) |
|
{ |
|
return *str == ch ? index : (*str == 0 ? SIZE_MAX : _stringFind(str+1, ch, index+1)); |
|
} |
|
|
|
constexpr static inline bool _stringEqual(const char* str1, const char* str2) |
|
{ |
|
return *str1 == 0 && *str2 == 0 ? true : (*str1 != *str2 ? false : (_stringEqual(str1+1, str2+1))); |
|
} |
|
|
|
constexpr static inline uint64_t _string2Uint64(const char* str, uint64_t n = 0, size_t index = 0) |
|
{ |
|
return *str == 0 ? n : _string2Uint64(str+1, n | (static_cast<uint64_t>(*str) << (8 * index)), index+1); |
|
} |
|
|
|
constexpr static inline size_t _findCharInUint64(uint64_t n, char ch, size_t index = 0) |
|
{ |
|
return n == 0 ? SIZE_MAX : ((n & 0xff) == ch ? index : _findCharInUint64(n >> 8, ch, index+1)); |
|
} |
|
|
|
constexpr static inline size_t _uint64StringLength(uint64_t n, size_t len = 0) |
|
{ |
|
return n == 0 ? len : _uint64StringLength(n >> 8, len+1); |
|
} |
|
|
|
namespace ColorSpace |
|
{ |
|
constexpr const char RED = 'R'; |
|
constexpr const char GREEN = 'G'; |
|
constexpr const char BLUE = 'B'; |
|
constexpr const char ALPHA = 'A'; |
|
|
|
constexpr static inline uint64_t CS(const char* str) |
|
{ |
|
return _string2Uint64(str); |
|
} |
|
|
|
constexpr static inline size_t CS_INDEX(uint64_t n, char ch) |
|
{ |
|
return _findCharInUint64(n, ch); |
|
} |
|
|
|
constexpr static inline size_t CS_LENGTH(uint64_t n) |
|
{ |
|
return _uint64StringLength(n); |
|
} |
|
}; |
|
|
|
namespace Pixel |
|
{ |
|
template<uint64_t format> |
|
class _RGBPixel |
|
{ |
|
public: |
|
uint8_t red() const |
|
{ |
|
return m_get(ColorSpace::RED); |
|
} |
|
|
|
uint8_t green() const |
|
{ |
|
return m_get(ColorSpace::GREEN); |
|
} |
|
|
|
uint8_t blue() const |
|
{ |
|
return m_get(ColorSpace::BLUE); |
|
} |
|
|
|
void setRed(uint8_t v) |
|
{ |
|
m_set(ColorSpace::RED, v); |
|
} |
|
|
|
void setGreen(uint8_t v) |
|
{ |
|
m_set(ColorSpace::GREEN, v); |
|
} |
|
|
|
void setBlue(uint8_t v) |
|
{ |
|
m_set(ColorSpace::BLUE, v); |
|
} |
|
|
|
private: |
|
static const size_t length = ColorSpace::CS_LENGTH(format); |
|
|
|
uint8_t m_data[ColorSpace::CS_LENGTH(format)]; |
|
|
|
uint8_t m_get(char color) |
|
{ |
|
size_t i = ColorSpace::CS_INDEX(format, color); |
|
if(i >= length) |
|
{ |
|
throw std::out_of_range("_RGBPixel out of range"); |
|
} |
|
return m_data[i]; |
|
} |
|
|
|
void m_set(char color, uint8_t v) |
|
{ |
|
size_t i = ColorSpace::CS_INDEX(format, color); |
|
if(i >= length) |
|
{ |
|
throw std::out_of_range("_RGBPixel out of range"); |
|
} |
|
m_data[i] = v; |
|
} |
|
}; |
|
|
|
template<uint64_t format> |
|
class _RGBAPixel |
|
{ |
|
public: |
|
uint8_t red() const |
|
{ |
|
return m_get(ColorSpace::RED); |
|
} |
|
|
|
uint8_t green() const |
|
{ |
|
return m_get(ColorSpace::GREEN); |
|
} |
|
|
|
uint8_t blue() const |
|
{ |
|
return m_get(ColorSpace::BLUE); |
|
} |
|
|
|
uint8_t alpha() const |
|
{ |
|
return m_get(ColorSpace::ALPHA); |
|
} |
|
|
|
void setRed(uint8_t v) |
|
{ |
|
m_set(ColorSpace::RED, v); |
|
} |
|
|
|
void setGreen(uint8_t v) |
|
{ |
|
m_set(ColorSpace::GREEN, v); |
|
} |
|
|
|
void setBlue(uint8_t v) |
|
{ |
|
m_set(ColorSpace::BLUE, v); |
|
} |
|
|
|
void setAlpha(uint8_t v) |
|
{ |
|
m_set(ColorSpace::ALPHA, v); |
|
} |
|
|
|
private: |
|
static const size_t length = ColorSpace::CS_LENGTH(format); |
|
|
|
uint8_t m_data[ColorSpace::CS_LENGTH(format)]; |
|
|
|
uint8_t m_get(char color) |
|
{ |
|
size_t i = ColorSpace::CS_INDEX(format, color); |
|
if(i >= length) |
|
{ |
|
throw std::out_of_range("_RGBAPixel out of range"); |
|
} |
|
return m_data[i]; |
|
} |
|
|
|
void m_set(char color, uint8_t v) |
|
{ |
|
size_t i = ColorSpace::CS_INDEX(format, color); |
|
if(i >= length) |
|
{ |
|
throw std::out_of_range("_RGBAPixel out of range"); |
|
} |
|
m_data[i] = v; |
|
} |
|
}; |
|
|
|
using RGB24 = _RGBPixel<ColorSpace::CS("RGB")>; |
|
using BGR24 = _RGBPixel<ColorSpace::CS("BGR")>; |
|
|
|
using RGBX32 = _RGBPixel<ColorSpace::CS("RGBX")>; |
|
using XRGB32 = _RGBPixel<ColorSpace::CS("XRGB")>; |
|
using BGRX32 = _RGBPixel<ColorSpace::CS("BGRX")>; |
|
using XBGR32 = _RGBPixel<ColorSpace::CS("XBGR")>; |
|
|
|
using RGBA32 = _RGBAPixel<ColorSpace::CS("RGBA")>; |
|
using ARGB32 = _RGBAPixel<ColorSpace::CS("ARGB")>; |
|
using BGRA32 = _RGBAPixel<ColorSpace::CS("BGRA")>; |
|
using ABGR32 = _RGBAPixel<ColorSpace::CS("ABGR")>; |
|
|
|
|
|
}; // namespace Pixel |
|
|
|
|
|
}; // namespace lolita |
|
|
|
#endif |