colourConverter.hpp 17.8 KB
Newer Older
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
1 2 3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library is distributed in the hope that it will be useful, but WITHOUT  *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
21 22 23 24
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

Sylvain Thery's avatar
Sylvain Thery committed
25 26
#include <algorithm>

27 28
namespace CGoGN
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
29

30 31
namespace Utils
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
32

Sylvain Thery's avatar
Sylvain Thery committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
template<typename REAL>
const REAL ColourConverter<REAL>::Xn = REAL(0.950456);

template<typename REAL>
const REAL ColourConverter<REAL>::Yn = REAL(1.0);

template<typename REAL>
const REAL ColourConverter<REAL>::Zn = REAL(1.088754);

template<typename REAL>
const REAL ColourConverter<REAL>::un = REAL(0.197832);

template<typename REAL>
const REAL ColourConverter<REAL>::vn = REAL(0.468340);

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
48
template<typename REAL>
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
49
ColourConverter<REAL>::ColourConverter(const VEC3& col, const enum ColourEncoding& enc) :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
50 51
	RGB(NULL),
	Luv(NULL),
52
	Lab(NULL),
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
53
	HSV(NULL),
54 55
	XYZ(NULL),
	HSL(NULL)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
56 57 58
{
	originalEnc = enc ;

59 60
	switch(originalEnc)
	{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
61
		case(C_RGB):
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
62 63 64 65
			#ifdef DEBUG
				if (!(-0.001 < col[0] && col[0] < 1.001 && -0.001 < col[1] && col[1] < 1.001 &&  -0.001 < col[2] && col[2] < 1.001))
					std::cerr << "Warning : an unvalid RGB color was entered in ColourConverter constructor" << std::endl ;
			#endif
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
66 67 68 69
			RGB = new VEC3(col) ;
			break ;

		case (C_Luv) :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
70 71 72 73
			#ifdef DEBUG
				if (!(-0.001 < col[0] && col[0] < 100.001 && -83.001 < col[1] && col[1] < 175.001 &&  -134.001 < col[2] && col[2] < 108.001))
					std::cerr << "Warning : an unvalid Luv color was entered in ColourConverter constructor" << std::endl ;
			#endif
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
74 75 76 77
			Luv = new VEC3(col) ;
			break ;

		case (C_XYZ) :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
78 79 80 81
			#ifdef DEBUG
				if (!(-0.001 < col[0] && col[0] < 1.001 && -0.001 < col[1] && col[1] < 1.001 &&  -0.001 < col[2] && col[2] < 1.001))
					std::cerr << "Warning : an unvalid XYZ color was entered in ColourConverter constructor" << std::endl ;
			#endif
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
82 83
			XYZ = new VEC3(col) ;
			break ;
84 85

		case (C_Lab) :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
86 87 88 89
			#ifdef DEBUG
				if (!(-0.001 < col[0] && col[0] < 100.001 && -86.001 < col[1] && col[1] < 98.001 && -108.001 < col[2] && col[2] < 95.001))
						std::cerr << "Warning : an unvalid Lab color was entered in ColourConverter constructor" << std::endl ;
			#endif
90 91
			Lab = new VEC3(col) ;
			break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
92 93
		case (C_HSV) :
			#ifdef DEBUG
94 95
				if (!(-0.001 < col[0] && col[0] < 1.001 && -0.001 < col[1] && col[1] < 1.001 && -0.001 < col[2] && col[2] < 1.001))
						std::cerr << "Warning : an unvalid HSV color was entered in ColourConverter constructor" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
96 97 98
			#endif
			HSV = new VEC3(col) ;
			break ;
99 100 101 102 103 104 105
		case (C_HSL) :
			#ifdef DEBUG
				if (!(-0.001 < col[0] && col[0] < 1.001 && -0.001 < col[1] && col[1] < 1.001 && -0.001 < col[2] && col[2] < 1.001))
						std::cerr << "Warning : an unvalid HSL color was entered in ColourConverter constructor" << std::endl ;
			#endif
			HSL = new VEC3(col) ;
			break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
106 107 108
	}
}

109 110 111 112 113 114 115
template<typename REAL>
ColourConverter<REAL>::~ColourConverter()
{
	delete RGB ;
	delete Luv ;
	delete XYZ ;
	delete Lab ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
116
	delete HSV ;
117
	delete HSL ;
118 119
}

