#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xlibint.h"
#include "Xcmsint.h"
#include <math.h>
#include "Cv.h"
#define MAXBISECTCOUNT 100
Status
XcmsCIELabClipLab (
XcmsCCC ccc,
XcmsColor *pColors_in_out,
unsigned int nColors,
unsigned int i,
Bool *pCompressed)
{
Status retval;
XcmsCCCRec myCCC;
XcmsColor *pColor;
XcmsColor Lab_max;
XcmsFloat hue, chroma, maxChroma;
XcmsFloat Chroma, bestChroma, Lstar, maxLstar, saveLstar;
XcmsFloat bestLstar, bestastar, bestbstar;
XcmsFloat nT, saveDist, tmpDist;
XcmsRGBi rgb_max;
int nCount, nMaxCount, nI, nILast;
memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
myCCC.clientWhitePt.format = XcmsUndefinedFormat;
myCCC.gamutCompProc = (XcmsCompressionProc)NULL;
pColor = pColors_in_out + i;
if (ccc->visual->class < StaticColor) {
_XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc),
1, XcmsCIELabFormat);
_XcmsDIConvertColors(ccc, pColor, ScreenWhitePointOfCCC(ccc),
1, XcmsCIEXYZFormat);
if (pCompressed) {
*(pCompressed + i) = True;
}
return(XcmsSuccess);
}
if (_XcmsDIConvertColors(&myCCC, pColor,
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat)
== XcmsFailure) {
return(XcmsFailure);
}
saveLstar = pColor->spec.CIELab.L_star;
hue = XCMS_CIELAB_PMETRIC_HUE(pColor->spec.CIELab.a_star,
pColor->spec.CIELab.b_star);
chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star,
pColor->spec.CIELab.b_star);
memcpy((char *)&Lab_max, (char *)pColor, sizeof(XcmsColor));
if (_XcmsCIELabQueryMaxLCRGB (&myCCC, hue, &Lab_max, &rgb_max)
== XcmsFailure) {
return (XcmsFailure);
}
maxLstar = Lab_max.spec.CIELab.L_star;
if (saveLstar == maxLstar) {
memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor));
retval = _XcmsDIConvertColors(&myCCC, pColor,
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
} else {
maxChroma = XCMS_CIELAB_PMETRIC_CHROMA(Lab_max.spec.CIELab.a_star,
Lab_max.spec.CIELab.b_star);
nMaxCount = MAXBISECTCOUNT;
nI = nMaxCount / 2;
bestLstar = Lstar = pColor->spec.CIELab.L_star;
bestastar = pColor->spec.CIELab.a_star;
bestbstar = pColor->spec.CIELab.b_star;
bestChroma = Chroma = chroma;
saveDist = XCMS_SQRT(((Chroma - maxChroma) * (Chroma - maxChroma)) +
((Lstar - maxLstar) * (Lstar - maxLstar)));
for (nCount = 0; nCount < nMaxCount; nCount++) {
nT = (XcmsFloat) nI / (XcmsFloat) nMaxCount;
if (saveLstar > maxLstar) {
pColor->spec.RGBi.red = rgb_max.red * (1.0 - nT) + nT;
pColor->spec.RGBi.green = rgb_max.green * (1.0 - nT) + nT;
pColor->spec.RGBi.blue = rgb_max.blue * (1.0 - nT) + nT;
} else {
pColor->spec.RGBi.red = rgb_max.red - (rgb_max.red * nT);
pColor->spec.RGBi.green = rgb_max.green - (rgb_max.green * nT);
pColor->spec.RGBi.blue = rgb_max.blue - (rgb_max.blue * nT);
}
pColor->format = XcmsRGBiFormat;
if (_XcmsConvertColorsWithWhitePt(&myCCC, pColor,
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat,
(Bool *) NULL) == XcmsFailure) {
return (XcmsFailure);
}
chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star,
pColor->spec.CIELab.b_star);
tmpDist = XCMS_SQRT(((Chroma - chroma) * (Chroma - chroma)) +
((Lstar - pColor->spec.CIELab.L_star) *
(Lstar - pColor->spec.CIELab.L_star)));
nILast = nI;
if (tmpDist > saveDist) {
nI /= 2;
} else {
nI = (nMaxCount + nI) / 2;
saveDist = tmpDist;
bestLstar = pColor->spec.CIELab.L_star;
bestastar = pColor->spec.CIELab.a_star;
bestbstar = pColor->spec.CIELab.b_star;
bestChroma = chroma;
}
if (nI == nILast || nI == 0) {
break;
}
}
if (bestChroma >= maxChroma) {
pColor->spec.CIELab.L_star = maxLstar;
pColor->spec.CIELab.a_star = Lab_max.spec.CIELab.a_star;
pColor->spec.CIELab.b_star = Lab_max.spec.CIELab.b_star;
} else {
pColor->spec.CIELab.L_star = bestLstar;
pColor->spec.CIELab.a_star = bestastar;
pColor->spec.CIELab.b_star = bestbstar;
}
retval = _XcmsDIConvertColors(&myCCC, pColor,
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
if (retval != XcmsFailure && pCompressed != NULL) {
*(pCompressed + i) = True;
}
}
return(retval);
}