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