git-svn-id: http://moon:8086/svn/software/trunk/libsrc/_to_be_added@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
576 lines
11 KiB
C
Executable File
576 lines
11 KiB
C
Executable File
// ----------------------------------------------------------------------
|
|
// color_conv.c
|
|
// 21.02.2005, Jens Ahrensfeld
|
|
// ----------------------------------------------------------------------
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include "color_conv.h"
|
|
#include "colortypes.h"
|
|
#include "mutil.h"
|
|
|
|
// ----------------------------------------------------------------------
|
|
void rgb2hsv(color_vector_t *pRGB, color_vector_t *pHSV, int len)
|
|
{
|
|
int i;
|
|
double *rgb, *hsv, v_min, v_max, diff_max, diff_max_r, diff_r, diff_g, diff_b;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
rgb = (double*)&pRGB[i];
|
|
hsv = (double*)&pHSV[i];
|
|
|
|
v_min = smin(rgb[0], rgb[1]);
|
|
v_min = smin(v_min, rgb[2]);
|
|
|
|
v_max = smax(rgb[0], rgb[1]);
|
|
v_max = smax(v_max, rgb[2]);
|
|
|
|
diff_max = v_max - v_min;
|
|
|
|
hsv[2] = v_max;
|
|
|
|
if (diff_max == 0)
|
|
{
|
|
hsv[0] = diff_max;
|
|
hsv[1] = diff_max;
|
|
}
|
|
else
|
|
{
|
|
diff_max_r = 1.0/diff_max;
|
|
hsv[1] = diff_max/v_max;
|
|
|
|
diff_r = (((v_max - rgb[0])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
|
diff_g = (((v_max - rgb[1])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
|
diff_b = (((v_max - rgb[2])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
|
|
|
if (rgb[0] == v_max)
|
|
{
|
|
hsv[0] = diff_b - diff_g;
|
|
}
|
|
else
|
|
{
|
|
if (rgb[1] == v_max)
|
|
{
|
|
hsv[0] = 1.0/3 + diff_r - diff_b;
|
|
}
|
|
else
|
|
{
|
|
if (rgb[2] == v_max)
|
|
{
|
|
hsv[0] = 2.0/3 + diff_g - diff_r;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hsv[0] < 0)
|
|
hsv[0] += 1;
|
|
|
|
if (hsv[0] > 1.0)
|
|
hsv[0] -= 1;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void hsv2rgb(color_vector_t *pHSV, color_vector_t *pRGB, int len)
|
|
{
|
|
int i, j;
|
|
double h, t1, t2, t3, *rgb, *hsv;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
rgb = (double*)&pRGB[i];
|
|
hsv = (double*)&pHSV[i];
|
|
|
|
if (hsv[1] == 0)
|
|
{
|
|
rgb[0] = hsv[2];
|
|
rgb[1] = hsv[2];
|
|
rgb[2] = hsv[2];
|
|
|
|
continue;
|
|
}
|
|
|
|
h = hsv[0] * 6;
|
|
j = (int)h;
|
|
t1 = hsv[2]*(1 - hsv[1]);
|
|
t2 = hsv[2]*(1 - hsv[1]*(h-(double)j));
|
|
t3 = hsv[2]*(1 - hsv[1]*(1-(h-(double)j)));
|
|
|
|
switch(j)
|
|
{
|
|
case 0:
|
|
rgb[0] = hsv[2];
|
|
rgb[1] = t3;
|
|
rgb[2] = t1;
|
|
break;
|
|
|
|
case 1:
|
|
rgb[0] = t2;
|
|
rgb[1] = hsv[2];
|
|
rgb[2] = t1;
|
|
break;
|
|
|
|
case 2:
|
|
rgb[0] = t1;
|
|
rgb[1] = hsv[2];
|
|
rgb[2] = t3;
|
|
break;
|
|
|
|
case 3:
|
|
rgb[0] = t1;
|
|
rgb[1] = t2;
|
|
rgb[2] = hsv[2];
|
|
break;
|
|
|
|
case 4:
|
|
rgb[0] = t3;
|
|
rgb[1] = t1;
|
|
rgb[2] = hsv[2];
|
|
break;
|
|
|
|
default:
|
|
rgb[0] = hsv[2];
|
|
rgb[1] = t1;
|
|
rgb[2] = t2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void rgb2hsl(color_vector_t *pRGB, color_vector_t *pHSL, int len)
|
|
{
|
|
int i;
|
|
double *rgb, *hsl, v_min, v_max, diff_max, diff_max_r, diff_r, diff_g, diff_b;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
rgb = (double*)&pRGB[i];
|
|
hsl = (double*)&pHSL[i];
|
|
|
|
v_min = smin(rgb[0], rgb[1]);
|
|
v_min = smin(v_min, rgb[2]);
|
|
|
|
v_max = smax(rgb[0], rgb[1]);
|
|
v_max = smax(v_max, rgb[2]);
|
|
|
|
diff_max = v_max - v_min;
|
|
|
|
hsl[2] = (v_max + v_min)/2;
|
|
|
|
if (diff_max == 0)
|
|
{
|
|
hsl[0] = diff_max;
|
|
hsl[1] = diff_max;
|
|
}
|
|
else
|
|
{
|
|
diff_max_r = 1.0/diff_max;
|
|
|
|
if(hsl[2] < 0.5)
|
|
{
|
|
hsl[1] = diff_max/(v_max + v_min);
|
|
}
|
|
else
|
|
{
|
|
hsl[1] = diff_max/(2 - v_max - v_min);
|
|
}
|
|
|
|
diff_r = (((v_max - rgb[0])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
|
diff_g = (((v_max - rgb[1])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
|
diff_b = (((v_max - rgb[2])*(1.0/6)) + (0.5*diff_max))*diff_max_r;
|
|
|
|
if (rgb[0] == v_max)
|
|
{
|
|
hsl[0] = diff_b - diff_g;
|
|
}
|
|
else
|
|
{
|
|
if (rgb[1] == v_max)
|
|
{
|
|
hsl[0] = 1.0/3 + diff_r - diff_b;
|
|
}
|
|
else
|
|
{
|
|
if (rgb[2] == v_max)
|
|
{
|
|
hsl[0] = 2.0/3 + diff_g - diff_r;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hsl[0] < 0)
|
|
hsl[0] += 1;
|
|
|
|
if (hsl[0] > 1.0)
|
|
hsl[0] -= 1;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
inline double Hue_2_RGB(double v1, double v2, double vH) //Function Hue_2_RGB
|
|
{
|
|
if (vH < 0)
|
|
vH += 1;
|
|
if (vH > 1)
|
|
vH -= 1;
|
|
|
|
if ((6*vH) < 1)
|
|
return v1 + (v2 - v1)*6*vH;
|
|
|
|
if ((2*vH) < 1)
|
|
return v2;
|
|
|
|
if ((3*vH) < 2)
|
|
return v1 + (v2 - v1)*((2.0/3) - vH)*6;
|
|
|
|
return v1;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void hsl2rgb(color_vector_t *pHSL, color_vector_t *pRGB, int len)
|
|
{
|
|
int i, j;
|
|
double h, t1, t2, t3, *rgb, *hsl;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
rgb = (double*)&pRGB[i];
|
|
hsl = (double*)&pHSL[i];
|
|
|
|
if (hsl[1] == 0)
|
|
{
|
|
rgb[0] = hsl[2];
|
|
rgb[1] = hsl[2];
|
|
rgb[2] = hsl[2];
|
|
|
|
continue;
|
|
}
|
|
|
|
if(hsl[2] < 0.5)
|
|
{
|
|
t2 = hsl[2]*(1 + hsl[1]);
|
|
}
|
|
else
|
|
{
|
|
t2 = (hsl[2] + hsl[1]) - hsl[2]*hsl[1];
|
|
}
|
|
|
|
t1 = 2*hsl[2] - t2;
|
|
|
|
rgb[0] = Hue_2_RGB(t1, t2, hsl[0] + 1.0/3);
|
|
rgb[1] = Hue_2_RGB(t1, t2, hsl[0]);
|
|
rgb[2] = Hue_2_RGB(t1, t2, hsl[0] - 1.0/3);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void rgb2xyz(double **ppRGB, double **ppXYZ, int len)
|
|
{
|
|
int i, j;
|
|
double rgb[3];
|
|
double *pRGB, *pXYZ;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
pRGB = ((double*)ppRGB[i]);
|
|
pXYZ = ((double*)ppXYZ[i]);
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
if (pRGB[j] > 0.04045)
|
|
{
|
|
rgb[j] = pow((pRGB[j]+0.055)/1.055,2.4);
|
|
}
|
|
else
|
|
{
|
|
rgb[j] = 1.0/12.92 * pRGB[j];
|
|
}
|
|
|
|
rgb[j] *= K_XYZ;
|
|
|
|
}
|
|
|
|
// Observer = 2°, Illuminant = D65
|
|
pXYZ[0] = 0.412453*rgb[0] + 0.357580*rgb[1] + 0.180423*rgb[2];
|
|
pXYZ[1] = 0.212671*rgb[0] + 0.715160*rgb[1] + 0.072169*rgb[2];
|
|
pXYZ[2] = 0.019334*rgb[0] + 0.119193*rgb[1] + 0.950227*rgb[2];
|
|
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void xyz2rgb(double **ppXYZ, double **ppRGB, int len)
|
|
{
|
|
int i, j;
|
|
double xyz[3];
|
|
double *pRGB, *pXYZ;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
pRGB = ((double*)ppRGB[i]);
|
|
pXYZ = ((double*)ppXYZ[i]);
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
xyz[j] = 1.0/K_XYZ * pXYZ[j];
|
|
}
|
|
|
|
// Observer = 2°, Illuminant = D65
|
|
pRGB[0] = 3.240479*xyz[0] - 1.537150*xyz[1] - 0.498535*xyz[2];
|
|
pRGB[1] = -0.969256*xyz[0] + 1.875992*xyz[1] + 0.041556*xyz[2];
|
|
pRGB[2] = 0.055648*xyz[0] - 0.204043*xyz[1] + 1.057311*xyz[2];
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
if (pRGB[j] > 0.0031308)
|
|
{
|
|
pRGB[j] = 1.055 * pow(pRGB[j],1.0/2.4) - 0.055;
|
|
}
|
|
else
|
|
{
|
|
pRGB[j] = 12.92 * pRGB[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void xyz2lab(double **ppXYZ, double **ppLAB, double *pRef, int len)
|
|
{
|
|
int i, j;
|
|
double xyz[3] = {0};
|
|
double *pLAB, *pXYZ;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
pXYZ = ((double*)ppXYZ[i]);
|
|
pLAB = ((double*)ppLAB[i]);
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
xyz[j] = pXYZ[j] / pRef[j];
|
|
}
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
if (xyz[j] > 0.008856)
|
|
{
|
|
xyz[j] = pow(xyz[j],1.0/3.0);
|
|
}
|
|
else
|
|
{
|
|
xyz[j] = 7.787*xyz[j] + 16.0/116.0;
|
|
}
|
|
|
|
}
|
|
|
|
pLAB[0] = 116.0*xyz[1] - 16;
|
|
pLAB[1] = 500.0*(xyz[0] - xyz[1]);
|
|
pLAB[2] = 200.0*(xyz[1] - xyz[2]);
|
|
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void lab2xyz(double **ppLAB, double **ppXYZ, double *pRef, int len)
|
|
{
|
|
int i, j;
|
|
double xyz[3], xyz3;
|
|
double *pLAB, *pXYZ;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
pXYZ = ((double*)ppXYZ[i]);
|
|
pLAB = ((double*)ppLAB[i]);
|
|
|
|
xyz[1] = 1.0/116.0*(pLAB[0] + 16);
|
|
xyz[0] = 1.0/500.0*pLAB[1] + xyz[1];
|
|
xyz[2] = xyz[1] - 1.0/200.0*pLAB[2];
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
xyz3 = pow(xyz[j],3.0);
|
|
if (xyz3 > 0.008856)
|
|
{
|
|
xyz[j] = xyz3;
|
|
}
|
|
else
|
|
{
|
|
xyz[j] = 1.0/7.787*(xyz[j] - 16.0/116);
|
|
}
|
|
}
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
pXYZ[j] = xyz[j] *pRef[j];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
void tristimulus(double *pRef, unsigned illuminant_type, unsigned observer_type)
|
|
{
|
|
double ref[3] = {K_XYZ*0.95047, K_XYZ*1.0, K_XYZ*1.08883};
|
|
|
|
if(observer_type == OBS_TYPE_2DEG)
|
|
{
|
|
|
|
switch (illuminant_type)
|
|
{
|
|
case ILLU_TYPE_A:
|
|
case ILLU_TYPE_INCANDESCENT:
|
|
pRef[0] = K_XYZ*1.09850;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.35585;
|
|
break;
|
|
|
|
case ILLU_TYPE_C:
|
|
pRef[0] = K_XYZ*0.98074;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.18232;
|
|
break;
|
|
|
|
case ILLU_TYPE_D50:
|
|
pRef[0] = K_XYZ*0.96422;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.82521;
|
|
break;
|
|
|
|
case ILLU_TYPE_D55:
|
|
pRef[0] = K_XYZ*0.95682;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.92149;
|
|
break;
|
|
|
|
case ILLU_TYPE_D65:
|
|
case ILLU_TYPE_DAYLIGHT:
|
|
pRef[0] = K_XYZ*0.95047;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.08883;
|
|
break;
|
|
|
|
case ILLU_TYPE_D75:
|
|
pRef[0] = K_XYZ*0.94972;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.22638;
|
|
break;
|
|
|
|
case ILLU_TYPE_F2:
|
|
case ILLU_TYPE_FLUORESCENT:
|
|
pRef[0] = K_XYZ*0.99187;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.67395;
|
|
break;
|
|
|
|
case ILLU_TYPE_F7:
|
|
pRef[0] = K_XYZ*0.95044;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.08755;
|
|
break;
|
|
|
|
case ILLU_TYPE_F11:
|
|
pRef[0] = K_XYZ*1.00966;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.64370;
|
|
break;
|
|
|
|
default:
|
|
memcpy(pRef, ref, 3*sizeof(double));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(observer_type == OBS_TYPE_10DEG)
|
|
{
|
|
|
|
switch (illuminant_type)
|
|
{
|
|
case ILLU_TYPE_A:
|
|
case ILLU_TYPE_INCANDESCENT:
|
|
pRef[0] = K_XYZ*1.11144;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.35200;
|
|
break;
|
|
|
|
case ILLU_TYPE_C:
|
|
pRef[0] = K_XYZ*0.97285;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.16145;
|
|
break;
|
|
|
|
case ILLU_TYPE_D50:
|
|
pRef[0] = K_XYZ*0.96720;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.81427;
|
|
break;
|
|
|
|
case ILLU_TYPE_D55:
|
|
pRef[0] = K_XYZ*0.95799;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.90926;
|
|
break;
|
|
|
|
case ILLU_TYPE_D65:
|
|
case ILLU_TYPE_DAYLIGHT:
|
|
pRef[0] = K_XYZ*0.94811;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.07304;
|
|
break;
|
|
|
|
case ILLU_TYPE_D75:
|
|
pRef[0] = K_XYZ*0.94416;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.20641;
|
|
break;
|
|
|
|
case ILLU_TYPE_F2:
|
|
case ILLU_TYPE_FLUORESCENT:
|
|
pRef[0] = K_XYZ*1.03280;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.69026;
|
|
break;
|
|
|
|
case ILLU_TYPE_F7:
|
|
pRef[0] = K_XYZ*0.95792;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*1.07687;
|
|
break;
|
|
|
|
case ILLU_TYPE_F11:
|
|
pRef[0] = K_XYZ*1.03866;
|
|
pRef[1] = K_XYZ*1.0;
|
|
pRef[2] = K_XYZ*0.65627;
|
|
break;
|
|
|
|
default:
|
|
memcpy(pRef, ref, 3*sizeof(double));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void rgb2rgb(double **ppSrc, double **ppDst, int len)
|
|
{
|
|
int i, j;
|
|
double *pSrc, *pDst;
|
|
|
|
for (i=0; i < len; i++)
|
|
{
|
|
pSrc = ((double*)ppSrc[i]);
|
|
pDst = ((double*)ppDst[i]);
|
|
|
|
for (j=0; j < 3; j++)
|
|
{
|
|
pDst[j] = pSrc[j];
|
|
}
|
|
|
|
}
|
|
}
|
|
|