Files
jens 05da8712f6 Initial import
git-svn-id: http://moon:8086/svn/software/trunk/libsrc/_to_be_added@1 b431acfa-c32f-4a4a-93f1-934dc6c82436
2014-07-19 07:44:42 +00:00

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];
}
}
}