1
/* $Xorg: LuvMxL.c,v 1.3 2000/08/17 19:44:45 cpqbld Exp $ */
4
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
7
* This file is a component of an X Window System-specific implementation
8
* of XCMS based on the TekColor Color Management System. Permission is
9
* hereby granted to use, copy, modify, sell, and otherwise distribute this
10
* software and its documentation for any purpose and without fee, provided
11
* that this copyright, permission, and disclaimer notice is reproduced in
12
* all copies of this software and in supporting documentation. TekColor
13
* is a trademark of Tektronix, Inc.
15
* Tektronix makes no representation about the suitability of this software
16
* for any purpose. It is provided "as is" and with all faults.
18
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
19
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
21
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22
* RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
23
* CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
24
* CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
30
* Source for the XcmsCIELuvQueryMaxL() gamut boundary
34
/* $XFree86: xc/lib/X11/LuvMxL.c,v 1.3 2001/01/17 19:41:40 dawes Exp $ */
43
#define MAXBISECTCOUNT 100
44
#define EPS (XcmsFloat)0.001
45
#define START_L_STAR (XcmsFloat)40.0
50
extern Status _XcmsCIELuvQueryMaxLCRGB();
53
extern Status _XcmsConvertColorsWithWhitePt();
56
/************************************************************************
60
************************************************************************/
64
* XcmsCIELuvQueryMaxL - Compute max Lstar for a hue and chroma
69
XcmsCIELuvQueryMaxL(ccc, hue_angle, chroma, pColor_return)
71
XcmsFloat hue_angle; /* hue angle in degrees */
73
XcmsColor *pColor_return;
76
* Return the maximum Lstar for a specified hue_angle and chroma.
79
* This routine assumes that the white point associated with
80
* the color specification is the Screen White Point. The
81
* Screen White Point will also be associated with the
82
* returned color specification.
85
* XcmsFailure - Failure
86
* XcmsSuccess - Succeeded with no modifications
91
XcmsColor max_lc, tmp, prev;
92
XcmsFloat max_chroma, tmp_chroma;
93
XcmsFloat hue, nT, nChroma, lastChroma, prevChroma;
96
int nCount, nMaxCount;
101
if (ccc == NULL || pColor_return == NULL) {
105
/* setup the CCC to use for the conversions. */
106
memcpy ((char *) &myCCC, (char *) ccc, sizeof(XcmsCCCRec));
107
myCCC.clientWhitePt.format = XcmsUndefinedFormat;
108
myCCC.gamutCompProc = (XcmsCompressionProc) NULL;
110
while (hue_angle < 0.0) {
113
while (hue_angle >= 360.0) {
117
hue = radians(hue_angle);
118
tmp.spec.CIELuv.L_star = START_L_STAR;
119
tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, chroma);
120
tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, chroma);
121
tmp.pixel = pColor_return->pixel;
122
tmp.format = XcmsCIELuvFormat;
124
/* Step 1: Obtain the maximum L_star and chroma for this hue. */
125
if (_XcmsCIELuvQueryMaxLCRGB(&myCCC, hue, &max_lc, &rgb_saved)
130
max_chroma = XCMS_CIELUV_PMETRIC_CHROMA(max_lc.spec.CIELuv.u_star,
131
max_lc.spec.CIELuv.v_star);
133
if (max_chroma <= chroma) {
135
* If the chroma is greater than the chroma for the
136
* maximum L/chroma point then the L_star is the
137
* the L_star for the maximum L_star/chroma point.
138
* This is an error but I return the best approximation I can.
139
* Thus the inconsistency.
141
memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor));
146
* If the chroma is equal to the chroma for the
147
* maximum L_star/chroma point then the L_star is the
148
* the L_star for the maximum L* and chroma point.
150
/* if (max_chroma == chroma) {
151
* memcpy ((char *) pColor_return, (char *) &max_lc, sizeof (XcmsColor));
152
* return(XcmsSuccess);
156
/* must do a bisection here to compute the maximum L* */
157
/* save the structure input so that any elements that */
158
/* are not touched are recopied later in the routine. */
160
tmp_chroma = max_chroma;
162
nMaxCount = MAXBISECTCOUNT;
165
for (nCount = 0; nCount < nMaxCount; nCount++) {
166
prevChroma = lastChroma;
167
lastChroma = tmp_chroma;
168
nT = (1.0 - (nChroma / max_chroma)) * rFactor;
169
memcpy ((char *)&prev, (char *)&tmp, sizeof(XcmsColor));
170
tmp.spec.RGBi.red = rgb_saved.red * (1.0 - nT) + nT;
171
tmp.spec.RGBi.green = rgb_saved.green * (1.0 - nT) + nT;
172
tmp.spec.RGBi.blue = rgb_saved.blue * (1.0 - nT) + nT;
173
tmp.format = XcmsRGBiFormat;
175
/* convert from RGB to CIELuv */
176
if (_XcmsConvertColorsWithWhitePt(&myCCC, &tmp,
177
ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat,
178
(Bool *) NULL) == XcmsFailure) {
182
/* Now check the return against what is expected */
183
tmp_chroma = XCMS_CIELUV_PMETRIC_CHROMA(tmp.spec.CIELuv.u_star,
184
tmp.spec.CIELuv.v_star);
185
if (tmp_chroma <= chroma + EPS && tmp_chroma >= chroma - EPS) {
187
memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor));
190
nChroma += chroma - tmp_chroma;
191
if (nChroma > max_chroma) {
192
nChroma = max_chroma;
193
rFactor *= 0.5; /* selective relaxation employed */
194
} else if (nChroma < 0.0) {
195
if (XCMS_FABS(lastChroma - chroma) <
196
XCMS_FABS(tmp_chroma - chroma)) {
197
memcpy ((char *)pColor_return, (char *)&prev,
200
memcpy ((char *)pColor_return, (char *)&tmp,
204
} else if (tmp_chroma <= prevChroma + EPS &&
205
tmp_chroma >= prevChroma - EPS) {
206
rFactor *= 0.5; /* selective relaxation employed */
210
if (nCount >= nMaxCount) {
211
if (XCMS_FABS(lastChroma - chroma) <
212
XCMS_FABS(tmp_chroma - chroma)) {
213
memcpy ((char *)pColor_return, (char *)&prev,
216
memcpy ((char *)pColor_return, (char *)&tmp,
220
memcpy ((char *) pColor_return, (char *) &tmp, sizeof (XcmsColor));