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