#pragma once #include #include #include #include "array.h" #include "intmath.h" constexpr int32_t kMinColor = 0; constexpr int32_t kMaxColor = UINT16_MAX; class ColorBase {}; template struct Color : public Array, public ColorBase { constexpr int32_t AbsDiff(const Color& other) const; constexpr Color Interpolate(const Color& other, int32_t mul, int32_t div) const; constexpr Color Crop() const; }; struct RgbColor : public Color<3> { public: RgbColor() = default; RgbColor(const Color<3>& src); }; template constexpr int32_t Color::AbsDiff(const Color& other) const { int32_t diff = 0; for (int32_t c = 0; c < C; ++c) { diff += ::AbsDiff(this->at(c), other.at(c)); } return diff; } template constexpr Color Color::Interpolate(const Color& other, int32_t mul, int32_t div) const { Color ret; for (int32_t c = 0; c < C; ++c) { ret.at(c) = ::Interpolate(this->at(c), other.at(c), mul, div); } return ret; } template constexpr Color Color::Crop() const { Color ret; for (int32_t c = 0; c < C; ++c) { ret.at(c) = std::max(kMinColor, std::min(kMaxColor, this->at(c))); } return ret; } template std::ostream& operator<<(std::ostream& os, const Color& color) { os << std::hex << std::setfill('0') << "Color("; for (int32_t c = 0; c < C; ++c) { os << "0x" << std::setw(4) << color.at(0); if (c < C - 1) { os << ", "; } } return os << ")" << std::dec; }