HVCMxVC.c revision 1ab64890
1/* $Xorg: HVCMxVC.c,v 1.3 2000/08/17 19:44:37 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.  TekColor is a
9 * trademark of Tektronix, Inc.  The term "TekHVC" designates a particular
10 * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent
11 * foreign patents pending).  Permission is hereby granted to use, copy,
12 * modify, sell, and otherwise distribute this software and its
13 * documentation for any purpose and without fee, provided that:
14 *
15 * 1. This copyright, permission, and disclaimer notice is reproduced in
16 *    all copies of this software and any modification thereof and in
17 *    supporting documentation;
18 * 2. Any color-handling application which displays TekHVC color
19 *    cooordinates identifies these as TekHVC color coordinates in any
20 *    interface that displays these coordinates and in any associated
21 *    documentation;
22 * 3. The term "TekHVC" is always used, and is only used, in association
23 *    with the mathematical derivations of the TekHVC Color Space,
24 *    including those provided in this file and any equivalent pathways and
25 *    mathematical derivations, regardless of digital (e.g., floating point
26 *    or integer) representation.
27 *
28 * Tektronix makes no representation about the suitability of this software
29 * for any purpose.  It is provided "as is" and with all faults.
30 *
31 * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
32 * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
33 * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
34 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
35 * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
36 * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
37 * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
38 *
39 *	NAME
40 *		TekHVCMxVC.c
41 *
42 *	DESCRIPTION
43 *		Source for the XcmsTekHVCQueryMaxVC() gamut boundary
44 *		querying routine.
45 *
46 */
47/* $XFree86$ */
48
49#ifdef HAVE_CONFIG_H
50#include <config.h>
51#endif
52#include "Xlibint.h"
53#include "Xcmsint.h"
54#include "Cv.h"
55
56/*
57 *	DEFINES
58 */
59#define MIN(x,y) ((x) > (y) ? (y) : (x))
60#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x))
61#define MAX(x,y) ((x) > (y) ? (x) : (y))
62#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z))))
63#define START_V	    40.0
64#define START_C	    120.0
65
66
67/************************************************************************
68 *									*
69 *			 API PRIVATE ROUTINES				*
70 *									*
71 ************************************************************************/
72
73/*
74 *	NAME
75 *		_XcmsTekHVCQueryMaxVCRGB - Compute maximum value/chroma.
76 *
77 *	SYNOPSIS
78 */
79Status
80_XcmsTekHVCQueryMaxVCRGB(
81    XcmsCCC	ccc,
82    XcmsFloat	hue,
83    XcmsColor   *pColor_return,
84    XcmsRGBi    *pRGB_return)
85
86/*
87 *	DESCRIPTION
88 *		Return the maximum chroma for a specified hue, and the
89 *		corresponding value.  This is computed by a binary search of
90 *		all possible chromas.  An assumption is made that there are
91 *		no local maxima.  Use the unrounded Max Chroma because
92 *		the difference check can be small.
93 *
94 *		NOTE:  No local CCC is used because this is a private
95 *		       routine and all routines that call it are expected
96 *		       to behave properly, i.e. send a local CCC with
97 *		       no white adjust function and no gamut compression
98 *		       function.
99 *
100 *		This routine only accepts hue as input and outputs
101 *		HVC's and RGBi's.
102 *
103 *	RETURNS
104 *		XcmsFailure - Failure
105 *		XCMS_SUCCUSS - Succeeded
106 *
107 */
108{
109    XcmsFloat nSmall, nLarge;
110    XcmsColor tmp;
111
112    tmp.format = XcmsTekHVCFormat;
113    tmp.spec.TekHVC.H = hue;
114    /*  Use some unreachable color on the given hue */
115    tmp.spec.TekHVC.V = START_V;
116    tmp.spec.TekHVC.C = START_C;
117
118
119    /*
120     * Convert from HVC to RGB
121     *
122     * Note that the CIEXYZ to RGBi conversion routine must stuff the
123     * out of bounds RGBi values in tmp when the ccc->gamutCompProc
124     * is NULL.
125     */
126    if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp,
127	    &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsRGBiFormat, (Bool *) NULL)
128	    == XcmsFailure) && tmp.format != XcmsRGBiFormat) {
129	return (XcmsFailure);
130    }
131
132    /* Now pick the smallest RGB */
133    nSmall = MIN3(tmp.spec.RGBi.red,
134		  tmp.spec.RGBi.green,
135		  tmp.spec.RGBi.blue);
136    /* Make the smallest RGB equal to zero */
137    tmp.spec.RGBi.red   -= nSmall;
138    tmp.spec.RGBi.green -= nSmall;
139    tmp.spec.RGBi.blue  -= nSmall;
140
141    /* Now pick the largest RGB */
142    nLarge = MAX3(tmp.spec.RGBi.red,
143		  tmp.spec.RGBi.green,
144		  tmp.spec.RGBi.blue);
145    /* Scale the RGB values based on the largest one */
146    tmp.spec.RGBi.red   /= nLarge;
147    tmp.spec.RGBi.green /= nLarge;
148    tmp.spec.RGBi.blue  /= nLarge;
149    tmp.format = XcmsRGBiFormat;
150
151    /* If the calling routine wants RGB value give them the ones used. */
152    if (pRGB_return) {
153	pRGB_return->red   = tmp.spec.RGBi.red;
154	pRGB_return->green = tmp.spec.RGBi.green;
155	pRGB_return->blue  = tmp.spec.RGBi.blue;
156    }
157
158    /* Convert from RGBi to HVC */
159    if (_XcmsConvertColorsWithWhitePt(ccc, &tmp,
160	    &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, (Bool *) NULL)
161	    == XcmsFailure) {
162	return (XcmsFailure);
163    }
164
165    /* make sure to return the input hue */
166    tmp.spec.TekHVC.H = hue;
167    memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor));
168    return (XcmsSuccess);
169}
170
171
172/************************************************************************
173 *									*
174 *			 PUBLIC ROUTINES				*
175 *									*
176 ************************************************************************/
177
178/*
179 *	NAME
180 *		XcmsTekHVCQueryMaxVC - Compute maximum value and chroma.
181 *
182 *	SYNOPSIS
183 */
184Status
185XcmsTekHVCQueryMaxVC (
186    XcmsCCC ccc,
187    XcmsFloat hue,
188    XcmsColor *pColor_return)
189
190/*
191 *	DESCRIPTION
192 *		Return the maximum chroma for the specified hue, and the
193 *		corresponding value.
194 *
195 *	ASSUMPTIONS
196 *		This routine assumes that the white point associated with
197 *		the color specification is the Screen White Point.  The
198 *		Screen White Point will also be associated with the
199 *		returned color specification.
200 *
201 *	RETURNS
202 *		XcmsFailure - Failure
203 *		XcmsSuccess - Succeeded
204 *
205 */
206{
207    XcmsCCCRec myCCC;
208
209    /*
210     * Check Arguments
211     */
212    if (ccc == NULL || pColor_return == NULL) {
213	return(XcmsFailure);
214    }
215
216    /*
217     * Insure TekHVC installed
218     */
219    if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) {
220	return(XcmsFailure);
221    }
222
223    /* Use my own CCC */
224    memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
225    myCCC.clientWhitePt.format = XcmsUndefinedFormat;
226    myCCC.gamutCompProc = (XcmsCompressionProc)NULL;
227
228    while (hue < 0.0) {
229	hue += 360.0;
230    }
231    while (hue >= 360.0) {
232	hue -= 360.0;
233    }
234
235    return(_XcmsTekHVCQueryMaxVCRGB (&myCCC, hue, pColor_return,
236	    (XcmsRGBi *)NULL));
237}
238