Commit 599d6307 authored by Kenneth Vanhoey's avatar Kenneth Vanhoey

implementation of Lab space in ColourConverter

parent 7718659d
......@@ -47,29 +47,75 @@ class ColourConverter
public: // types
typedef Geom::Vector<3,REAL> VEC3 ;
enum ColourEncoding { C_RGB, C_XYZ, C_Luv } ;
/**
* Supported colour spaces
*/
enum ColourEncoding { C_RGB, C_XYZ, C_Luv, C_Lab } ;
public: // methods
/**
* Constructor
* @param col a VEC3 colour
* @param enc the colour space of provided colour
*/
ColourConverter(VEC3 col, enum ColourEncoding enc) ;
/**
* Destructor
*/
~ColourConverter() {} ;
/**
* getR
* @return RGB value of provided colour
*/
VEC3 getRGB() ;
/**
* getR
* @return Luv value of provided colour
*/
VEC3 getLuv() ;
/**
* getR
* @return Lab value of provided colour
*/
VEC3 getLab() ;
/**
* getR
* @return XYZ value of provided colour
*/
VEC3 getXYZ() ;
public: // members
/**
* Colour space of original (unaltered) data
*/
enum ColourEncoding originalEnc ;
private: // private members
VEC3 *RGB ;
VEC3 *Luv ;
VEC3 *Lab ;
VEC3 *XYZ ;
bool convert(enum ColourEncoding from, enum ColourEncoding to) ;
void convertRGBtoXYZ() ;
void convertXYZtoRGB() ;
void convertXYZtoLuv() ;
void convertLuvToXYZ() ;
void convertXYZtoRGB() ;
void convertXYZtoLab() ;
void convertLabToXYZ() ;
private: // private constants
// D65 reference white
static const REAL Xn = 0.950456 ;
static const REAL Yn = 1.0 ;
static const REAL Zn = 1.088754 ;
static const REAL un = 0.197832 ;
static const REAL vn = 0.468340 ;
} ;
......
......@@ -29,6 +29,7 @@ template<typename REAL>
ColourConverter<REAL>::ColourConverter(VEC3 col, enum ColourEncoding enc) :
RGB(NULL),
Luv(NULL),
Lab(NULL),
XYZ(NULL)
{
originalEnc = enc ;
......@@ -45,6 +46,10 @@ ColourConverter<REAL>::ColourConverter(VEC3 col, enum ColourEncoding enc) :
case (C_XYZ) :
XYZ = new VEC3(col) ;
break ;
case (C_Lab) :
Lab = new VEC3(col) ;
break ;
}
}
......@@ -64,6 +69,14 @@ Geom::Vector<3,REAL> ColourConverter<REAL>::getLuv() {
return *Luv ;
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getLab() {
if (Luv == NULL)
convert(originalEnc,C_Lab) ;
return *Luv ;
}
template<typename REAL>
Geom::Vector<3,REAL> ColourConverter<REAL>::getXYZ() {
if (XYZ == NULL) {
......@@ -160,8 +173,79 @@ void ColourConverter<REAL>::convertLuvToXYZ() {
XYZ = new VEC3(X,Y,Z) ;
}
/*
template<typename REAL>
REAL f(REAL x) {
if (x > 0.008856)
return pow(x,1.0/3.0) ;
else
return 7.787 * x + 16.0/116.0 ;
}*/
template<typename REAL>
void ColourConverter<REAL>::convertXYZtoLab() {
REAL L,a,b ;
REAL &X = (*XYZ)[0] ;
REAL &Y = (*XYZ)[1] ;
REAL &Z = (*XYZ)[2] ;
struct Local {
static REAL f(REAL x) {
if (x > 0.008856)
return pow(x,1.0/3.0) ;
else
return 7.787 * x + 16.0/116.0 ;
}
} ;
if (Y > 0.008856)
L = 116.0f * pow(Y,1.0f/3.0) - 16 ;
else // near black
L = 903.3 * Y ;
a = 500.0 * (Local::f(X/Xn) - Local::f(Y/Yn)) ;
b = 200.0 * (Local::f(Y/Yn) - Local::f(Z/Zn)) ;
Lab = new VEC3(L,a,b) ;
}
template<typename REAL>
void ColourConverter<REAL>::convertLabToXYZ() {
REAL X,Y,Z ;
REAL &L = (*Luv)[0] ;
REAL &a = (*Luv)[1] ;
REAL &b = (*Luv)[2] ;
struct Local {
static REAL f(REAL x) {
if (x > 0.206893)
return pow(x,3.0) ;
else
return x / 7.787 - 16.0/903.3 ;
}
} ;
if (L > 8.0)
Y = pow(((L+16.0) / 116.0),3) ;
else // near black
Y = L / 903.3 ;
REAL nom = (L+16.0) / 116.0 ;
X = Xn * Local::f( nom + a/500.0) ;
Z = Zn * Local::f( nom - b/200.0) ;
XYZ = new VEC3(X,Y,Z) ;
}
template<typename REAL>
bool ColourConverter<REAL>::convert(enum ColourEncoding from, enum ColourEncoding to) {
if (to == from) {
std::cerr << "ColourConverter::convert(from,to) : conversion into same colour space" << std::endl ;
return false ;
}
switch(from) {
case(C_RGB) :
switch (to) {
......@@ -175,6 +259,12 @@ bool ColourConverter<REAL>::convert(enum ColourEncoding from, enum ColourEncodin
if (Luv == NULL)
convertXYZtoLuv() ;
break ;
case(C_Lab) :
if (XYZ == NULL)
convertRGBtoXYZ() ;
if (Lab == NULL)
convertXYZtoLab() ;
break ;
default :
std::cerr << "Colour conversion not supported" << std::endl ;
return false ;
......@@ -196,6 +286,13 @@ bool ColourConverter<REAL>::convert(enum ColourEncoding from, enum ColourEncodin
convertLuvToXYZ() ;
break ;
}
case(C_Lab) :
if (Lab == NULL) {
if (XYZ == NULL)
convertLuvToXYZ() ;
convertXYZtoLab() ;
}
break ;
default :
std::cerr << "Colour conversion not supported" << std::endl ;
return false ;
......@@ -212,11 +309,44 @@ bool ColourConverter<REAL>::convert(enum ColourEncoding from, enum ColourEncodin
if (Luv == NULL)
convertXYZtoLuv() ;
break ;
case(C_Lab) :
if (Lab == NULL)
convertXYZtoLab() ;
break ;
default :
std::cerr << "Colour conversion not supported" << std::endl ;
return false ;
}
break ;
case(C_Lab) :
switch (to) {
case(C_RGB) : {
if (RGB == NULL) {
if (XYZ == NULL)
convertLabToXYZ() ;
convertXYZtoRGB() ;
}
break ;
}
case(C_XYZ) : {
if (XYZ == NULL)
convertLabToXYZ() ;
break ;
}
case(C_Luv) :
if (Luv == NULL) {
if (XYZ == NULL)
convertLabToXYZ() ;
convertXYZtoLuv() ;
}
break ;
default :
std::cerr << "Colour conversion not supported" << std::endl ;
return false ;
}
break ;
default :
std::cerr << "Colour conversion not supported" << std::endl ;
return false ;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment