LabGcL.c revision 61b2299d
11.4Sis/* $Xorg: LabGcL.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */
21.1Sis
31.1Sis/*
41.1Sis * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
51.1Sis * 	All Rights Reserved
61.1Sis *
71.1Sis * This file is a component of an X Window System-specific implementation
81.1Sis * of XCMS based on the TekColor Color Management System.  Permission is
91.1Sis * hereby granted to use, copy, modify, sell, and otherwise distribute this
101.1Sis * software and its documentation for any purpose and without fee, provided
111.1Sis * that this copyright, permission, and disclaimer notice is reproduced in
121.1Sis * all copies of this software and in supporting documentation.  TekColor
131.1Sis * is a trademark of Tektronix, Inc.
141.1Sis *
151.1Sis * Tektronix makes no representation about the suitability of this software
161.1Sis * for any purpose.  It is provided "as is" and with all faults.
171.1Sis *
181.1Sis * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
191.1Sis * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
201.1Sis * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
211.1Sis * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
221.1Sis * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
231.1Sis * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
241.1Sis * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
251.1Sis *
261.1Sis *	NAME
271.1Sis *		CIELabGcL.c
281.1Sis *
291.1Sis *	DESCRIPTION
301.1Sis *		Source for XcmsCIELabClipL() gamut compression routine.
311.1Sis *
321.1Sis */
331.1Sis/* $XFree86: xc/lib/X11/LabGcL.c,v 1.3 2001/01/17 19:41:38 dawes Exp $ */
341.1Sis
351.1Sis#ifdef HAVE_CONFIG_H
361.1Sis#include <config.h>
371.1Sis#endif
381.1Sis#include "Xlibint.h"
391.1Sis#include "Xcmsint.h"
401.1Sis#include "Cv.h"
411.1Sis
421.1Sis
431.1Sis/************************************************************************
441.1Sis *									*
451.1Sis *			 PUBLIC ROUTINES				*
461.1Sis *									*
471.1Sis ************************************************************************/
481.1Sis
491.1Sis/*
501.1Sis *	NAME
511.1Sis *		XcmsCIELabClipL - Return the closest L*
521.1Sis *
531.1Sis *	SYNOPSIS
541.1Sis */
551.1Sis/* ARGSUSED */
561.1SisStatus
571.1SisXcmsCIELabClipL (
581.1Sis    XcmsCCC ccc,
591.1Sis    XcmsColor *pColors_in_out,
601.1Sis    unsigned int nColors,
611.1Sis    unsigned int i,
621.1Sis    Bool *pCompressed)
631.1Sis/*
641.1Sis *	DESCRIPTION
651.1Sis *		Return the closest L* for a specific hue and chroma.
661.1Sis *		This routine takes any color as input and outputs
671.1Sis *		a CIE XYZ color.
681.1Sis *
691.1Sis *		Since this routine works with the L* within
701.1Sis *		pColor_in_out intermediate results may be returned
711.1Sis *		even though it may be invalid.
721.1Sis *
731.1Sis *	RETURNS
741.1Sis *		XcmsFailure - Failure
751.1Sis *              XcmsSuccess - Succeeded
761.1Sis *
771.1Sis */
781.1Sis{
791.1Sis    XcmsCCCRec	myCCC;
801.1Sis    XcmsColor	*pColor;
811.1Sis    XcmsColor   Lab_max;
821.1Sis    XcmsFloat	hue, chroma, maxChroma;
831.1Sis    Status retval;
841.1Sis
851.1Sis    /* Use my own CCC */
861.1Sis    memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
871.1Sis    myCCC.clientWhitePt.format = XcmsUndefinedFormat;/* Inherit Screen WP */
881.1Sis    myCCC.gamutCompProc = (XcmsCompressionProc)NULL;/* no gamut compression */
891.1Sis
901.1Sis    /*
911.1Sis     * Color specification passed as input can be assumed to:
921.1Sis     *	1. Be in XcmsCIEXYZFormat
931.1Sis     *	2. Already be white point adjusted for the Screen White Point.
941.1Sis     *	    This means that the white point now associated with this
951.1Sis     *	    color spec is the Screen White Point (even if the
961.1Sis     *	    ccc->clientWhitePt differs).
971.1Sis     */
981.1Sis
991.1Sis    pColor = pColors_in_out + i;
1001.1Sis
1011.1Sis    if (ccc->visual->class < StaticColor) {
1021.1Sis	/*
1031.1Sis	 * GRAY !
1041.1Sis	 */
1051.1Sis	return(XcmsFailure);
1061.1Sis    } else {
1071.1Sis	/* Convert from CIEXYZ to CIE L*u*v* format */
1081.1Sis	if (_XcmsDIConvertColors(&myCCC, pColor,
1091.1Sis		ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIELabFormat)
1101.1Sis		== XcmsFailure) {
1111.1Sis	    return(XcmsFailure);
1121.1Sis	}
1131.1Sis
1141.1Sis	hue = XCMS_CIELAB_PMETRIC_HUE(pColor->spec.CIELab.a_star,
1151.1Sis				      pColor->spec.CIELab.b_star);
1161.1Sis	chroma = XCMS_CIELAB_PMETRIC_CHROMA(pColor->spec.CIELab.a_star,
1171.1Sis					    pColor->spec.CIELab.b_star);
1181.1Sis	/* Step 1: compute the maximum L* and chroma for this hue. */
1191.1Sis	/*         This copy may be overkill but it preserves the pixel etc. */
1201.1Sis	memcpy((char *)&Lab_max, (char *)pColor, sizeof(XcmsColor));
1211.1Sis	if (_XcmsCIELabQueryMaxLCRGB (&myCCC, hue, &Lab_max,
1221.1Sis		(XcmsRGBi *)NULL) == XcmsFailure) {
1231.1Sis	    return (XcmsFailure);
1241.1Sis	}
1251.1Sis	maxChroma = XCMS_CIELAB_PMETRIC_CHROMA(Lab_max.spec.CIELab.a_star,
1261.1Sis					       Lab_max.spec.CIELab.b_star);
1271.1Sis
1281.1Sis	/* Now check and return the appropriate L* */
1291.1Sis	if (chroma == maxChroma) {
1301.1Sis	    /* When the chroma input is equal to the maximum chroma */
1311.1Sis	    /* merely return the L* for that chroma. */
1321.1Sis	    memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor));
1331.1Sis	    retval = _XcmsDIConvertColors(&myCCC, pColor,
1341.1Sis		    ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
1351.1Sis	} else if (chroma > maxChroma) {
1361.1Sis	    /* When the chroma input is greater than the maximum chroma */
1371.1Sis	    /* merely return the L* and chroma for the given hue. */
1381.1Sis	    memcpy((char *)pColor, (char *)&Lab_max, sizeof(XcmsColor));
1391.1Sis	    return (XcmsFailure);
1401.1Sis	} else if (pColor->spec.CIELab.L_star < Lab_max.spec.CIELab.L_star) {
1411.1Sis	    /* Find the minimum lightness for the given chroma. */
1421.1Sis	    if (pColor->format != XcmsCIELabFormat) {
1431.1Sis		if (_XcmsDIConvertColors(ccc, pColor,
1441.1Sis			ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat)
1451.1Sis			== XcmsFailure) {
1461.1Sis		    return(XcmsFailure);
1471.1Sis		}
1481.1Sis	    }
1491.1Sis	    if (XcmsCIELabQueryMinL(&myCCC, degrees(hue), chroma, pColor)
1501.1Sis		== XcmsFailure) {
1511.1Sis		    return (XcmsFailure);
1521.1Sis	    }
1531.1Sis	    retval = _XcmsDIConvertColors(&myCCC, pColor,
1541.1Sis		           ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
1551.1Sis	} else {
1561.1Sis	    /* Find the maximum lightness for the given chroma. */
1571.1Sis	    if (pColor->format != XcmsCIELabFormat) {
1581.1Sis		if (_XcmsDIConvertColors(ccc, pColor,
1591.1Sis			      ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat)
1601.1Sis			== XcmsFailure) {
1611.1Sis		    return(XcmsFailure);
1621.1Sis		}
1631.1Sis	    }
1641.1Sis	    if (XcmsCIELabQueryMaxL(&myCCC, degrees(hue), chroma, pColor)
1651.1Sis		== XcmsFailure) {
1661.1Sis		    return (XcmsFailure);
1671.1Sis	    }
1681.1Sis	    retval = _XcmsDIConvertColors(&myCCC, pColor,
1691.1Sis		           ScreenWhitePointOfCCC(&myCCC), 1, XcmsCIEXYZFormat);
1701.1Sis	}
1711.1Sis	if (retval != XcmsFailure && pCompressed != NULL) {
1721.1Sis	    *(pCompressed + i) = True;
1731.1Sis	}
1741.1Sis	return(retval);
1751.1Sis    }
1761.1Sis}
1771.1Sis