Initialize Tizen 2.3
[framework/uifw/xorg/lib/libx11.git] / src / xcms / LabMxLC.c
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  *
26  *
27  *      NAME
28  *              CIELabMxVC.c
29  *
30  *      DESCRIPTION
31  *              Source for the XcmsCIELabQueryMaxLC() gamut boundary
32  *              querying routine.
33  *
34  *      DOCUMENTATION
35  *              "TekColor Color Management System, System Implementor's Manual"
36  *              and
37  *              Fred W. Billmeyer & Max Saltzman, "Principles of Color
38  *              Technology", John Wily & Sons, Inc, 1981.
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44 #include "Xlibint.h"
45 #include "Xcmsint.h"
46 #include "Cv.h"
47
48 /*
49  *      DEFINES
50  */
51 #define MIN(x,y)        ((x) > (y) ? (y) : (x))
52 #define MIN3(x,y,z)     ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x))
53 #define MAX(x,y)        ((x) > (y) ? (x) : (y))
54 #define MAX3(x,y,z)     ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z))))
55 #define START_LSTAR     (XcmsFloat)40.0
56 #define START_CHROMA    (XcmsFloat)3.6
57
58 \f
59 /************************************************************************
60  *                                                                      *
61  *                       API PRIVATE ROUTINES                           *
62  *                                                                      *
63  ************************************************************************/
64
65 /*
66  *      NAME
67  *              _XcmsCIELabQueryMaxLCRGB - Compute maximum L* and chroma.
68  *
69  *      SYNOPSIS
70  */
71 Status
72 _XcmsCIELabQueryMaxLCRGB(
73     XcmsCCC     ccc,
74     XcmsFloat   hue,                /* hue in radians */
75     XcmsColor   *pColor_return,
76     XcmsRGBi    *pRGB_return)
77 /*
78  *      DESCRIPTION
79  *              Return the maximum psychometric chroma for a specified
80  *              hue, and the corresponding L*.  This is computed
81  *              by a binary search of all possible chromas.  An assumption
82  *              is made that there are no local maxima.  Use the unrounded
83  *              Max psychometric chroma because the difference check can be
84  *              small.
85  *
86  *              NOTE:  No local CCC is used because this is a private
87  *                     routine and all routines that call it are expected
88  *                     to behave properly, i.e. send a local CCC with
89  *                     no white adjust function and no gamut compression
90  *                     function.
91  *
92  *              This routine only accepts hue in radians as input and outputs
93  *              Lab and RGBi.
94  *
95  *      RETURNS
96  *              XcmsFailure - Failure
97  *              XcmsSuccess - Succeeded
98  *
99  */
100 {
101     XcmsFloat nSmall, nLarge;
102     XcmsColor tmp;
103
104     tmp.format = XcmsCIELabFormat;
105     /*  Use some unreachable color on the given hue */
106     tmp.spec.CIELab.L_star = START_LSTAR;
107     tmp.spec.CIELab.a_star = XCMS_CIEASTAROFHUE(hue, START_CHROMA);
108     tmp.spec.CIELab.b_star = XCMS_CIEBSTAROFHUE(hue, START_CHROMA);
109     /*
110      * Convert from Lab to RGB
111      *
112      * Note that the CIEXYZ to RGBi conversion routine must stuff the
113      * out of bounds RGBi values in tmp when the ccc->gamutCompProc
114      * is NULL.
115      */
116     if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp, ScreenWhitePointOfCCC(ccc),
117                                (unsigned int)1, XcmsRGBiFormat, (Bool *) NULL)
118             == XcmsFailure) && tmp.format != XcmsRGBiFormat) {
119         return (XcmsFailure);
120     }
121
122     /* Now pick the smallest RGB */
123     nSmall = MIN3(tmp.spec.RGBi.red,
124                   tmp.spec.RGBi.green,
125                   tmp.spec.RGBi.blue);
126     /* Make the smallest RGB equal to zero */
127     tmp.spec.RGBi.red   -= nSmall;
128     tmp.spec.RGBi.green -= nSmall;
129     tmp.spec.RGBi.blue  -= nSmall;
130
131     /* Now pick the largest RGB */
132     nLarge = MAX3(tmp.spec.RGBi.red,
133                   tmp.spec.RGBi.green,
134                   tmp.spec.RGBi.blue);
135     /* Scale the RGB values based on the largest one */
136     tmp.spec.RGBi.red   /= nLarge;
137     tmp.spec.RGBi.green /= nLarge;
138     tmp.spec.RGBi.blue  /= nLarge;
139     tmp.format = XcmsRGBiFormat;
140
141     /* If the calling routine wants RGB value give them the ones used. */
142     if (pRGB_return) {
143         pRGB_return->red   = tmp.spec.RGBi.red;
144         pRGB_return->green = tmp.spec.RGBi.green;
145         pRGB_return->blue  = tmp.spec.RGBi.blue;
146     }
147
148     /* Convert from RGBi to Lab */
149     if (_XcmsConvertColorsWithWhitePt(ccc, &tmp,
150                ScreenWhitePointOfCCC(ccc), 1, XcmsCIELabFormat, (Bool *) NULL)
151             == XcmsFailure) {
152         return (XcmsFailure);
153     }
154
155     memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor));
156     return (XcmsSuccess);
157 }
158
159 \f
160 /************************************************************************
161  *                                                                      *
162  *                       PUBLIC ROUTINES                                *
163  *                                                                      *
164  ************************************************************************/
165
166 /*
167  *      NAME
168  *              XcmsCIELabQueryMaxLC - Compute maximum L* and chroma.
169  *
170  *      SYNOPSIS
171  */
172 Status
173 XcmsCIELabQueryMaxLC (
174     XcmsCCC ccc,
175     XcmsFloat hue_angle,            /* hue_angle in degrees */
176     XcmsColor *pColor_return)
177
178 /*
179  *      DESCRIPTION
180  *              Return the point of maximum chroma for the specified
181  *              hue_angle.
182  *
183  *      ASSUMPTIONS
184  *              This routine assumes that the white point associated with
185  *              the color specification is the Screen White Point.  The
186  *              Screen White Point will also be associated with the
187  *              returned color specification.
188  *
189  *      RETURNS
190  *              XcmsFailure - Failure
191  *              XcmsSuccess - Succeeded
192  *
193  */
194 {
195     XcmsCCCRec myCCC;
196
197     /*
198      * Check Arguments
199      */
200     if (ccc == NULL || pColor_return == NULL) {
201         return(XcmsFailure);
202     }
203
204     /* Use my own CCC */
205     memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
206     myCCC.clientWhitePt.format = XcmsUndefinedFormat;
207     myCCC.gamutCompProc = (XcmsCompressionProc)NULL;
208
209     while (hue_angle < 0.0) {
210         hue_angle += 360.0;
211     }
212     while (hue_angle >= 360.0) {
213         hue_angle -= 360.0;
214     }
215
216     return(_XcmsCIELabQueryMaxLCRGB (&myCCC, radians(hue_angle), pColor_return,
217             (XcmsRGBi *)NULL));
218 }