Implementation of sRGB image support. Overhauls the linearization setup to utilize the sRGB image types, as well as refactors the use of ColorF and ColorI to be properly internally consistent. ColorIs are used only for front-facing/editing/UI settings, and ColorFs, now renamed to LinearColorF to reduce confusion of purpose, are used for color info in the engine itself. This avoids confusing and expensive conversions back and forth between types and avoids botches with linearity. Majority work done by @rextimmy

This commit is contained in:
Areloch 2017-06-23 11:36:20 -05:00
parent 8780f83262
commit 25686ed4be
294 changed files with 3894 additions and 2813 deletions

View file

@ -23,13 +23,13 @@
#include "platform/platform.h"
#include "core/color.h"
const ColorF ColorF::ZERO( 0, 0, 0, 0 );
const ColorF ColorF::ONE( 1, 1, 1, 1 );
const ColorF ColorF::WHITE( 1, 1, 1 );
const ColorF ColorF::BLACK( 0, 0, 0 );
const ColorF ColorF::RED( 1, 0, 0 );
const ColorF ColorF::GREEN( 0, 1, 0 );
const ColorF ColorF::BLUE( 0, 0, 1 );
const LinearColorF LinearColorF::ZERO( 0, 0, 0, 0 );
const LinearColorF LinearColorF::ONE( 1, 1, 1, 1 );
const LinearColorF LinearColorF::WHITE( 1, 1, 1 );
const LinearColorF LinearColorF::BLACK( 0, 0, 0 );
const LinearColorF LinearColorF::RED( 1, 0, 0 );
const LinearColorF LinearColorF::GREEN( 0, 1, 0 );
const LinearColorF LinearColorF::BLUE( 0, 0, 1 );
const ColorI ColorI::ZERO( 0, 0, 0, 0 );
const ColorI ColorI::ONE( 255, 255, 255, 255 );
@ -54,9 +54,9 @@ const ColorI ColorI::BLUE( 0, 0, 255 );
//-----------------------------------------------------------------------------
typedef HashTable<StringTableEntry, ColorF> typeNameToColorFHash;
typedef HashTable<StringTableEntry, LinearColorF> typeNameToColorFHash;
typedef HashTable<StringTableEntry, ColorI> typeNameToColorIHash;
typedef HashTable<ColorF, StringTableEntry> typeColorFToNameHash;
typedef HashTable<LinearColorF, StringTableEntry> typeColorFToNameHash;
typedef HashTable<ColorI, StringTableEntry> typeColorIToNameHash;
static typeNameToColorFHash mNameToColorF;
@ -299,7 +299,7 @@ bool StockColor::isColor( const char* pStockColorName )
//-----------------------------------------------------------------------------
const ColorF& StockColor::colorF( const char* pStockColorName )
const LinearColorF& StockColor::colorF( const char* pStockColorName )
{
// Sanity!
AssertFatal( pStockColorName != NULL, "Cannot fetch a NULL stock color name." );
@ -347,7 +347,7 @@ const ColorI& StockColor::colorI( const char* pStockColorName )
//-----------------------------------------------------------------------------
StringTableEntry StockColor::name( const ColorF& color )
StringTableEntry StockColor::name( const LinearColorF& color )
{
// Find stock color name.
typeColorFToNameHash::Iterator colorNameItr = mColorFToName.find( color );
@ -403,7 +403,7 @@ const StockColorItem* StockColor::getColorItem( const S32 index )
//-----------------------------------------------------------------------------
ColorF::ColorF( const char* pStockColorName )
LinearColorF::LinearColorF( const char* pStockColorName )
{
// Set stock color.
*this = StockColor::colorF( pStockColorName );
@ -411,7 +411,7 @@ ColorF::ColorF( const char* pStockColorName )
//-----------------------------------------------------------------------------
void ColorF::set( const char* pStockColorName )
void LinearColorF::set( const char* pStockColorName )
{
// Set stock color.
*this = StockColor::colorF( pStockColorName );
@ -419,14 +419,14 @@ void ColorF::set( const char* pStockColorName )
//-----------------------------------------------------------------------------
const ColorF& ColorF::StockColor( const char* pStockColorName )
const LinearColorF& LinearColorF::StockColor( const char* pStockColorName )
{
return StockColor::colorF( pStockColorName );
}
//-----------------------------------------------------------------------------
StringTableEntry ColorF::StockColor( void )
StringTableEntry LinearColorF::StockColor( void )
{
// Return stock color name.
return StockColor::name( *this );
@ -465,6 +465,77 @@ StringTableEntry ColorI::StockColor( void )
//-----------------------------------------------------------------------------
#ifdef TORQUE_USE_LEGACY_GAMMA
//legacy pow 2.2 - powf(color, 2.2f);
float LinearColorF::sSrgbToLinear[256] =
{
0.000000f, 0.000005f, 0.000023f, 0.000057f, 0.000107f, 0.000175f, 0.000262f, 0.000367f, 0.000493f,
0.000638f, 0.000805f, 0.000992f, 0.001202f, 0.001433f, 0.001687f, 0.001963f, 0.002263f, 0.002586f,
0.002932f, 0.003303f, 0.003697f, 0.004116f, 0.004560f, 0.005028f, 0.005522f, 0.006041f, 0.006585f,
0.007155f, 0.007751f, 0.008373f, 0.009021f, 0.009696f, 0.010398f, 0.011126f, 0.011881f, 0.012664f,
0.013473f, 0.014311f, 0.015175f, 0.016068f, 0.016988f, 0.017936f, 0.018913f, 0.019918f, 0.020951f,
0.022013f, 0.023104f, 0.024223f, 0.025371f, 0.026549f, 0.027755f, 0.028991f, 0.030257f, 0.031551f,
0.032876f, 0.034230f, 0.035614f, 0.037029f, 0.038473f, 0.039947f, 0.041452f, 0.042987f, 0.044553f,
0.046149f, 0.047776f, 0.049433f, 0.051122f, 0.052842f, 0.054592f, 0.056374f, 0.058187f, 0.060032f,
0.061907f, 0.063815f, 0.065754f, 0.067725f, 0.069727f, 0.071761f, 0.073828f, 0.075926f, 0.078057f,
0.080219f, 0.082414f, 0.084642f, 0.086901f, 0.089194f, 0.091518f, 0.093876f, 0.096266f, 0.098689f,
0.101145f, 0.103634f, 0.106156f, 0.108711f, 0.111299f, 0.113921f, 0.116576f, 0.119264f, 0.121986f,
0.124741f, 0.127530f, 0.130352f, 0.133209f, 0.136099f, 0.139022f, 0.141980f, 0.144972f, 0.147998f,
0.151058f, 0.154152f, 0.157281f, 0.160444f, 0.163641f, 0.166872f, 0.170138f, 0.173439f, 0.176774f,
0.180144f, 0.183549f, 0.186989f, 0.190463f, 0.193972f, 0.197516f, 0.201096f, 0.204710f, 0.208360f,
0.212044f, 0.215764f, 0.219520f, 0.223310f, 0.227137f, 0.230998f, 0.234895f, 0.238828f, 0.242796f,
0.246800f, 0.250840f, 0.254916f, 0.259027f, 0.263175f, 0.267358f, 0.271577f, 0.275833f, 0.280124f,
0.284452f, 0.288816f, 0.293216f, 0.297653f, 0.302126f, 0.306635f, 0.311181f, 0.315763f, 0.320382f,
0.325037f, 0.329729f, 0.334458f, 0.339223f, 0.344026f, 0.348865f, 0.353741f, 0.358654f, 0.363604f,
0.368591f, 0.373615f, 0.378676f, 0.383775f, 0.388910f, 0.394083f, 0.399293f, 0.404541f, 0.409826f,
0.415148f, 0.420508f, 0.425905f, 0.431340f, 0.436813f, 0.442323f, 0.447871f, 0.453456f, 0.459080f,
0.464741f, 0.470440f, 0.476177f, 0.481952f, 0.487765f, 0.493616f, 0.499505f, 0.505432f, 0.511398f,
0.517401f, 0.523443f, 0.529523f, 0.535642f, 0.541798f, 0.547994f, 0.554227f, 0.560499f, 0.566810f,
0.573159f, 0.579547f, 0.585973f, 0.592438f, 0.598942f, 0.605484f, 0.612066f, 0.618686f, 0.625345f,
0.632043f, 0.638779f, 0.645555f, 0.652370f, 0.659224f, 0.666117f, 0.673049f, 0.680020f, 0.687031f,
0.694081f, 0.701169f, 0.708298f, 0.715465f, 0.722672f, 0.729919f, 0.737205f, 0.744530f, 0.751895f,
0.759300f, 0.766744f, 0.774227f, 0.781751f, 0.789314f, 0.796917f, 0.804559f, 0.812241f, 0.819964f,
0.827726f, 0.835528f, 0.843370f, 0.851252f, 0.859174f, 0.867136f, 0.875138f, 0.883180f, 0.891262f,
0.899384f, 0.907547f, 0.915750f, 0.923993f, 0.932277f, 0.940601f, 0.948965f, 0.957370f, 0.965815f,
0.974300f, 0.982826f, 0.991393f, 1.000000f
};
#else
//sRGB - color < 0.04045f ? (1.0f / 12.92f) * color : powf((color + 0.055f) * (1.0f / 1.055f), 2.4f);
float LinearColorF::sSrgbToLinear[256] =
{
0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f,
0.002732f, 0.003035f, 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f,
0.006049f, 0.006512f, 0.006995f, 0.007499f, 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f,
0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, 0.015209f, 0.015996f, 0.016807f,
0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, 0.025187f,
0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f,
0.036889f, 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f,
0.049707f, 0.051269f, 0.052861f, 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f,
0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, 0.074214f, 0.076185f, 0.078187f, 0.080220f,
0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, 0.097587f, 0.099899f,
0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f,
0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f,
0.149960f, 0.152926f, 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f,
0.177888f, 0.181164f, 0.184475f, 0.187821f, 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f,
0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, 0.230740f, 0.234551f, 0.238398f,
0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, 0.274677f,
0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f,
0.318547f, 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f,
0.361307f, 0.366253f, 0.371238f, 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f,
0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, 0.434154f, 0.439657f, 0.445201f, 0.450786f,
0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, 0.496933f, 0.502886f,
0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f,
0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f,
0.623960f, 0.630757f, 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f,
0.686685f, 0.693872f, 0.701102f, 0.708376f, 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f,
0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, 0.799103f, 0.806952f, 0.814847f,
0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, 0.887923f,
0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f,
0.973445f, 0.982251f, 0.991102f, 1.000000f
};
#endif
//-----------------------------------------------------------------------------
ConsoleFunction( getStockColorCount, S32, 1, 1, "() - Gets a count of available stock colors.\n"
"@return A count of available stock colors." )
{
@ -513,7 +584,7 @@ ConsoleFunction( getStockColorF, const char*, 2, 2, "(stockColorName) - Gets a f
return StringTable->EmptyString();
// Fetch stock color.
const ColorF& color = StockColor::colorF( pStockColorName );
const LinearColorF& color = StockColor::colorF( pStockColorName );
// Format stock color.
char* returnBuffer = Con::getReturnBuffer(256);

View file

@ -36,54 +36,48 @@
const F32 gGamma = 2.2f;
const F32 gOneOverGamma = 1.f / 2.2f;
const F32 gOneOver255 = 1.f / 255.f;
class ColorI;
class ColorF
//32bit color in linear space
class LinearColorF
{
public:
public:
F32 red;
F32 green;
F32 blue;
F32 alpha;
public:
ColorF() { }
ColorF(const ColorF& in_rCopy);
ColorF(const F32 in_r,
const F32 in_g,
const F32 in_b,
const F32 in_a = 1.0f);
ColorF( const char* pStockColorName );
void set(const F32 in_r,
const F32 in_g,
const F32 in_b,
const F32 in_a = 1.0f);
public:
LinearColorF() : red(0), green(0), blue(0), alpha(0) {}
LinearColorF(const LinearColorF& in_rCopy);
LinearColorF(const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a = 1.0f);
LinearColorF(const ColorI &color);
LinearColorF(const char* pStockColorName);
void set( const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a = 1.0f );
void set( const char* pStockColorName );
static const ColorF& StockColor( const char* pStockColorName );
static const LinearColorF& StockColor( const char* pStockColorName );
StringTableEntry StockColor( void );
ColorF& operator*=(const ColorF& in_mul); // Can be useful for lighting
ColorF operator*(const ColorF& in_mul) const;
ColorF& operator+=(const ColorF& in_rAdd);
ColorF operator+(const ColorF& in_rAdd) const;
ColorF& operator-=(const ColorF& in_rSub);
ColorF operator-(const ColorF& in_rSub) const;
LinearColorF& operator*=(const LinearColorF& in_mul); // Can be useful for lighting
LinearColorF operator*(const LinearColorF& in_mul) const;
LinearColorF& operator+=(const LinearColorF& in_rAdd);
LinearColorF operator+(const LinearColorF& in_rAdd) const;
LinearColorF& operator-=(const LinearColorF& in_rSub);
LinearColorF operator-(const LinearColorF& in_rSub) const;
ColorF& operator*=(const F32 in_mul);
ColorF operator*(const F32 in_mul) const;
ColorF& operator/=(const F32 in_div);
ColorF operator/(const F32 in_div) const;
LinearColorF& operator*=(const F32 in_mul);
LinearColorF operator*(const F32 in_mul) const;
LinearColorF& operator/=(const F32 in_div);
LinearColorF operator/(const F32 in_div) const;
ColorF operator-() const;
LinearColorF operator-() const;
bool operator==(const ColorF&) const;
bool operator!=(const ColorF&) const;
bool operator==(const LinearColorF&) const;
bool operator!=(const LinearColorF&) const;
operator F32*() { return &red; }
operator const F32*() const { return &red; }
@ -95,39 +89,38 @@ class ColorF
U32 getRGBAPack() const;
U32 getABGRPack() const;
operator ColorI() const;
void interpolate(const ColorF& in_rC1,
const ColorF& in_rC2,
void interpolate(const LinearColorF& in_rC1,
const LinearColorF& in_rC2,
const F32 in_factor);
bool isValidColor() const { return (red >= 0.0f && red <= 1.0f) &&
(green >= 0.0f && green <= 1.0f) &&
(blue >= 0.0f && blue <= 1.0f) &&
(alpha >= 0.0f && alpha <= 1.0f); }
bool isClamped() const { return (red >= 0.0f && red <= 1.0f) &&
(green >= 0.0f && green <= 1.0f) &&
(blue >= 0.0f && blue <= 1.0f) &&
(alpha >= 0.0f && alpha <= 1.0f); }
void clamp();
ColorF toLinear();
ColorF toGamma();
//calculate luminance, make sure color is linear first
//calculate luminance
F32 luminance();
static const ColorF ZERO;
static const ColorF ONE;
static const ColorF WHITE;
static const ColorF BLACK;
static const ColorF RED;
static const ColorF GREEN;
static const ColorF BLUE;
//convert to ColorI - slow operation, avoid when possible
ColorI toColorI(const bool keepAsLinear = false);
static const LinearColorF ZERO;
static const LinearColorF ONE;
static const LinearColorF WHITE;
static const LinearColorF BLACK;
static const LinearColorF RED;
static const LinearColorF GREEN;
static const LinearColorF BLUE;
static F32 sSrgbToLinear[256];
};
//-------------------------------------- ColorI's are missing some of the operations
// present in ColorF since they cannot recover
// properly from over/underflow.
//8bit color in srgb space
class ColorI
{
public:
public:
U8 red;
U8 green;
U8 blue;
@ -143,17 +136,13 @@ class ColorI
U32 brightness; //Brightness/Value/Lightness
};
public:
ColorI() { }
public:
ColorI() : red(0), green(0), blue(0), alpha(0) {}
ColorI(const ColorI& in_rCopy);
ColorI(const Hsb& color);
ColorI(const U8 in_r,
const U8 in_g,
const U8 in_b,
const U8 in_a = U8(255));
ColorI(const U8 in_r, const U8 in_g, const U8 in_b, const U8 in_a = U8(255));
ColorI(const ColorI& in_rCopy, const U8 in_a);
ColorI( const char* pStockColorName );
ColorI(const char* pStockColorName);
void set(const Hsb& color);
@ -173,25 +162,10 @@ class ColorI
static const ColorI& StockColor( const char* pStockColorName );
StringTableEntry StockColor( void );
ColorI& operator*=(const F32 in_mul);
ColorI operator*(const F32 in_mul) const;
ColorI operator+(const ColorI& in_rAdd) const;
ColorI& operator+=(const ColorI& in_rAdd);
ColorI& operator*=(const S32 in_mul);
ColorI& operator/=(const S32 in_mul);
ColorI operator*(const S32 in_mul) const;
ColorI operator/(const S32 in_mul) const;
bool operator==(const ColorI&) const;
bool operator!=(const ColorI&) const;
void interpolate(const ColorI& in_rC1,
const ColorI& in_rC2,
const F32 in_factor);
U32 getARGBPack() const;
U32 getRGBAPack() const;
U32 getABGRPack() const;
@ -210,13 +184,11 @@ class ColorI
String getHex() const;
S32 convertFromHex(const String& hex) const;
operator ColorF() const;
operator const U8*() const { return &red; }
ColorI toLinear();
ColorI toGamma();
//convert linear color to srgb - slow operation, avoid when possible
ColorI fromLinear();
static const ColorI ZERO;
static const ColorI ONE;
static const ColorI WHITE;
@ -247,11 +219,11 @@ public:
}
inline const char* getColorName( void ) const { return mColorName; }
inline const ColorF& getColorF( void ) const { return mColorF; }
inline const LinearColorF& getColorF( void ) const { return mColorF; }
inline const ColorI& getColorI( void ) const { return mColorI; }
const char* mColorName;
ColorF mColorF;
LinearColorF mColorF;
ColorI mColorI;
};
@ -261,9 +233,9 @@ class StockColor
{
public:
static bool isColor( const char* pStockColorName );
static const ColorF& colorF( const char* pStockColorName );
static const LinearColorF& colorF( const char* pStockColorName );
static const ColorI& colorI( const char* pStockColorName );
static StringTableEntry name( const ColorF& color );
static StringTableEntry name( const LinearColorF& color );
static StringTableEntry name( const ColorI& color );
static S32 getCount( void );
@ -274,12 +246,9 @@ public:
};
//------------------------------------------------------------------------------
//-------------------------------------- INLINES (ColorF)
//-------------------------------------- INLINES (LinearColorF)
//
inline void ColorF::set(const F32 in_r,
const F32 in_g,
const F32 in_b,
const F32 in_a)
inline void LinearColorF::set(const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a)
{
red = in_r;
green = in_g;
@ -287,7 +256,7 @@ inline void ColorF::set(const F32 in_r,
alpha = in_a;
}
inline ColorF::ColorF(const ColorF& in_rCopy)
inline LinearColorF::LinearColorF(const LinearColorF& in_rCopy)
{
red = in_rCopy.red;
green = in_rCopy.green;
@ -295,15 +264,12 @@ inline ColorF::ColorF(const ColorF& in_rCopy)
alpha = in_rCopy.alpha;
}
inline ColorF::ColorF(const F32 in_r,
const F32 in_g,
const F32 in_b,
const F32 in_a)
inline LinearColorF::LinearColorF(const F32 in_r, const F32 in_g, const F32 in_b, const F32 in_a)
{
set(in_r, in_g, in_b, in_a);
}
inline ColorF& ColorF::operator*=(const ColorF& in_mul)
inline LinearColorF& LinearColorF::operator*=(const LinearColorF& in_mul)
{
red *= in_mul.red;
green *= in_mul.green;
@ -313,108 +279,98 @@ inline ColorF& ColorF::operator*=(const ColorF& in_mul)
return *this;
}
inline ColorF ColorF::operator*(const ColorF& in_mul) const
inline LinearColorF LinearColorF::operator*(const LinearColorF& in_mul) const
{
return ColorF(red * in_mul.red,
green * in_mul.green,
blue * in_mul.blue,
alpha * in_mul.alpha);
LinearColorF tmp(*this);
tmp *= in_mul;
return tmp;
}
inline ColorF& ColorF::operator+=(const ColorF& in_rAdd)
inline LinearColorF& LinearColorF::operator+=(const LinearColorF& in_rAdd)
{
red += in_rAdd.red;
red += in_rAdd.red;
green += in_rAdd.green;
blue += in_rAdd.blue;
blue += in_rAdd.blue;
alpha += in_rAdd.alpha;
return *this;
}
inline ColorF ColorF::operator+(const ColorF& in_rAdd) const
inline LinearColorF LinearColorF::operator+(const LinearColorF& in_rAdd) const
{
return ColorF(red + in_rAdd.red,
green + in_rAdd.green,
blue + in_rAdd.blue,
alpha + in_rAdd.alpha);
LinearColorF temp(*this);
temp += in_rAdd;
return temp;
}
inline ColorF& ColorF::operator-=(const ColorF& in_rSub)
inline LinearColorF& LinearColorF::operator-=(const LinearColorF& in_rSub)
{
red -= in_rSub.red;
red -= in_rSub.red;
green -= in_rSub.green;
blue -= in_rSub.blue;
blue -= in_rSub.blue;
alpha -= in_rSub.alpha;
return *this;
}
inline ColorF ColorF::operator-(const ColorF& in_rSub) const
inline LinearColorF LinearColorF::operator-(const LinearColorF& in_rSub) const
{
return ColorF(red - in_rSub.red,
green - in_rSub.green,
blue - in_rSub.blue,
alpha - in_rSub.alpha);
LinearColorF tmp(*this);
tmp -= in_rSub;
return tmp;
}
inline ColorF& ColorF::operator*=(const F32 in_mul)
inline LinearColorF& LinearColorF::operator*=(const F32 in_mul)
{
red *= in_mul;
green *= in_mul;
blue *= in_mul;
alpha *= in_mul;
return *this;
}
inline ColorF ColorF::operator*(const F32 in_mul) const
inline LinearColorF LinearColorF::operator*(const F32 in_mul) const
{
return ColorF(red * in_mul,
green * in_mul,
blue * in_mul,
alpha * in_mul);
LinearColorF tmp(*this);
tmp *= in_mul;
return tmp;
}
inline ColorF& ColorF::operator/=(const F32 in_div)
inline LinearColorF& LinearColorF::operator/=(const F32 in_div)
{
AssertFatal(in_div != 0.0f, "Error, div by zero...");
F32 inv = 1.0f / in_div;
red *= inv;
red *= inv;
green *= inv;
blue *= inv;
blue *= inv;
alpha *= inv;
return *this;
}
inline ColorF ColorF::operator/(const F32 in_div) const
inline LinearColorF LinearColorF::operator/(const F32 in_div) const
{
AssertFatal(in_div != 0.0f, "Error, div by zero...");
F32 inv = 1.0f / in_div;
return ColorF(red * inv,
green * inv,
blue * inv,
alpha * inv);
LinearColorF tmp(*this);
tmp /= inv;
return tmp;
}
inline ColorF ColorF::operator-() const
inline LinearColorF LinearColorF::operator-() const
{
return ColorF(-red, -green, -blue, -alpha);
return LinearColorF(-red, -green, -blue, -alpha);
}
inline bool ColorF::operator==(const ColorF& in_Cmp) const
inline bool LinearColorF::operator==(const LinearColorF& in_Cmp) const
{
return (red == in_Cmp.red && green == in_Cmp.green && blue == in_Cmp.blue && alpha == in_Cmp.alpha);
}
inline bool ColorF::operator!=(const ColorF& in_Cmp) const
inline bool LinearColorF::operator!=(const LinearColorF& in_Cmp) const
{
return (red != in_Cmp.red || green != in_Cmp.green || blue != in_Cmp.blue || alpha != in_Cmp.alpha);
}
inline U32 ColorF::getARGBPack() const
inline U32 LinearColorF::getARGBPack() const
{
return (U32(alpha * 255.0f + 0.5) << 24) |
(U32(red * 255.0f + 0.5) << 16) |
@ -422,7 +378,7 @@ inline U32 ColorF::getARGBPack() const
(U32(blue * 255.0f + 0.5) << 0);
}
inline U32 ColorF::getRGBAPack() const
inline U32 LinearColorF::getRGBAPack() const
{
return ( U32( red * 255.0f + 0.5) << 0 ) |
( U32( green * 255.0f + 0.5) << 8 ) |
@ -430,7 +386,7 @@ inline U32 ColorF::getRGBAPack() const
( U32( alpha * 255.0f + 0.5) << 24 );
}
inline U32 ColorF::getABGRPack() const
inline U32 LinearColorF::getABGRPack() const
{
return (U32(alpha * 255.0f + 0.5) << 24) |
(U32(blue * 255.0f + 0.5) << 16) |
@ -439,61 +395,43 @@ inline U32 ColorF::getABGRPack() const
}
inline void ColorF::interpolate(const ColorF& in_rC1,
const ColorF& in_rC2,
inline void LinearColorF::interpolate(const LinearColorF& in_rC1,
const LinearColorF& in_rC2,
const F32 in_factor)
{
if (in_factor <= 0 || in_rC1 == in_rC2)
{
red = in_rC1.red;
green = in_rC1.green;
blue =in_rC1.blue;
alpha = in_rC1.alpha;
return;
}
else if (in_factor >= 1)
{
red = in_rC2.red;
green = in_rC2.green;
blue = in_rC2.blue;
alpha = in_rC2.alpha;
return;
}
F32 f2 = 1.0f - in_factor;
red = (in_rC1.red * f2) + (in_rC2.red * in_factor);
red = (in_rC1.red * f2) + (in_rC2.red * in_factor);
green = (in_rC1.green * f2) + (in_rC2.green * in_factor);
blue = (in_rC1.blue * f2) + (in_rC2.blue * in_factor);
blue = (in_rC1.blue * f2) + (in_rC2.blue * in_factor);
alpha = (in_rC1.alpha * f2) + (in_rC2.alpha * in_factor);
}
inline void ColorF::clamp()
inline void LinearColorF::clamp()
{
if (red > 1.0f)
red = 1.0f;
else if (red < 0.0f)
red = 0.0f;
if (green > 1.0f)
green = 1.0f;
else if (green < 0.0f)
green = 0.0f;
if (blue > 1.0f)
blue = 1.0f;
else if (blue < 0.0f)
blue = 0.0f;
if (alpha > 1.0f)
alpha = 1.0f;
else if (alpha < 0.0f)
alpha = 0.0f;
red = mClampF(red, 0.0f, 1.0f);
green = mClampF(green, 0.0f, 1.0f);
blue = mClampF(blue, 0.0f, 1.0f);
alpha = mClampF(alpha, 0.0f, 1.0f);
}
inline ColorF ColorF::toGamma()
{
ColorF color;
color.red = mPow(red,gOneOverGamma);
color.green = mPow(green, gOneOverGamma);
color.blue = mPow(blue, gOneOverGamma);
color.alpha = alpha;
return color;
}
inline ColorF ColorF::toLinear()
{
ColorF color;
color.red = mPow(red,gGamma);
color.green = mPow(green, gGamma);
color.blue = mPow(blue, gGamma);
color.alpha = alpha;
return color;
}
inline F32 ColorF::luminance()
inline F32 LinearColorF::luminance()
{
// ITU BT.709
//return red * 0.2126f + green * 0.7152f + blue * 0.0722f;
@ -719,70 +657,6 @@ inline ColorI::ColorI(const ColorI& in_rCopy,
set(in_rCopy, in_a);
}
inline ColorI& ColorI::operator*=(const F32 in_mul)
{
red = U8((F32(red) * in_mul) + 0.5f);
green = U8((F32(green) * in_mul) + 0.5f);
blue = U8((F32(blue) * in_mul) + 0.5f);
alpha = U8((F32(alpha) * in_mul) + 0.5f);
return *this;
}
inline ColorI& ColorI::operator*=(const S32 in_mul)
{
red = red * in_mul;
green = green * in_mul;
blue = blue * in_mul;
alpha = alpha * in_mul;
return *this;
}
inline ColorI& ColorI::operator/=(const S32 in_mul)
{
AssertFatal(in_mul != 0.0f, "Error, div by zero...");
red = red / in_mul;
green = green / in_mul;
blue = blue / in_mul;
alpha = alpha / in_mul;
return *this;
}
inline ColorI ColorI::operator+(const ColorI &in_add) const
{
ColorI tmp;
tmp.red = red + in_add.red;
tmp.green = green + in_add.green;
tmp.blue = blue + in_add.blue;
tmp.alpha = alpha + in_add.alpha;
return tmp;
}
inline ColorI ColorI::operator*(const F32 in_mul) const
{
ColorI temp(*this);
temp *= in_mul;
return temp;
}
inline ColorI ColorI::operator*(const S32 in_mul) const
{
ColorI temp(*this);
temp *= in_mul;
return temp;
}
inline ColorI ColorI::operator/(const S32 in_mul) const
{
ColorI temp(*this);
temp /= in_mul;
return temp;
}
inline bool ColorI::operator==(const ColorI& in_Cmp) const
{
return (red == in_Cmp.red && green == in_Cmp.green && blue == in_Cmp.blue && alpha == in_Cmp.alpha);
@ -793,27 +667,6 @@ inline bool ColorI::operator!=(const ColorI& in_Cmp) const
return (red != in_Cmp.red || green != in_Cmp.green || blue != in_Cmp.blue || alpha != in_Cmp.alpha);
}
inline ColorI& ColorI::operator+=(const ColorI& in_rAdd)
{
red += in_rAdd.red;
green += in_rAdd.green;
blue += in_rAdd.blue;
alpha += in_rAdd.alpha;
return *this;
}
inline void ColorI::interpolate(const ColorI& in_rC1,
const ColorI& in_rC2,
const F32 in_factor)
{
F32 f2= 1.0f - in_factor;
red = U8(((F32(in_rC1.red) * f2) + (F32(in_rC2.red) * in_factor)) + 0.5f);
green = U8(((F32(in_rC1.green) * f2) + (F32(in_rC2.green) * in_factor)) + 0.5f);
blue = U8(((F32(in_rC1.blue) * f2) + (F32(in_rC2.blue) * in_factor)) + 0.5f);
alpha = U8(((F32(in_rC1.alpha) * f2) + (F32(in_rC2.alpha) * in_factor)) + 0.5f);
}
inline U32 ColorI::getARGBPack() const
{
return (U32(alpha) << 24) |
@ -971,35 +824,72 @@ inline String ColorI::getHex() const
return result;
}
inline ColorI ColorI::toGamma()
inline LinearColorF::LinearColorF( const ColorI &color)
{
ColorF color = (ColorF)*this;
return (ColorI)color.toGamma();
red = sSrgbToLinear[color.red],
green = sSrgbToLinear[color.green],
blue = sSrgbToLinear[color.blue],
alpha = F32(color.alpha * gOneOver255);
}
inline ColorI ColorI::toLinear()
inline ColorI LinearColorF::toColorI(const bool keepAsLinear)
{
ColorF color = (ColorF)*this;
return (ColorI)color.toLinear();
if (isClamped())
{
if (keepAsLinear)
{
return ColorI(U8(red * 255.0f + 0.5), U8(green * 255.0f + 0.5), U8(blue * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
}
else
{
#ifdef TORQUE_USE_LEGACY_GAMMA
float r = mPow(red, gOneOverGamma);
float g = mPow(green, gOneOverGamma);
float b = mPow(blue, gOneOverGamma);
return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
#else
float r = red < 0.0031308f ? 12.92f * red : 1.055 * mPow(red, 1.0f / 2.4f) - 0.055f;
float g = green < 0.0031308f ? 12.92f * green : 1.055 * mPow(green, 1.0f / 2.4f) - 0.055f;
float b = blue < 0.0031308f ? 12.92f * blue : 1.055 * mPow(blue, 1.0f / 2.4f) - 0.055f;
return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
#endif
}
}
else
{
LinearColorF color = LinearColorF(*this);
color.clamp();
if (keepAsLinear)
{
return ColorI(U8(color.red * 255.0f + 0.5), U8(color.green * 255.0f + 0.5), U8(color.blue * 255.0f + 0.5), U8(color.alpha * 255.0f + 0.5));
}
else
{
#ifdef TORQUE_USE_LEGACY_GAMMA
float r = mPow(red, gOneOverGamma);
float g = mPow(green, gOneOverGamma);
float b = mPow(blue, gOneOverGamma);
return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
#else
float r = red < 0.0031308f ? 12.92f * red : 1.055 * mPow(red, 1.0f / 2.4f) - 0.055f;
float g = green < 0.0031308f ? 12.92f * green : 1.055 * mPow(green, 1.0f / 2.4f) - 0.055f;
float b = blue < 0.0031308f ? 12.92f * blue : 1.055 * mPow(blue, 1.0f / 2.4f) - 0.055f;
return ColorI(U8(r * 255.0f + 0.5), U8(g * 255.0f + 0.5), U8(b * 255.0f + 0.5), U8(alpha * 255.0f + 0.5));
#endif
}
}
}
//-------------------------------------- INLINE CONVERSION OPERATORS
inline ColorF::operator ColorI() const
inline ColorI ColorI::fromLinear()
{
return ColorI(U8(red * 255.0f + 0.5),
U8(green * 255.0f + 0.5),
U8(blue * 255.0f + 0.5),
U8(alpha * 255.0f + 0.5));
}
inline ColorI::operator ColorF() const
{
const F32 inv255 = 1.0f / 255.0f;
return ColorF(F32(red) * inv255,
F32(green) * inv255,
F32(blue) * inv255,
F32(alpha) * inv255);
//manually create LinearColorF, otherwise it will try and convert to linear first
LinearColorF linearColor = LinearColorF(F32(red) * 255.0f + 0.5f,
F32(red) * 255.0f + 0.5f,
F32(red) * 255.0f + 0.5f,
F32(alpha) * 255.0f + 0.5f);
//convert back to srgb
return linearColor.toColorI();
}
#endif //_COLOR_H_

View file

@ -271,9 +271,9 @@ bool Stream::write(const ColorI& rColor)
return success;
}
bool Stream::write(const ColorF& rColor)
bool Stream::write(const LinearColorF& rColor)
{
ColorI temp = rColor;
ColorI temp = LinearColorF(rColor).toColorI();
return write(temp);
}
@ -287,7 +287,7 @@ bool Stream::read(ColorI* pColor)
return success;
}
bool Stream::read(ColorF* pColor)
bool Stream::read(LinearColorF* pColor)
{
ColorI temp;
bool success = read(&temp);

View file

@ -41,7 +41,7 @@
/// @}
class ColorI;
class ColorF;
class LinearColorF;
struct NetAddress;
class RawData;
class String;
@ -155,11 +155,11 @@ public:
/// Write an integral color to the stream.
bool write(const ColorI&);
/// Write a floating point color to the stream.
bool write(const ColorF&);
bool write(const LinearColorF&);
/// Read an integral color from the stream.
bool read(ColorI*);
/// Read a floating point color from the stream.
bool read(ColorF*);
bool read(LinearColorF*);
/// Write a network address to the stream.
bool write(const NetAddress &);

View file

@ -31,12 +31,12 @@
namespace ConvertRGB
{
ColorF toLUV( const ColorF &rgbColor )
LinearColorF toLUV( const LinearColorF &rgbColor )
{
static const Point3F scXYZLUVDot( 1.0f, 15.0f, 3.0f );
static const Point2F sc49( 4.0f, 9.0f );
ColorF xyzColor = ConvertRGB::toXYZ( rgbColor );
LinearColorF xyzColor = ConvertRGB::toXYZ( rgbColor );
const Point2F &xyz_xy = *((Point2F *)&xyzColor);
@ -44,12 +44,12 @@ ColorF toLUV( const ColorF &rgbColor )
uvColor.convolve( xyz_xy );
uvColor /= mDot( *(Point3F *)&xyzColor, scXYZLUVDot );
return ColorF( uvColor.x, uvColor.y, xyzColor.green, rgbColor.alpha );
return LinearColorF( uvColor.x, uvColor.y, xyzColor.green, rgbColor.alpha );
}
ColorF toLUVScaled( const ColorF &rgbColor )
LinearColorF toLUVScaled( const LinearColorF &rgbColor )
{
ColorF luvColor = toLUV( rgbColor );
LinearColorF luvColor = toLUV( rgbColor );
luvColor.red /= 0.62f;
luvColor.green /= 0.62f;
return luvColor;

View file

@ -29,9 +29,9 @@
namespace ConvertRGB
{
ColorF toLUV( const ColorF &rgbColor );
ColorF toLUVScaled( const ColorF &rgbColor );
ColorF fromLUV( const ColorF &luvColor );
LinearColorF toLUV( const LinearColorF &rgbColor );
LinearColorF toLUVScaled( const LinearColorF &rgbColor );
LinearColorF fromLUV( const LinearColorF &luvColor );
};
#endif

View file

@ -46,20 +46,20 @@ static const F32 scXYZ2RGB[] =
0.0f, 0.0f, 0.0f, 1.0f,
};
ColorF toXYZ( const ColorF &rgbColor )
LinearColorF toXYZ( const LinearColorF &rgbColor )
{
const MatrixF &rgb2xyz = *((MatrixF *)scRGB2XYZ);
ColorF retColor = rgbColor;
LinearColorF retColor = rgbColor;
rgb2xyz.mul( *(Point4F *)&retColor );
return retColor;
}
ColorF fromXYZ( const ColorF &xyzColor )
LinearColorF fromXYZ( const LinearColorF &xyzColor )
{
const MatrixF &xyz2rgb = *((MatrixF *)scXYZ2RGB);
ColorF retColor = xyzColor;
LinearColorF retColor = xyzColor;
xyz2rgb.mul( *(Point4F *)&retColor );
return retColor;
}

View file

@ -27,8 +27,8 @@
namespace ConvertRGB
{
ColorF toXYZ( const ColorF &rgbColor );
ColorF fromXYZ( const ColorF &xyzColor );
LinearColorF toXYZ( const LinearColorF &rgbColor );
LinearColorF fromXYZ( const LinearColorF &xyzColor );
};
#endif