120
template<typename REAL>
121 122 123 124
Geom::Vector<3,REAL> ColourConverter<REAL>::getColour(enum ColourEncoding enc)
{
	switch (enc)
	{
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
	case (C_RGB) :
		return getRGB() ;
		break ;

	case (C_XYZ) :
		return getXYZ() ;
		break ;

	case (C_Luv) :
		return getLuv() ;
		break ;

	case (C_Lab) :
		return getLab() ;
		break ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
141
	case (C_HSV) :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
142 143 144
		return getHSV() ;
		break ;

145 146 147 148
	case (C_HSL) :
		return getHSL() ;
		break ;

149 150 151 152 153 154 155
	default :
		assert(!"Should never arrive here : ColourConverter::getColour default case") ;
		return getOriginal() ;
	}
}

template<typename REAL>
156 157 158
Geom::Vector<3,REAL>
ColourConverter<REAL>::getOriginal()
{
159 160 161
	return getColour(this->originalEnc) ;
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
162
template<typename REAL>
163 164 165
Geom::Vector<3,REAL>
ColourConverter<REAL>::getRGB()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
166 167 168 169 170 171 172
	if (RGB == NULL)
		convert(originalEnc,C_RGB) ;

	return *RGB ;
}

template<typename REAL>
173 174 175
Geom::Vector<3,REAL>
ColourConverter<REAL>::getLuv()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
176 177 178 179 180 181
	if (Luv == NULL)
		convert(originalEnc,C_Luv) ;

	return *Luv ;
}

182
template<typename REAL>
183 184 185
Geom::Vector<3,REAL>
ColourConverter<REAL>::getLab()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
186
	if (Lab == NULL)
187 188
		convert(originalEnc,C_Lab) ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
189
	return *Lab ;
190 191
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
192
template<typename REAL>
193 194 195
Geom::Vector<3,REAL>
ColourConverter<REAL>::getXYZ()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
196 197 198 199 200 201 202
	if (XYZ == NULL) {
		convert(originalEnc,C_XYZ) ;
	}

	return *XYZ ;
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
203
template<typename REAL>
204 205 206
Geom::Vector<3,REAL>
ColourConverter<REAL>::getHSV()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
207 208 209 210 211 212
	if (HSV == NULL)
		convert(originalEnc,C_HSV) ;

	return *HSV ;
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
213
template<typename REAL>
214 215 216 217 218 219 220 221 222 223 224 225 226
Geom::Vector<3,REAL>
ColourConverter<REAL>::getHSL()
{
	if (HSL == NULL)
		convert(originalEnc,C_HSL) ;

	return *HSL ;
}

template<typename REAL>
void
ColourConverter<REAL>::convertRGBtoXYZ()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
227 228
	Geom::Matrix<3,3,REAL> M ;

Sylvain Thery's avatar
Sylvain Thery committed
229 230 231
	M(0,0) = REAL(0.412453);
	M(0, 1) = REAL(0.357580);
	M(0, 2) = REAL(0.180423);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
232

Sylvain Thery's avatar
Sylvain Thery committed
233 234 235
	M(1, 0) = REAL(0.212671);
	M(1, 1) = REAL(0.715160);
	M(1, 2) = REAL(0.072169);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
236

Sylvain Thery's avatar
Sylvain Thery committed
237 238 239
	M(2, 0) = REAL(0.019334);
	M(2, 1) = REAL(0.119193);
	M(2, 2) = REAL(0.950227);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
240 241 242

	VEC3 c = M * (*RGB) ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
243 244 245 246
	if (XYZ != NULL)
		*XYZ = c ;
	else
		XYZ = new VEC3(c) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
247 248 249
}

template<typename REAL>
250 251 252
void
ColourConverter<REAL>::convertXYZtoRGB()
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
253 254
	Geom::Matrix<3,3,REAL> M ;

Sylvain Thery's avatar
Sylvain Thery committed
255 256 257
	M(0, 0) = REAL(3.240479);
	M(0, 1) = REAL(-1.537150);
	M(0, 2) = REAL(-0.498535);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
258

Sylvain Thery's avatar
Sylvain Thery committed
259 260 261
	M(1, 0) = REAL(-0.969256);
	M(1, 1) = REAL(1.875992);
	M(1, 2) = REAL(0.041556);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
262

Sylvain Thery's avatar
Sylvain Thery committed
263 264 265
	M(2, 0) = REAL(0.055648);
	M(2, 1) = REAL(-0.204043);
	M(2, 2) = REAL(1.057311);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
266 267 268

	VEC3 c = M * (*XYZ) ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
269 270 271 272
	if (RGB != NULL)
		*RGB = c ;
	else
		RGB = new VEC3(c) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
273 274 275
}

template<typename REAL>
276 277
void
ColourConverter<REAL>::convertRGBtoHSV()
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
278 279 280 281 282 283 284
{
	const REAL& r = (*RGB)[0] ;
	const REAL& g = (*RGB)[1] ;
	const REAL& b = (*RGB)[2] ;
	const REAL& max = std::max(std::max(r,g),b) ;
	const REAL& min = std::min(std::min(r,g),b) ;

285

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
286
	VEC3 c ;
287 288 289 290 291 292 293
	REAL& H = c[0] ;
	REAL& S = c[1] ;
	REAL& V = c[2] ;

	const REAL diff = max - min ;

	V = max ;
Sylvain Thery's avatar
Sylvain Thery committed
294
	S = max == 0.0f ? 0.0f : diff / max ;
295 296


Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
297 298
	if (max == min)
	{
299
		H = 0 ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
300
	}
301
	else
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
302
	{
303 304 305 306 307 308 309 310 311 312 313 314
		if (max == r)
		{
			H = (g - b) / diff + (g < b ? 6 : 0) ;
		}
		else if (max == g)
		{
			H = (b - r) / diff + 2 ;
		}
		else if (max == b)
		{
			H = (r - g) / diff + 4 ;
		}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
315
	}
316
	H /= 6. ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
317 318 319 320 321 322 323 324

	if (HSV != NULL)
		*HSV = c ;
	else
		HSV = new VEC3(c) ;
}

template<typename REAL>
325 326
void
ColourConverter<REAL>::convertHSVtoRGB()
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
327 328
{
	const REAL& H = (*HSV)[0] ;
329 330
	const REAL& S = (*HSV)[1] ;
	const REAL& V = (*HSV)[2] ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
331

Sylvain Thery's avatar
Sylvain Thery committed
332
	const int i = int(std::floor(H * 6));
333 334 335 336
	const REAL f = H * 6 - i;
	const REAL p = V * (1 - S);
	const REAL q = V * (1 - f * S);
	const REAL t = V * (1 - (1 - f) * S);
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
337 338

	VEC3 c ;
339 340 341 342 343
	REAL& r = c[0] ;
	REAL& g = c[1] ;
	REAL& b = c[2] ;

	switch(i % 6)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
344
	{
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
	case 0: r = V, g = t, b = p; break;
	case 1: r = q, g = V, b = p; break;
	case 2: r = p, g = V, b = t; break;
	case 3: r = p, g = q, b = V; break;
	case 4: r = t, g = p, b = V; break;
	case 5: r = V, g = p, b = q; break;
	}

	if (RGB != NULL)
		*RGB = c ;
	else
		RGB = new VEC3(c) ;
}

template<typename REAL>
void
ColourConverter<REAL>::convertRGBtoHSL()
{
	const REAL& r = (*RGB)[0] ;
	const REAL& g = (*RGB)[1] ;
	const REAL& b = (*RGB)[2] ;
	const REAL& max = std::max(std::max(r,g),b) ;
	const REAL& min = std::min(std::min(r,g),b) ;

	VEC3 c ;
	REAL& H = c[0] ;
	REAL& S = c[1] ;
	REAL& L = c[2] ;

	const REAL sum = max + min ;
Sylvain Thery's avatar
Sylvain Thery committed
375
	L = sum / 2.0f ;
376 377 378 379 380 381 382 383 384

	if (max == min)
	{
		H = 0 ;
		S = 0 ;
	}
	else
	{
		const REAL diff = max - min ;
Sylvain Thery's avatar
Sylvain Thery committed
385
		S = L > 0.5f ? diff / (2 - sum) : diff / sum ;
386 387

		if (max == r)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
388
		{
389
			H = (g - b) / diff + (g < b ? 6 : 0) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
390
		}
391
		else if (max == g)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
392
		{
393
			H = (b - r) / diff + 2 ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
394
		}
395
		else if (max == b)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
396
		{
397
			H = (r - g) / diff + 4 ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
398
		}
399 400
	}
	H /= 6. ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
401

402 403 404 405 406
	if (HSL != NULL)
		*HSL = c ;
	else
		HSL = new VEC3(c) ;
}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
407

