#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xlibint.h"
#include "Xcmsint.h"
#include <math.h>
#include "Cv.h"
#define MAXBISECTCOUNT 100
#define EPS (XcmsFloat)0.001
#define START_L_STAR (XcmsFloat)40
Status
XcmsCIELabQueryMaxL(
XcmsCCC ccc,
XcmsFloat hue_angle,
XcmsFloat chroma,
XcmsColor *pColor_return)
{
XcmsCCCRec myCCC;
XcmsColor max_lc, tmp, prev;
XcmsFloat max_chroma, tmp_chroma;
XcmsFloat hue, nT, nChroma, lastChroma, prevChroma;
XcmsFloat rFactor;
XcmsRGBi rgb_saved;
int nCount, nMaxCount;
if (ccc == NULL || pColor_return == NULL) {
return(XcmsFailure);
}
memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec));
myCCC.clientWhitePt.format = XcmsUndefinedFormat;
myCCC.gamutCompProc = (XcmsCompressionProc) NULL;
while (hue_angle < 0.0) {
hue_angle += 360.0;
}
while (hue_angle >= 360.0) {
hue_angle -= 360.0;
}
hue = radians(hue_angle);
tmp.spec.CIELab.L_star = START_L_STAR;
tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, chroma);
tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, chroma);
tmp.pixel = pColor_return->pixel;
tmp.format = XcmsCIELabFormat;
if (_XcmsCIELabQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved)
== XcmsFailure) {
return(XcmsFailure);
}
max_chroma = XCMS_CIELAB_PMETRIC_CHROMA(max_lc.spec.CIELab.a_star,
max_lc.spec.CIELab.b_star);
if (max_chroma <= chroma) {
memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor));
return(XcmsSuccess);
}
nChroma = chroma;
tmp_chroma = max_chroma;
lastChroma = -1.0;
nMaxCount = MAXBISECTCOUNT;
rFactor = 1.0;
for (nCount = 0; nCount < nMaxCount; nCount++) {
prevChroma = lastChroma;
lastChroma = tmp_chroma;
nT = (1.0 - (nChroma / max_chroma)) * rFactor;
memcpy ((char *)&prev, (char *)&tmp, sizeof(XcmsColor));
tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT;
tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT;
tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT;
tmp.format = XcmsRGBiFormat;
if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp,
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat,
(Bool *) NULL) == XcmsFailure) {
return(XcmsFailure);
}
tmp_chroma = XCMS_CIELAB_PMETRIC_CHROMA(tmp.spec.CIELab.a_star,
tmp.spec.CIELab.b_star);
if (tmp_chroma <= chroma + EPS && tmp_chroma >= chroma - EPS) {
memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor));
return(XcmsSuccess);
}
nChroma += chroma - tmp_chroma;
if (nChroma > max_chroma) {
nChroma = max_chroma;
rFactor *= 0.5;
} else if (nChroma < 0.0) {
if (XCMS_FABS(lastChroma - chroma) <
XCMS_FABS(tmp_chroma - chroma)) {
memcpy ((char *)pColor_return, (char *)&prev,
sizeof(XcmsColor));
} else {
memcpy ((char *)pColor_return, (char *)&tmp,
sizeof(XcmsColor));
}
return(XcmsSuccess);
} else if (tmp_chroma <= prevChroma + EPS &&
tmp_chroma >= prevChroma - EPS) {
rFactor *= 0.5;
}
}
if (nCount >= nMaxCount) {
if (XCMS_FABS(lastChroma - chroma) <
XCMS_FABS(tmp_chroma - chroma)) {
memcpy ((char *)pColor_return, (char *)&prev,
sizeof(XcmsColor));
} else {
memcpy ((char *)pColor_return, (char *)&tmp,
sizeof(XcmsColor));
}
}
memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor));
return(XcmsSuccess);
}