#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_CHROMA (XcmsFloat)3.6
#define TOPL (XcmsFloat)100.0
Status
XcmsCIELabQueryMaxC(
XcmsCCC ccc,
XcmsFloat hue_angle,
XcmsFloat L_star,
XcmsColor *pColor_return)
{
XcmsCCCRec myCCC;
XcmsColor tmp;
XcmsColor max_lc;
XcmsFloat n_L_star, last_L_star, prev_L_star;
XcmsFloat hue, lastaStar, lastbStar, maxDist, nT, 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 = L_star;
tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, START_CHROMA);
tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, START_CHROMA);
tmp.pixel = pColor_return->pixel;
tmp.format = XcmsCIELabFormat;
memcpy((char *)&max_lc, (char *)&tmp, sizeof(XcmsColor));
if (_XcmsCIELabQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved)
== XcmsFailure) {
return(XcmsFailure);
}
if (L_star <= max_lc.spec.CIELab.L_star) {
maxDist = max_lc.spec.CIELab.L_star;
} else {
maxDist = TOPL - max_lc.spec.CIELab.L_star;
}
n_L_star = L_star;
last_L_star = -1.0;
nMaxCount = MAXBISECTCOUNT;
rFactor = 1.0;
for (nCount = 0; nCount < nMaxCount; nCount++) {
prev_L_star = last_L_star;
last_L_star = tmp.spec.CIELab.L_star;
lastaStar = tmp.spec.CIELab.a_star;
lastbStar = tmp.spec.CIELab.b_star;
nT = (n_L_star - max_lc.spec.CIELab.L_star) / maxDist * rFactor;
if (nT > 0) {
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;
} else {
tmp.spec.RGBi.red = rgb_saved.red + (rgb_saved.red * nT);
tmp.spec.RGBi.green = rgb_saved.green + (rgb_saved.green * nT);
tmp.spec.RGBi.blue = rgb_saved.blue + (rgb_saved.blue * nT);
}
tmp.format = XcmsRGBiFormat;
if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp,
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat,
(Bool *) NULL) == XcmsFailure) {
return(XcmsFailure);
}
if (tmp.spec.CIELab.L_star <= L_star + EPS &&
tmp.spec.CIELab.L_star >= L_star - EPS) {
memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor));
return(XcmsSuccess);
}
if (nT > 0) {
n_L_star += ((TOPL - n_L_star) *
(L_star - tmp.spec.CIELab.L_star)) / (TOPL - L_star);
} else {
n_L_star *= L_star / tmp.spec.CIELuv.L_star;
}
if (tmp.spec.CIELab.L_star <= prev_L_star + EPS &&
tmp.spec.CIELab.L_star >= prev_L_star - EPS) {
rFactor *= 0.5;
}
}
if (XCMS_FABS(last_L_star - L_star) <
XCMS_FABS(tmp.spec.CIELab.L_star - L_star)) {
tmp.spec.CIELab.a_star = lastaStar;
tmp.spec.CIELab.b_star = lastbStar;
}
tmp.spec.CIELab.L_star = L_star;
memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor));
return(XcmsSuccess);
}