408 409 410 411 412 413 414 415 416 417 418 419 420
template<typename REAL>
REAL
ColourConverter<REAL>::hue2rgb(const REAL& p, const REAL& q, REAL t)
{
	if(t < 0)
		t += 1 ;
	if(t > 1)
		t -= 1 ;
	if(t < 1/6.)
		return p + (q - p) * 6 * t ;
	if(t < 1/2.)
		return q ;
	if(t < 2/3.)
Sylvain Thery's avatar
Sylvain Thery committed
421
		return p + (q - p) * (REAL(2.0/3.0) - t) * 6.0f ;
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448

	return p ;
}

template<typename REAL>
void
ColourConverter<REAL>::convertHSLtoRGB()
{
	const REAL& H = (*HSL)[0] ;
	const REAL& S = (*HSL)[1] ;
	const REAL& L = (*HSL)[2] ;

	VEC3 c ;
	REAL& r = c[0] ;
	REAL& g = c[1] ;
	REAL& b = c[2] ;

    if(S < 1e-8)
    {
    	r = L ;
    	g = L ;
    	b = L ;
    }
    else
    {
    	const REAL q = L < 0.5 ? L * (1 + S) : L + S - L * S;
    	const REAL p = 2 * L - q ;
Sylvain Thery's avatar
Sylvain Thery committed
449
		r = hue2rgb(p, q, H + REAL(1./3.));
450
    	g = hue2rgb(p, q, H) ;
Sylvain Thery's avatar
Sylvain Thery committed
451
    	b = hue2rgb(p, q, H - REAL(1./3.)) ;
452
    }
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
453 454 455 456 457 458 459 460

	if (RGB != NULL)
		*RGB = c ;
	else
		RGB = new VEC3(c) ;
}

template<typename REAL>
461 462
void
ColourConverter<REAL>::convertXYZtoLuv()
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
463
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
464 465 466 467 468 469
	REAL L,u,v ;

	REAL &X = (*XYZ)[0] ;
	REAL &Y = (*XYZ)[1] ;
	REAL &Z = (*XYZ)[2] ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
470 471
	REAL Ydiv = Y/Yn ;
	if (Ydiv > 0.008856)
Sylvain Thery's avatar
Sylvain Thery committed
472
		L = 116.0f* pow(Ydiv,1.0f/3.0f) - 16.0f ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
473
	else // near black
Sylvain Thery's avatar
Sylvain Thery committed
474
		L = 903.3f * Ydiv ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
475

Sylvain Thery's avatar
Sylvain Thery committed
476 477 478
	REAL den = X + 15.0f * Y + 3 * Z ;
	REAL u1 = (4.0f * X) / den ;
	REAL v1 = (9.0f * Y) / den ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
479 480
	u = 13*L * (u1 - un) ;
	v = 13*L * (v1 - vn) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
481

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
482 483 484 485
	if (Luv != NULL)
		*Luv = VEC3(L,u,v) ;
	else
		Luv = new VEC3(L,u,v) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
486 487 488
}

template<typename REAL>
489 490
void
ColourConverter<REAL>::convertLuvToXYZ()
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
491
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
492 493 494 495 496 497 498
	REAL X,Y,Z ;

	REAL &L = (*Luv)[0] ;
	REAL &u = (*Luv)[1] ;
	REAL &v = (*Luv)[2] ;

	if (L > 8.0)
Sylvain Thery's avatar
Sylvain Thery committed
499
		Y = pow(((L+16.0f) / 116.0f),3) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
500
	else // near black
Sylvain Thery's avatar
Sylvain Thery committed
501
		Y = Yn * L / 903.3f ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
502

Sylvain Thery's avatar
Sylvain Thery committed
503
	REAL den = 13.0f * L ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
504 505
	REAL u1 = u/den + un ;
	REAL v1 = v/den + vn ;
Sylvain Thery's avatar
Sylvain Thery committed
506 507 508
	den = 4.0f*v1 ;
	X = Y * 9.0f * u1 / den ;
	Z = Y * (12.0f - 3.0f*u1 - 20.0f*v1) / den ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
509

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
510 511 512 513
	if (XYZ != NULL)
		*XYZ = VEC3(X,Y,Z) ;
	else
		XYZ = new VEC3(X,Y,Z) ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
514 515
}

516
template<typename REAL>
517 518 519
void
ColourConverter<REAL>::convertXYZtoLab()
{
520 521 522 523 524 525
	REAL L,a,b ;

	REAL &X = (*XYZ)[0] ;
	REAL &Y = (*XYZ)[1] ;
	REAL &Z = (*XYZ)[2] ;

526 527 528 529
	struct Local
	{
		static REAL f(REAL x)
		{
530
			if (x > 0.008856)
Sylvain Thery's avatar
Sylvain Thery committed
531
			return pow(x,1.0f/3.0f) ;
532
			else
Sylvain Thery's avatar
Sylvain Thery committed
533
				return 7.787f * x + 16.0f/116.0f ;
534 535 536 537
		}
	} ;

	if (Y > 0.008856)
Sylvain Thery's avatar
Sylvain Thery committed
538
		L = 116.0f * pow(Y,1.0f/3.0f) - 16 ;
539
	else // near black
Sylvain Thery's avatar
Sylvain Thery committed
540
		L = 903.3f * Y ;
541

Sylvain Thery's avatar
Sylvain Thery committed
542 543
	a = 500.0f * (Local::f(X/Xn) - Local::f(Y/Yn)) ;
	b = 200.0f * (Local::f(Y/Yn) - Local::f(Z/Zn)) ;
544

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
545 546 547 548
	if (Lab != NULL)
		*Lab = VEC3(L,a,b) ;
	else
		Lab = new VEC3(L,a,b) ;
549 550 551
}

