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