1 
2 /*
3  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
4  * 	All Rights Reserved
5  *
6  * This file is a component of an X Window System-specific implementation
7  * of XCMS based on the TekColor Color Management System.  Permission is
8  * hereby granted to use, copy, modify, sell, and otherwise distribute this
9  * software and its documentation for any purpose and without fee, provided
10  * that this copyright, permission, and disclaimer notice is reproduced in
11  * all copies of this software and in supporting documentation.  TekColor
12  * is a trademark of Tektronix, Inc.
13  *
14  * Tektronix makes no representation about the suitability of this software
15  * for any purpose.  It is provided "as is" and with all faults.
16  *
17  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
18  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
20  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
22  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
24  *
25  *	NAME
26  *		CIELabGcL.c
27  *
28  *	DESCRIPTION
29  *		Source for XcmsCIELabClipL() gamut compression routine.
30  *
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 #include "Xlibint.h"
37 #include "Xcmsint.h"
38 #include "Cv.h"
39 
40 
41 /************************************************************************
42  *									*
43  *			 PUBLIC ROUTINES				*
44  *									*
45  ************************************************************************/
46 
47 /*
48  *	NAME
49  *		XcmsCIELabClipL - Return the closest L*
50  *
51  *	SYNOPSIS
52  */
53 /* ARGSUSED */
54 Status
XcmsCIELabClipL(XcmsCCC ccc,XcmsColor * pColors_in_out,unsigned int nColors,unsigned int i,Bool * pCompressed)55 XcmsCIELabClipL (
56     XcmsCCC ccc,
57     XcmsColor *pColors_in_out,
58     unsigned int nColors,
59     unsigned int i,
60     Bool *pCompressed)
61 /*
62  *	DESCRIPTION
63  *		Return the closest L* for a specific hue and chroma.
64  *		This routine takes any color as input and outputs
65  *		a CIE XYZ color.
66  *
67  *		Since this routine works with the L* within
68  *		pColor_in_out intermediate results may be returned
69  *		even though it may be invalid.
70  *
71  *	RETURNS
72  *		XcmsFailure - Failure
73  *              XcmsSuccess - Succeeded
74  *
75  */
76 {
77     XcmsCCCRec	myCCC;
78     XcmsColor	*pColor;
79     XcmsColor   Lab_max;
80     XcmsFloat	hue, chroma, maxChroma;
81     Status retval;
82 
83     /* Use my own CCC */
84     memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
85     myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* Inherit Screen WP */
86     myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression */
87 
88     /*
89      * Color specification passed as input can be assumed to:
90      *	1. Be in XcmsCIEXYZFormat
91      *	2. Already be white point adjusted for the Screen White Point.
92      *	    This means that the white point now associated with this
93      *	    color spec is the Screen White Point (even if the
94      *	    ccc->clientWhitePt differs).
95      */
96 
97     pColor = pColors_in_out + i;
98 
99     if (ccc->visual->class < StaticColor) {
100 	/*
101 	 * GRAY !
102 	 */
103 	return(XcmsFailure);
104     } else {
105 	/* Convert from CIEXYZ to CIE L*u*v* format */
106 	if (_XcmsDIConvertColors(&myCCC, pColor,
107 		ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat)
108 		== XcmsFailure) {
109 	    return(XcmsFailure);
110 	}
111 
112 	hue = XCMS_CIELAB_PMETRIC_HUE(pColor->spec.CIELab.a_star,
113 				      pColor->spec.CIELab.b_star);
114 	chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star,
115 					    pColor->spec.CIELab.b_star);
116 	/* Step 1: compute the maximum L* and chroma for this hue. */
117 	/*         This copy may be overkill but it preserves the pixel etc. */
118 	memcpy((char *)&Lab_max, (char *)pColor, sizeof(XcmsColor));
119 	if (_XcmsCIELabQueryMaxLCRGB (&myCCC, hue, &Lab_max,
120 		(XcmsRGBi *)NULL) == XcmsFailure) {
121 	    return (XcmsFailure);
122 	}
123 	maxChroma = XCMS_CIELAB_PMETRIC_CHROMA(Lab_max.spec.CIELab.a_star,
124 					       Lab_max.spec.CIELab.b_star);
125 
126 	/* Now check and return the appropriate L* */
127 	if (chroma == maxChroma) {
128 	    /* When the chroma input is equal to the maximum chroma */
129 	    /* merely return the L* for that chroma. */
130 	    memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor));
131 	    retval = _XcmsDIConvertColors(&myCCC, pColor,
132 		    ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
133 	} else if (chroma > maxChroma) {
134 	    /* When the chroma input is greater than the maximum chroma */
135 	    /* merely return the L* and chroma for the given hue. */
136 	    memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor));
137 	    return (XcmsFailure);
138 	} else if (pColor->spec.CIELab.L_star < Lab_max.spec.CIELab.L_star) {
139 	    /* Find the minimum lightness for the given chroma. */
140 	    if (pColor->format != XcmsCIELabFormat) {
141 		if (_XcmsDIConvertColors(ccc, pColor,
142 			ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat)
143 			== XcmsFailure) {
144 		    return(XcmsFailure);
145 		}
146 	    }
147 	    if (XcmsCIELabQueryMinL(&myCCC, degrees(hue), chroma, pColor)
148 		== XcmsFailure) {
149 		    return (XcmsFailure);
150 	    }
151 	    retval = _XcmsDIConvertColors(&myCCC, pColor,
152 		           ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
153 	} else {
154 	    /* Find the maximum lightness for the given chroma. */
155 	    if (pColor->format != XcmsCIELabFormat) {
156 		if (_XcmsDIConvertColors(ccc, pColor,
157 			      ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat)
158 			== XcmsFailure) {
159 		    return(XcmsFailure);
160 		}
161 	    }
162 	    if (XcmsCIELabQueryMaxL(&myCCC, degrees(hue), chroma, pColor)
163 		== XcmsFailure) {
164 		    return (XcmsFailure);
165 	    }
166 	    retval = _XcmsDIConvertColors(&myCCC, pColor,
167 		           ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
168 	}
169 	if (retval != XcmsFailure && pCompressed != NULL) {
170 	    *(pCompressed + i) = True;
171 	}
172 	return(retval);
173     }
174 }
175