template<typename REAL>
552 553 554
void
ColourConverter<REAL>::convertLabToXYZ()
{
555 556
	REAL X,Y,Z ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
557 558 559
	REAL &L = (*Lab)[0] ;
	REAL &a = (*Lab)[1] ;
	REAL &b = (*Lab)[2] ;
560

561 562 563 564
	struct Local
	{
		static REAL f(REAL x)
		{
Sylvain Thery's avatar
Sylvain Thery committed
565 566
			if (x > 0.206893f)
			return pow(x,3.0f) ;
567
			else
Sylvain Thery's avatar
Sylvain Thery committed
568
				return x / 7.787f - REAL(16.0/903.3) ;
569 570 571
		}
	} ;

Sylvain Thery's avatar
Sylvain Thery committed
572 573
	if (L > 8.0f)
		Y = pow(((L+16.0f) / 116.0f),3) ;
574
	else // near black
Sylvain Thery's avatar
Sylvain Thery committed
575
		Y = L / 903.3f ;
576

Sylvain Thery's avatar
Sylvain Thery committed
577 578 579
	REAL nom = (L+16.0f) / 116.0f ;
	X = Xn * Local::f( nom +  a/500.0f) ;
	Z = Zn * Local::f( nom -  b/200.0f) ;
580

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
581 582 583 584
	if (XYZ != NULL)
		*XYZ = VEC3(X,Y,Z) ;
	else
		XYZ = new VEC3(X,Y,Z) ;
585 586
}

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
587
template<typename REAL>
588 589 590
bool
ColourConverter<REAL>::convert(enum ColourEncoding from, enum ColourEncoding to)
{
591 592
	if (to == from)
	{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
593 594 595 596
		#ifdef DEBUG
			std::cout << "WARNING ColourConverter::convert(from,to) : conversion into same colour space" << std::endl ;
		#endif
		return true ;
597 598
	}

599 600
	switch(from)
	{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
601
		case(C_RGB) :
602 603
			switch (to)
			{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
604 605 606 607 608 609
				case (C_XYZ) :
					if (XYZ == NULL)
						convertRGBtoXYZ() ;
					break ;
				case (C_Luv) :
					if (Luv == NULL)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
610 611 612
					{
						if (XYZ == NULL)
							convertRGBtoXYZ() ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
613
						convertXYZtoLuv() ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
614
					}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
615
					break ;
616 617
				case(C_Lab) :
					if (Lab == NULL)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
618 619 620
					{
						if (XYZ == NULL)
							convertRGBtoXYZ() ;
621
						convertXYZtoLab() ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
622 623 624 625 626
					}
				break ;
				case(C_HSV) :
					if (HSV == NULL)
						convertRGBtoHSV() ;
627
					break ;
628 629 630 631
				case(C_HSL) :
					if (HSL == NULL)
						convertRGBtoHSL() ;
					break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
632
				default :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
633
					std::cerr << "Colour conversion not supported" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
634 635 636 637 638
					return false ;
			}
			break ;

		case(C_Luv) :
639 640
			switch(to)
			{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
641
				case(C_RGB) : {
642 643
					if (RGB == NULL)
					{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
644 645 646 647 648 649 650 651 652 653 654
						if (XYZ == NULL)
							convertLuvToXYZ() ;
						convertXYZtoRGB() ;
					}
					break ;
				}
				case(C_XYZ) : {
					if (XYZ == NULL)
						convertLuvToXYZ() ;
					break ;
				}
655
				case(C_Lab) :
656 657
					if (Lab == NULL)
					{
658 659 660 661 662
						if (XYZ == NULL)
							convertLuvToXYZ() ;
						convertXYZtoLab() ;
					}
					break ;
663
				case(C_HSV) :
664 665 666 667
					if (HSV == NULL)
					{
						if (RGB == NULL)
						{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
668 669 670 671 672 673 674
							if (XYZ == NULL)
								convertLuvToXYZ() ;
							convertXYZtoRGB() ;
						}
						convertRGBtoHSV() ;
					}
					break ;
675
				case(C_HSL) : {
676 677 678 679
					if (HSL == NULL)
					{
						if (RGB == NULL)
						{
680 681 682 683 684 685 686
							if (XYZ == NULL)
								convertLuvToXYZ() ;
							convertXYZtoRGB() ;
						}
						convertRGBtoHSL() ;
					}
					break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
687
				}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
688
				default :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
689
					std::cerr << "Colour conversion not supported" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
690 691 692 693 694
					return false ;
			}
			break ;

		case(C_XYZ) :
695 696
			switch (to)
			{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
697
				case(C_RGB) :
698
					if (RGB == NULL)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
699 700 701 702 703 704
						convertXYZtoRGB() ;
					break ;
				case(C_Luv) :
					if (Luv == NULL)
						convertXYZtoLuv() ;
					break ;
705 706 707 708
				case(C_Lab) :
					if (Lab == NULL)
						convertXYZtoLab() ;
					break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
709
				case(C_HSV) :
710 711 712
						if (HSV == NULL)
						{
							if (RGB == NULL)
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
713 714 715 716
								convertXYZtoRGB() ;
							convertRGBtoHSV() ;
						}
					break ;
717
				case(C_HSL) :
718 719 720
					if (HSL == NULL)
					{
						if (RGB == NULL)
721
							convertXYZtoRGB() ;
722 723
						convertRGBtoHSL() ;
					}
724
					break ;
725
				default :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
726
					std::cerr << "Colour conversion not supported" << std::endl ;
727 728 729 730 731
					return false ;
			}
			break ;

		case(C_Lab) :
732 733
			switch (to)
			{
734
				case(C_RGB) : {
735 736
					if (RGB == NULL)
					{
737 738 739 740 741 742 743 744 745 746 747 748
						if (XYZ == NULL)
							convertLabToXYZ() ;
						convertXYZtoRGB() ;
					}
					break ;
				}
				case(C_XYZ) : {
					if (XYZ == NULL)
						convertLabToXYZ() ;
					break ;
				}
				case(C_Luv) :
749 750
					if (Luv == NULL)
					{
751 752 753 754 755
						if (XYZ == NULL)
							convertLabToXYZ() ;
						convertXYZtoLuv() ;
					}
					break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
756
				case(C_HSV) : {
757 758 759 760
					if (HSV == NULL)
					{
						if (RGB == NULL)
						{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
761 762 763 764 765 766 767 768
							if (XYZ == NULL)
								convertLabToXYZ() ;
							convertXYZtoRGB() ;
						}
						convertRGBtoHSV() ;
					}
					break ;
				}
769
				case(C_HSL) : {
770 771 772 773
					if (HSL == NULL)
					{
						if (RGB == NULL)
						{
774 775 776 777 778 779 780 781
							if (XYZ == NULL)
								convertLabToXYZ() ;
							convertXYZtoRGB() ;
						}
						convertRGBtoHSL() ;
					}
					break ;
				}
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
782
				default :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
783
					std::cerr << "Colour conversion not supported" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
784 785 786
					return false ;
			}
			break ;
787

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
788
		case(C_HSV) :
789 790
				switch (to)
				{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
791
					case(C_RGB) : {
792 793
						if (RGB == NULL)
						{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
794 795 796 797 798 799 800 801 802 803 804 805 806 807
							convertHSVtoRGB() ;
						}
						break ;
					}
					case(C_XYZ) : {
						if (XYZ == NULL)
						{
							if (RGB == NULL)
								convertHSVtoRGB() ;
							convertRGBtoXYZ() ;
						}
						break ;
					}
					case(C_Lab) :
808 809
						if (Lab == NULL)
						{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
810 811 812 813 814 815 816 817 818 819 820 821
							if (XYZ == NULL)
							{
								if (RGB == NULL)
								{
									convertHSVtoRGB() ;
								}
								convertRGBtoXYZ() ;
							}
							convertXYZtoLab() ;
						}
						break ;
					case(C_Luv) :
822 823
						if (Luv == NULL)
						{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
824 825 826 827 828 829 830 831 832 833 834
							if (XYZ == NULL)
							{
								if (RGB == NULL)
								{
									convertHSVtoRGB() ;
								}
								convertRGBtoXYZ() ;
							}
							convertXYZtoLuv() ;
						}
						break ;
835
					case(C_HSL) :
836 837
						if (HSL == NULL)
						{
838 839 840 841 842
							if (RGB == NULL)
								convertHSVtoRGB() ;
							convertRGBtoHSL() ;
						}
						break ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
843 844 845 846 847 848
					default :
						std::cerr << "Colour conversion not supported" << std::endl ;
						return false ;
				}
				break ;

849
				case(C_HSL) :
850 851
						switch (to)
						{
852
							case(C_RGB) : {
853 854
								if (RGB == NULL)
								{
855 856 857 858 859 860 861 862 863 864 865 866 867 868
									convertHSLtoRGB() ;
								}
								break ;
							}
							case(C_XYZ) : {
								if (XYZ == NULL)
								{
									if (RGB == NULL)
										convertHSLtoRGB() ;
									convertRGBtoXYZ() ;
								}
								break ;
							}
							case(C_Lab) :
869 870
								if (Lab == NULL)
								{
871 872 873 874 875 876 877 878 879 880 881 882
									if (XYZ == NULL)
									{
										if (RGB == NULL)
										{
											convertHSLtoRGB() ;
										}
										convertRGBtoXYZ() ;
									}
									convertXYZtoLab() ;
								}
								break ;
							case(C_Luv) :
883 884
								if (Luv == NULL)
								{
885 886 887 888 889 890 891 892 893 894 895 896
									if (XYZ == NULL)
									{
										if (RGB == NULL)
										{
											convertHSLtoRGB() ;
										}
										convertRGBtoXYZ() ;
									}
									convertXYZtoLuv() ;
								}
								break ;
							case(C_HSL) :
897 898
								if (HSL == NULL)
								{
899 900 901 902 903 904 905 906 907 908 909
									if (RGB == NULL)
										convertHSLtoRGB() ;
									convertRGBtoHSV() ;
								}
								break ;
							default :
								std::cerr << "Colour conversion not supported" << std::endl ;
								return false ;
						}
						break ;

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
910
		default :
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
911
			std::cerr << "Colour conversion not supported" << std::endl ;
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
912 913 914 915 916 917 918
			return false ;
	}

	return true ;
}

} // namespace Utils
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
919

Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
920 921 922
} // namespace CGoGN