#include "BsColor.h" #include "BsMath.h" namespace BansheeEngine { const Color Color::ZERO = Color(0.0,0.0,0.0,0.0); const Color Color::Black = Color(0.0,0.0,0.0); const Color Color::White = Color(1.0,1.0,1.0); const Color Color::Red = Color(1.0,0.0,0.0); const Color Color::Green = Color(0.0,1.0,0.0); const Color Color::Blue = Color(0.0,0.0,1.0); ABGR Color::getAsABGR() const { UINT8 val8; UINT32 val32 = 0; // Convert to 32bit pattern // (RGBA = 8888) // Red val8 = static_cast(r * 255); val32 = val8 << 24; // Green val8 = static_cast(g * 255); val32 += val8 << 16; // Blue val8 = static_cast(b * 255); val32 += val8 << 8; // Alpha val8 = static_cast(a * 255); val32 += val8; return val32; } BGRA Color::getAsBGRA() const { UINT8 val8; UINT32 val32 = 0; // Convert to 32bit pattern // (ARGB = 8888) // Alpha val8 = static_cast(a * 255); val32 = val8 << 24; // Red val8 = static_cast(r * 255); val32 += val8 << 16; // Green val8 = static_cast(g * 255); val32 += val8 << 8; // Blue val8 = static_cast(b * 255); val32 += val8; return val32; } ARGB Color::getAsARGB() const { UINT8 val8; UINT32 val32 = 0; // Convert to 32bit pattern // (ARGB = 8888) // Blue val8 = static_cast(b * 255); val32 = val8 << 24; // Green val8 = static_cast(g * 255); val32 += val8 << 16; // Red val8 = static_cast(r * 255); val32 += val8 << 8; // Alpha val8 = static_cast(a * 255); val32 += val8; return val32; } RGBA Color::getAsRGBA() const { UINT8 val8; UINT32 val32 = 0; // Convert to 32bit pattern // (ABRG = 8888) // Alpha val8 = static_cast(a * 255); val32 = val8 << 24; // Blue val8 = static_cast(b * 255); val32 += val8 << 16; // Green val8 = static_cast(g * 255); val32 += val8 << 8; // Red val8 = static_cast(r * 255); val32 += val8; return val32; } void Color::setAsABGR(const ABGR val) { UINT32 val32 = val; // Convert from 32bit pattern // (RGBA = 8888) // Red r = ((val32 >> 24) & 0xFF) / 255.0f; // Green g = ((val32 >> 16) & 0xFF) / 255.0f; // Blue b = ((val32 >> 8) & 0xFF) / 255.0f; // Alpha a = (val32 & 0xFF) / 255.0f; } void Color::setAsBGRA(const BGRA val) { UINT32 val32 = val; // Convert from 32bit pattern // (ARGB = 8888) // Alpha a = ((val32 >> 24) & 0xFF) / 255.0f; // Red r = ((val32 >> 16) & 0xFF) / 255.0f; // Green g = ((val32 >> 8) & 0xFF) / 255.0f; // Blue b = (val32 & 0xFF) / 255.0f; } void Color::setAsARGB(const ARGB val) { UINT32 val32 = val; // Convert from 32bit pattern // (ARGB = 8888) // Blue b = ((val32 >> 24) & 0xFF) / 255.0f; // Green g = ((val32 >> 16) & 0xFF) / 255.0f; // Red r = ((val32 >> 8) & 0xFF) / 255.0f; // Alpha a = (val32 & 0xFF) / 255.0f; } void Color::setAsRGBA(const RGBA val) { UINT32 val32 = val; // Convert from 32bit pattern // (ABGR = 8888) // Alpha a = ((val32 >> 24) & 0xFF) / 255.0f; // Blue b = ((val32 >> 16) & 0xFF) / 255.0f; // Green g = ((val32 >> 8) & 0xFF) / 255.0f; // Red r = (val32 & 0xFF) / 255.0f; } bool Color::operator==(const Color& rhs) const { return (r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a); } bool Color::operator!=(const Color& rhs) const { return !(*this == rhs); } void Color::setHSB(float hue, float saturation, float brightness) { // wrap hue if (hue > 1.0f) { hue -= (int)hue; } else if (hue < 0.0f) { hue += (int)hue + 1; } // clamp saturation / brightness saturation = std::min(saturation, (float)1.0); saturation = std::max(saturation, (float)0.0); brightness = std::min(brightness, (float)1.0); brightness = std::max(brightness, (float)0.0); if (brightness == 0.0f) { // early exit, this has to be black r = g = b = 0.0f; return; } if (saturation == 0.0f) { // early exit, this has to be grey r = g = b = brightness; return; } float hueDomain = hue * 6.0f; if (hueDomain >= 6.0f) { // wrap around, and allow mathematical errors hueDomain = 0.0f; } unsigned short domain = (unsigned short)hueDomain; float f1 = brightness * (1 - saturation); float f2 = brightness * (1 - saturation * (hueDomain - domain)); float f3 = brightness * (1 - saturation * (1 - (hueDomain - domain))); switch (domain) { case 0: // red domain; green ascends r = brightness; g = f3; b = f1; break; case 1: // yellow domain; red descends r = f2; g = brightness; b = f1; break; case 2: // green domain; blue ascends r = f1; g = brightness; b = f3; break; case 3: // cyan domain; green descends r = f1; g = f2; b = brightness; break; case 4: // blue domain; red ascends r = f3; g = f1; b = brightness; break; case 5: // magenta domain; blue descends r = brightness; g = f1; b = f2; break; } } void Color::getHSB(float* hue, float* saturation, float* brightness) const { float vMin = std::min(r, std::min(g, b)); float vMax = std::max(r, std::max(g, b)); float delta = vMax - vMin; *brightness = vMax; if (Math::approxEquals(delta, 0.0f, 1e-6f)) { // grey *hue = 0; *saturation = 0; } else { // a colour *saturation = delta / vMax; float deltaR = (((vMax - r) / 6.0f) + (delta / 2.0f)) / delta; float deltaG = (((vMax - g) / 6.0f) + (delta / 2.0f)) / delta; float deltaB = (((vMax - b) / 6.0f) + (delta / 2.0f)) / delta; if (Math::approxEquals(r, vMax)) *hue = deltaB - deltaG; else if (Math::approxEquals(g, vMax)) *hue = 0.3333333f + deltaR - deltaB; else if (Math::approxEquals(b, vMax)) *hue = 0.6666667f + deltaG - deltaR; if (*hue < 0.0f) *hue += 1.0f; if (*hue > 1.0f) *hue -= 1.0f; } } }