11ab64890Smrg 21ab64890Smrg/* 31ab64890Smrg * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. 41ab64890Smrg * All Rights Reserved 561b2299dSmrg * 61ab64890Smrg * This file is a component of an X Window System-specific implementation 71ab64890Smrg * of XCMS based on the TekColor Color Management System. Permission is 81ab64890Smrg * hereby granted to use, copy, modify, sell, and otherwise distribute this 91ab64890Smrg * software and its documentation for any purpose and without fee, provided 101ab64890Smrg * that this copyright, permission, and disclaimer notice is reproduced in 111ab64890Smrg * all copies of this software and in supporting documentation. TekColor 121ab64890Smrg * is a trademark of Tektronix, Inc. 1361b2299dSmrg * 141ab64890Smrg * Tektronix makes no representation about the suitability of this software 151ab64890Smrg * for any purpose. It is provided "as is" and with all faults. 1661b2299dSmrg * 171ab64890Smrg * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, 181ab64890Smrg * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 191ab64890Smrg * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY 201ab64890Smrg * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 211ab64890Smrg * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF 221ab64890Smrg * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 231ab64890Smrg * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. 241ab64890Smrg * 251ab64890Smrg * 261ab64890Smrg * 271ab64890Smrg * NAME 281ab64890Smrg * CIELuvMxVC.c 291ab64890Smrg * 301ab64890Smrg * DESCRIPTION 311ab64890Smrg * Source for the XcmsCIELuvQueryMaxLC() gamut boundary 321ab64890Smrg * querying routine. 331ab64890Smrg * 341ab64890Smrg * DOCUMENTATION 351ab64890Smrg * "TekColor Color Management System, System Implementor's Manual" 361ab64890Smrg * and 371ab64890Smrg * Fred W. Billmeyer & Max Saltzman, "Principles of Color 381ab64890Smrg * Technology", John Wily & Sons, Inc, 1981. 391ab64890Smrg */ 401ab64890Smrg 411ab64890Smrg#ifdef HAVE_CONFIG_H 421ab64890Smrg#include <config.h> 431ab64890Smrg#endif 441ab64890Smrg#include "Xlibint.h" 451ab64890Smrg#include "Xcmsint.h" 461ab64890Smrg#include "Cv.h" 471ab64890Smrg 481ab64890Smrg/* 491ab64890Smrg * DEFINES 501ab64890Smrg */ 511ab64890Smrg#define MIN(x,y) ((x) > (y) ? (y) : (x)) 521ab64890Smrg#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x)) 531ab64890Smrg#define MAX(x,y) ((x) > (y) ? (x) : (y)) 541ab64890Smrg#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z)))) 551ab64890Smrg#define START_LSTAR (XcmsFloat)40.0 561ab64890Smrg#define START_CHROMA (XcmsFloat)2.2 571ab64890Smrg 581ab64890Smrg 591ab64890Smrg/************************************************************************ 601ab64890Smrg * * 611ab64890Smrg * API PRIVATE ROUTINES * 621ab64890Smrg * * 631ab64890Smrg ************************************************************************/ 641ab64890Smrg 651ab64890Smrg/* 661ab64890Smrg * NAME 671ab64890Smrg * _XcmsCIELuvQueryMaxLCRGB - Compute maximum L* and chroma. 681ab64890Smrg * 691ab64890Smrg * SYNOPSIS 701ab64890Smrg */ 711ab64890SmrgStatus 721ab64890Smrg_XcmsCIELuvQueryMaxLCRGB( 731ab64890Smrg XcmsCCC ccc, 741ab64890Smrg XcmsFloat hue, /* hue in radians */ 751ab64890Smrg XcmsColor *pColor_return, 761ab64890Smrg XcmsRGBi *pRGB_return) 771ab64890Smrg/* 781ab64890Smrg * DESCRIPTION 791ab64890Smrg * Return the maximum psychometric chroma for a specified 801ab64890Smrg * hue angle(radians), and the corresponding L*. This is computed 811ab64890Smrg * by a binary search of all possible chromas. An assumption 821ab64890Smrg * is made that there are no local maxima. Use the unrounded 831ab64890Smrg * Max psychometric chroma because the difference check can be 841ab64890Smrg * small. 851ab64890Smrg * 861ab64890Smrg * NOTE: No local CCC is used because this is a private 871ab64890Smrg * routine and all routines that call it are expected 881ab64890Smrg * to behave properly, i.e. send a local CCC with 891ab64890Smrg * no white adjust function and no gamut compression 901ab64890Smrg * function. 911ab64890Smrg * 921ab64890Smrg * This routine only accepts hue as input and outputs 931ab64890Smrg * Luv and RGBi. 941ab64890Smrg * 951ab64890Smrg * RETURNS 961ab64890Smrg * XcmsFailure - Failure 971ab64890Smrg * XcmsSuccess - Succeeded 981ab64890Smrg * 9961b2299dSmrg */ 1001ab64890Smrg{ 1011ab64890Smrg XcmsFloat nSmall, nLarge; 1021ab64890Smrg XcmsColor tmp; 1031ab64890Smrg 1041ab64890Smrg tmp.format = XcmsCIELuvFormat; 1051ab64890Smrg /* Use some unreachable color on the given hue angle */ 1061ab64890Smrg tmp.spec.CIELuv.L_star = START_LSTAR; 1071ab64890Smrg tmp.spec.CIELuv.u_star = XCMS_CIEUSTAROFHUE(hue, START_CHROMA); 1081ab64890Smrg tmp.spec.CIELuv.v_star = XCMS_CIEVSTAROFHUE(hue, START_CHROMA); 1091ab64890Smrg /* 1101ab64890Smrg * Convert from Luv to RGB 1111ab64890Smrg * 1121ab64890Smrg * Note that the CIEXYZ to RGBi conversion routine must stuff the 1131ab64890Smrg * out of bounds RGBi values in tmp when the ccc->gamutCompProc 1141ab64890Smrg * is NULL. 1151ab64890Smrg */ 11661b2299dSmrg if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp, ScreenWhitePointOfCCC(ccc), 11761b2299dSmrg (unsigned int)1, XcmsRGBiFormat, (Bool *) NULL) 1181ab64890Smrg == XcmsFailure) && tmp.format != XcmsRGBiFormat) { 1191ab64890Smrg return (XcmsFailure); 1201ab64890Smrg } 1211ab64890Smrg 1221ab64890Smrg /* Now pick the smallest RGB */ 12361b2299dSmrg nSmall = MIN3(tmp.spec.RGBi.red, 12461b2299dSmrg tmp.spec.RGBi.green, 1251ab64890Smrg tmp.spec.RGBi.blue); 1261ab64890Smrg /* Make the smallest RGB equal to zero */ 1271ab64890Smrg tmp.spec.RGBi.red -= nSmall; 1281ab64890Smrg tmp.spec.RGBi.green -= nSmall; 1291ab64890Smrg tmp.spec.RGBi.blue -= nSmall; 1301ab64890Smrg 1311ab64890Smrg /* Now pick the largest RGB */ 13261b2299dSmrg nLarge = MAX3(tmp.spec.RGBi.red, 13361b2299dSmrg tmp.spec.RGBi.green, 1341ab64890Smrg tmp.spec.RGBi.blue); 1351ab64890Smrg /* Scale the RGB values based on the largest one */ 1361ab64890Smrg tmp.spec.RGBi.red /= nLarge; 1371ab64890Smrg tmp.spec.RGBi.green /= nLarge; 1381ab64890Smrg tmp.spec.RGBi.blue /= nLarge; 1391ab64890Smrg tmp.format = XcmsRGBiFormat; 1401ab64890Smrg 1411ab64890Smrg /* If the calling routine wants RGB value give them the ones used. */ 1421ab64890Smrg if (pRGB_return) { 1431ab64890Smrg pRGB_return->red = tmp.spec.RGBi.red; 1441ab64890Smrg pRGB_return->green = tmp.spec.RGBi.green; 1451ab64890Smrg pRGB_return->blue = tmp.spec.RGBi.blue; 1461ab64890Smrg } 1471ab64890Smrg 1481ab64890Smrg /* Convert from RGBi to Luv */ 1491ab64890Smrg if (_XcmsConvertColorsWithWhitePt(ccc, &tmp, 15061b2299dSmrg ScreenWhitePointOfCCC(ccc), 1, XcmsCIELuvFormat, (Bool *) NULL) 1511ab64890Smrg == XcmsFailure) { 1521ab64890Smrg return (XcmsFailure); 1531ab64890Smrg } 1541ab64890Smrg 1551ab64890Smrg memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor)); 15661b2299dSmrg return (XcmsSuccess); 1571ab64890Smrg} 1581ab64890Smrg 1591ab64890Smrg 1601ab64890Smrg/************************************************************************ 1611ab64890Smrg * * 1621ab64890Smrg * PUBLIC ROUTINES * 1631ab64890Smrg * * 1641ab64890Smrg ************************************************************************/ 1651ab64890Smrg 1661ab64890Smrg/* 1671ab64890Smrg * NAME 1681ab64890Smrg * XcmsCIELuvQueryMaxLC - Compute maximum L* and chroma. 1691ab64890Smrg * 1701ab64890Smrg * SYNOPSIS 1711ab64890Smrg */ 1721ab64890SmrgStatus 1731ab64890SmrgXcmsCIELuvQueryMaxLC ( 1741ab64890Smrg XcmsCCC ccc, 1751ab64890Smrg XcmsFloat hue_angle, /* hue angle in degrees */ 1761ab64890Smrg XcmsColor *pColor_return) 1771ab64890Smrg 1781ab64890Smrg/* 1791ab64890Smrg * DESCRIPTION 1801ab64890Smrg * Return the point of maximum chroma for the specified 1811ab64890Smrg * hue angle. 1821ab64890Smrg * 1831ab64890Smrg * ASSUMPTIONS 1841ab64890Smrg * This routine assumes that the white point associated with 1851ab64890Smrg * the color specification is the Screen White Point. The 1861ab64890Smrg * Screen White Point will also be associated with the 1871ab64890Smrg * returned color specification. 1881ab64890Smrg * 1891ab64890Smrg * RETURNS 1901ab64890Smrg * XcmsFailure - Failure 1911ab64890Smrg * XcmsSuccess - Succeeded 1921ab64890Smrg * 19361b2299dSmrg */ 1941ab64890Smrg{ 1951ab64890Smrg XcmsCCCRec myCCC; 1961ab64890Smrg 1971ab64890Smrg /* 1981ab64890Smrg * Check Arguments 1991ab64890Smrg */ 2001ab64890Smrg if (ccc == NULL || pColor_return == NULL) { 2011ab64890Smrg return(XcmsFailure); 2021ab64890Smrg } 20361b2299dSmrg 2041ab64890Smrg /* Use my own CCC */ 2051ab64890Smrg memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec)); 2061ab64890Smrg myCCC.clientWhitePt.format = XcmsUndefinedFormat; 2071ab64890Smrg myCCC.gamutCompProc = (XcmsCompressionProc)NULL; 2081ab64890Smrg 2091ab64890Smrg while (hue_angle < 0.0) { 2101ab64890Smrg hue_angle += 360.0; 2111ab64890Smrg } 2121ab64890Smrg while (hue_angle >= 360.0) { 2131ab64890Smrg hue_angle -= 360.0; 21461b2299dSmrg } 21561b2299dSmrg 2161ab64890Smrg return(_XcmsCIELuvQueryMaxLCRGB (&myCCC, radians(hue_angle), pColor_return, 2171ab64890Smrg (XcmsRGBi *)NULL)); 2181ab64890Smrg} 219