LuvGcL.c revision 1ab64890
1/* $Xorg: LuvGcL.c,v 1.3 2000/08/17 19:44:41 cpqbld Exp $ */
2
3/*
4 * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
5 * 	All Rights Reserved
6 *
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.
14 *
15 * Tektronix makes no representation about the suitability of this software
16 * for any purpose.  It is provided "as is" and with all faults.
17 *
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.
25 *
26 *	NAME
27 *		CIELuvGcL.c
28 *
29 *	DESCRIPTION
30 *		Source for XcmsCIELuvClipL() gamut compression routine.
31 *
32 */
33/* $XFree86: xc/lib/X11/LuvGcL.c,v 1.3 2001/01/17 19:41:39 dawes Exp $ */
34
35#ifdef HAVE_CONFIG_H
36#include <config.h>
37#endif
38#include "Xlibint.h"
39#include "Xcmsint.h"
40#include "Cv.h"
41
42
43/************************************************************************
44 *									*
45 *			 PUBLIC ROUTINES				*
46 *									*
47 ************************************************************************/
48
49/*
50 *	NAME
51 *		XcmsCIELuvClipL - Return the closest L*
52 *
53 *	SYNOPSIS
54 */
55/* ARGSUSED */
56Status
57XcmsCIELuvClipL (
58    XcmsCCC ccc,
59    XcmsColor *pColors_in_out,
60    unsigned int nColors,
61    unsigned int i,
62    Bool *pCompressed)
63/*
64 *	DESCRIPTION
65 *		Return the closest L* for a specific hue and chroma.
66 *		This routine takes any color as input and outputs
67 *		a CIE XYZ color.
68 *
69 *		Since this routine works with the L* within
70 *		pColor_in_out intermediate results may be returned
71 *		even though it may be invalid.
72 *
73 *	RETURNS
74 *		XcmsFailure - Failure
75 *              XcmsSuccess - Succeeded
76 *
77 */
78{
79    XcmsCCCRec	myCCC;
80    XcmsColor	*pColor;
81    XcmsColor   Luv_max;
82    XcmsFloat	hue, chroma, maxChroma;
83    Status retval;
84
85    /* Use my own CCC */
86    memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
87    myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* Inherit Screen WP */
88    myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression */
89
90    /*
91     * Color specification passed as input can be assumed to:
92     *	1. Be in XcmsCIEXYZFormat
93     *	2. Already be white point adjusted for the Screen White Point.
94     *	    This means that the white point now associated with this
95     *	    color spec is the Screen White Point (even if the
96     *	    ccc->clientWhitePt differs).
97     */
98
99    pColor = pColors_in_out + i;
100
101    if (ccc->visual->class < StaticColor) {
102	/*
103	 * GRAY !
104	 */
105	return(XcmsFailure);
106    } else {
107	/* Convert from CIEXYZ to CIE L*u*v* format */
108	if (_XcmsDIConvertColors(&myCCC, pColor,
109		ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELuvFormat)
110		== XcmsFailure) {
111	    return(XcmsFailure);
112	}
113
114	hue = XCMS_CIELUV_PMETRIC_HUE(pColor->spec.CIELuv.u_star,
115				      pColor->spec.CIELuv.v_star);
116	chroma = XCMS_CIELUV_PMETRIC_CHROMA(pColor->spec.CIELuv.u_star,
117					    pColor->spec.CIELuv.v_star);
118	/* Step 1: compute the maximum L* and chroma for this hue. */
119	/*         This copy may be overkill but it preserves the pixel etc. */
120	memcpy((char *)&Luv_max, (char *)pColor, sizeof(XcmsColor));
121	if (_XcmsCIELuvQueryMaxLCRGB (&myCCC, hue, &Luv_max,
122		(XcmsRGBi *)NULL) == XcmsFailure) {
123	    return (XcmsFailure);
124	}
125	maxChroma = XCMS_CIELUV_PMETRIC_CHROMA(Luv_max.spec.CIELuv.u_star,
126					       Luv_max.spec.CIELuv.v_star);
127
128	/* Now check and return the appropriate L* */
129	if (chroma == maxChroma) {
130	    /* When the chroma input is equal to the maximum chroma */
131	    /* merely return the L* for that chroma. */
132	    memcpy((char *)pColor, (char *)&Luv_max, sizeof(XcmsColor));
133	    retval = _XcmsDIConvertColors(&myCCC, pColor,
134		    ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
135	} else if (chroma > maxChroma) {
136	    /* When the chroma input is greater than the maximum chroma */
137	    /* merely return the L* and chroma for the given hue. */
138	    memcpy((char *)pColor, (char *)&Luv_max, sizeof(XcmsColor));
139	    return (XcmsFailure);
140	} else if (pColor->spec.CIELuv.L_star < Luv_max.spec.CIELuv.L_star) {
141	    /* Find the minimum lightness for the given chroma. */
142	    if (pColor->format != XcmsCIELuvFormat) {
143		if (_XcmsDIConvertColors(ccc, pColor,
144			ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat)
145			== XcmsFailure) {
146		    return(XcmsFailure);
147		}
148	    }
149	    if (XcmsCIELuvQueryMinL(&myCCC, degrees(hue), chroma, pColor)
150		== XcmsFailure) {
151		    return (XcmsFailure);
152	    }
153	    retval = _XcmsDIConvertColors(&myCCC, pColor,
154		           ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
155	} else {
156	    /* Find the maximum lightness for the given chroma. */
157	    if (pColor->format != XcmsCIELuvFormat) {
158		if (_XcmsDIConvertColors(ccc, pColor,
159			      ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat)
160			== XcmsFailure) {
161		    return(XcmsFailure);
162		}
163	    }
164	    if (XcmsCIELuvQueryMaxL(&myCCC, degrees(hue), chroma, pColor)
165		== XcmsFailure) {
166		    return (XcmsFailure);
167	    }
168	    retval = _XcmsDIConvertColors(&myCCC, pColor,
169		           ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
170	}
171	if (retval != XcmsFailure && pCompressed != NULL) {
172	    *(pCompressed + i) = True;
173	}
174	return(retval);
175    }
176}
177