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 */
54Status
55XcmsCIELabClipL (
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