LuvMxLC.c revision b4ee4795
18abac3daSmrg 28abac3daSmrg/* 38abac3daSmrg * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. 48abac3daSmrg * All Rights Reserved 58abac3daSmrg * 68abac3daSmrg * This file is a component of an X Window System-specific implementation 78abac3daSmrg * of XCMS based on the TekColor Color Management System. Permission is 816f0be2fSmaya * hereby granted to use, copy, modify, sell, and otherwise distribute this 98abac3daSmrg * software and its documentation for any purpose and without fee, provided 108abac3daSmrg * that this copyright, permission, and disclaimer notice is reproduced in 118abac3daSmrg * all copies of this software and in supporting documentation. TekColor 128abac3daSmrg * is a trademark of Tektronix, Inc. 138abac3daSmrg * 148abac3daSmrg * Tektronix makes no representation about the suitability of this software 158abac3daSmrg * for any purpose. It is provided "as is" and with all faults. 168abac3daSmrg * 178abac3daSmrg * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, 1874966952Smrg * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 1974966952Smrg * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY 20b6e4ce1fSchristos * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21b6e4ce1fSchristos * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF 2274966952Smrg * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2374966952Smrg * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. 2416f0be2fSmaya * 2516f0be2fSmaya * 2616f0be2fSmaya * 2716f0be2fSmaya * NAME 2816f0be2fSmaya * CIELuvMxVC.c 2974966952Smrg * 3074966952Smrg * DESCRIPTION 3174966952Smrg * Source for the XcmsCIELuvQueryMaxLC() gamut boundary 3274966952Smrg * querying routine. 3374966952Smrg * 3474966952Smrg * DOCUMENTATION 3574966952Smrg * "TekColor Color Management System, System Implementor's Manual" 3674966952Smrg * and 3774966952Smrg * Fred W. Billmeyer & Max Saltzman, "Principles of Color 3874966952Smrg * Technology", John Wily & Sons, Inc, 1981. 3974966952Smrg */ 4074966952Smrg 4174966952Smrg#ifdef HAVE_CONFIG_H 4274966952Smrg#include <config.h> 4374966952Smrg#endif 4474966952Smrg#include "Xlibint.h" 4574966952Smrg#include "Xcmsint.h" 4674966952Smrg#include "Cv.h" 478abac3daSmrg 488abac3daSmrg/* 498abac3daSmrg * DEFINES 508abac3daSmrg */ 518abac3daSmrg#define MIN(x,y) ((x) > (y) ? (y) : (x)) 528abac3daSmrg#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) 538abac3daSmrg#define MAX(x,y) ((x) > (y) ? (x) : (y)) 548abac3daSmrg#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) 558abac3daSmrg#define START_LSTAR (XcmsFloat)40.0 568abac3daSmrg#define START_CHROMA (XcmsFloat)2.2 578abac3daSmrg 588abac3daSmrg 598abac3daSmrg/************************************************************************ 608abac3daSmrg * * 618abac3daSmrg * API PRIVATE ROUTINES * 628abac3daSmrg * * 638abac3daSmrg ************************************************************************/ 648abac3daSmrg 658abac3daSmrg/* 668abac3daSmrg * NAME 678abac3daSmrg * _XcmsCIELuvQueryMaxLCRGB - Compute maximum L* and chroma. 688abac3daSmrg * 698abac3daSmrg * SYNOPSIS 708abac3daSmrg */ 718abac3daSmrgStatus 7274966952Smrg_XcmsCIELuvQueryMaxLCRGB( 7374966952Smrg XcmsCCC ccc, 7474966952Smrg XcmsFloat hue, /* hue in radians */ 7574966952Smrg XcmsColor *pColor_return, 7674966952Smrg XcmsRGBi *pRGB_return) 7774966952Smrg/* 7816f0be2fSmaya * DESCRIPTION 7916f0be2fSmaya * Return the maximum psychometric chroma for a specified 8074966952Smrg * hue angle(radians), and the corresponding L*. This is computed 8174966952Smrg * by a binary search of all possible chromas. An assumption 8274966952Smrg * is made that there are no local maxima. Use the unrounded 8374966952Smrg * Max psychometric chroma because the difference check can be 8474966952Smrg * small. 8574966952Smrg * 8674966952Smrg * NOTE: No local CCC is used because this is a private 8774966952Smrg * routine and all routines that call it are expected 8874966952Smrg * to behave properly, i.e. send a local CCC with 8974966952Smrg * no white adjust function and no gamut compression 9074966952Smrg * function. 9174966952Smrg * 9274966952Smrg * This routine only accepts hue as input and outputs 9374966952Smrg * Luv and RGBi. 9474966952Smrg * 9574966952Smrg * RETURNS 9674966952Smrg * XcmsFailure - Failure 9774966952Smrg * XcmsSuccess - Succeeded 9874966952Smrg * 9974966952Smrg */ 10074966952Smrg{ 10174966952Smrg XcmsFloat nSmall, nLarge; 10274966952Smrg XcmsColor tmp; 10374966952Smrg 10474966952Smrg tmp.format = XcmsCIELuvFormat; 10574966952Smrg /* Use some unreachable color on the given hue angle */ 10674966952Smrg tmp.spec.CIELuv.L_star = START_LSTAR; 10774966952Smrg tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, START_CHROMA); 10874966952Smrg tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, START_CHROMA); 10974966952Smrg /* 11074966952Smrg * Convert from Luv to RGB 11174966952Smrg * 1129676eccbSmrg * Note that the CIEXYZ to RGBi conversion routine must stuff the 113b6e4ce1fSchristos * out of bounds RGBi values in tmp when the ccc->gamutCompProc 11474966952Smrg * is NULL. 11574966952Smrg */ 11674966952Smrg if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp, ScreenWhitePointOfCCC(ccc), 11774966952Smrg (unsigned int)1, XcmsRGBiFormat, (Bool *) NULL) 1189676eccbSmrg == XcmsFailure) && tmp.format != XcmsRGBiFormat) { 11974966952Smrg return (XcmsFailure); 12074966952Smrg } 12174966952Smrg 12274966952Smrg /* Now pick the smallest RGB */ 12374966952Smrg nSmall = MIN3(tmp.spec.RGBi.red, 12474966952Smrg tmp.spec.RGBi.green, 12574966952Smrg tmp.spec.RGBi.blue); 12674966952Smrg /* Make the smallest RGB equal to zero */ 12774966952Smrg tmp.spec.RGBi.red -= nSmall; 12874966952Smrg tmp.spec.RGBi.green -= nSmall; 12974966952Smrg tmp.spec.RGBi.blue -= nSmall; 13074966952Smrg 13174966952Smrg /* Now pick the largest RGB */ 13274966952Smrg nLarge = MAX3(tmp.spec.RGBi.red, 13374966952Smrg tmp.spec.RGBi.green, 1349676eccbSmrg tmp.spec.RGBi.blue); 13574966952Smrg /* Scale the RGB values based on the largest one */ 13674966952Smrg tmp.spec.RGBi.red /= nLarge; 13774966952Smrg tmp.spec.RGBi.green /= nLarge; 13874966952Smrg tmp.spec.RGBi.blue /= nLarge; 13974966952Smrg tmp.format = XcmsRGBiFormat; 14074966952Smrg 14174966952Smrg /* If the calling routine wants RGB value give them the ones used. */ 14274966952Smrg if (pRGB_return) { 14374966952Smrg pRGB_return->red = tmp.spec.RGBi.red; 14474966952Smrg pRGB_return->green = tmp.spec.RGBi.green; 14574966952Smrg pRGB_return->blue = tmp.spec.RGBi.blue; 14674966952Smrg } 14774966952Smrg 14874966952Smrg /* Convert from RGBi to Luv */ 14974966952Smrg if (_XcmsConvertColorsWithWhitePt(ccc, &tmp, 15074966952Smrg ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat, (Bool *) NULL) 15174966952Smrg == XcmsFailure) { 15274966952Smrg return (XcmsFailure); 15374966952Smrg } 15474966952Smrg 15574966952Smrg memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); 15674966952Smrg return (XcmsSuccess); 15774966952Smrg} 15874966952Smrg 15974966952Smrg 16074966952Smrg/************************************************************************ 16174966952Smrg * * 16274966952Smrg * PUBLIC ROUTINES * 16374966952Smrg * * 1649676eccbSmrg ************************************************************************/ 1659676eccbSmrg 1669676eccbSmrg/* 1679676eccbSmrg * NAME 16874966952Smrg * XcmsCIELuvQueryMaxLC - Compute maximum L* and chroma. 16974966952Smrg * 17074966952Smrg * SYNOPSIS 17174966952Smrg */ 17274966952SmrgStatus 17374966952SmrgXcmsCIELuvQueryMaxLC ( 17474966952Smrg XcmsCCC ccc, 17574966952Smrg XcmsFloat hue_angle, /* hue angle in degrees */ 17674966952Smrg XcmsColor *pColor_return) 17774966952Smrg 1789676eccbSmrg/* 17974966952Smrg * DESCRIPTION 1809676eccbSmrg * Return the point of maximum chroma for the specified 18174966952Smrg * hue angle. 18274966952Smrg * 18374966952Smrg * ASSUMPTIONS 18474966952Smrg * This routine assumes that the white point associated with 18574966952Smrg * the color specification is the Screen White Point. The 18674966952Smrg * Screen White Point will also be associated with the 18774966952Smrg * returned color specification. 18874966952Smrg * 18974966952Smrg * RETURNS 19074966952Smrg * XcmsFailure - Failure 19174966952Smrg * XcmsSuccess - Succeeded 19274966952Smrg * 19374966952Smrg */ 19474966952Smrg{ 19574966952Smrg XcmsCCCRec myCCC; 19674966952Smrg 19774966952Smrg /* 19874966952Smrg * Check Arguments 19974966952Smrg */ 20074966952Smrg if (ccc == NULL || pColor_return == NULL) { 20174966952Smrg return(XcmsFailure); 20274966952Smrg } 20374966952Smrg 20474966952Smrg /* Use my own CCC */ 20574966952Smrg memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); 20674966952Smrg myCCC.clientWhitePt.format = XcmsUndefinedFormat; 20774966952Smrg myCCC.gamutCompProc = (XcmsCompressionProc)NULL; 20874966952Smrg 20974966952Smrg while (hue_angle < 0.0) { 21074966952Smrg hue_angle += 360.0; 21174966952Smrg } 21274966952Smrg while (hue_angle >= 360.0) { 21374966952Smrg hue_angle -= 360.0; 21474966952Smrg } 21574966952Smrg 21674966952Smrg return(_XcmsCIELuvQueryMaxLCRGB (&myCCC, radians(hue_angle), pColor_return, 21774966952Smrg (XcmsRGBi *)NULL)); 21874966952Smrg} 21974966952Smrg